>>30

マルチスレッドを実現するならば、task_startup関数は以下のように終了前に別タスクへディスパッチするようにします。
マルチスレッドで無いならば>>30氏の指摘通りにクラッシュしてしまいます。

void task_startup(void)
{
  int task_ret;

  /* ユーザー指示のタスクメイン関数を実行 */
  task_ret = (*g_new_task_main)(g_new_task_arg);

  /* タスクを終了して別タスクへディスパッチ */
  task_exit(task_ret);

  /* ここへは到達しない */
  assert(0);
}

env[0].という書き方は、私の環境のjmp_bufの型定義によるものです。この辺りは各環境に従ってください。