/* Tests that a thread returns from desch() only after being mkrun()'d */
int
main(void)
{
  int i, child;
  char *stack;

  TEST_STRT(ITERATIONS);

  for(i = 0; i < ITERATIONS; i++) {
    stack = malloc(STACKSZ);
    TEST_EXIT_IF(stack == 0, "malloc failed");
    stack += STACKSZ; // Must give pointer to top of the stack

    child = tspawn(stack, thread_func, (void *) i);

    TEST_EXIT_IF(child < 0, "tspawn failed");

    sleep(64); // #YOLOMAGICNUMBER
    has_mkran[i] = 1; // inform child they have actually been awoken
    TEST_EXIT_IF(mkrun(child) < 0, "mkrun failed");

    // #YOLOLEAK because we have no uthr_join
    // and we can't free until texit()
    // free(stack);
  }

  texit();
}
int main() {
  int i, pid;
  void *s;
  int guard = 1;
  TEST_STRT(1);
  TEST_DIAG("WARNING: this test will fail if run with more than two existing processes");
  int parent_pid = getpid();
  pid = fork();
  TEST_EXIT_IF(pid < 0, "Fork failed.\n");
  if (pid == 0) {
     for(i = 0; i < LOTS; i++) {
        TEST_DIAG("spawned %d", i + 5);
        TEST_EXIT_IF((s = malloc(STKSIZE)) == 0, "oom");
        s += STKSIZE;
        TEST_EXIT_IF(tspawn(s, spawnee, (void *) parent_pid) < 0, 
          "spawn fail before full at i=%d", i);
     }
     // inherently racy - if mkrun happens before desch, we'll never wake up
     // not too likely, esp since every thread is yielding to the parent
     mkrun(parent_pid);
     while(1);
  }
  desch(&guard);
  TEST_EXIT_IF(fork() > 0, "Fork succeeded even though there were no "
    "more threads available.");
  kill(pid);
  wait();
  TEST_FINI();
  exit();
}
int
main(void)
{
  TEST_STRT(1);
  TEST_FINI("no panics on boot, shell, or fork/exec. Good job!");

  exit();
}
int main() {
  TEST_STRT(1);

  if(fork() == 0) {
    sleep(10); //Make sure the parent made it to wait();
    texit();
  } else {
    wait();
    TEST_FINI();
  }
  exit();
}
int main() {
 TEST_STRT(2);
 TEST_DIAG("This test may fail due to an unavoidable race condition");
 int f = fork();
 if (f < 0) {
   TEST_EXIT("Fork failed");
 } else if (f == 0) {
   TEST_FINI("child"); /* success 1 */
 } else {
   sleep(20);
   TEST_FINI("parent"); /* success 2 */
 }
 exit();
}
int main() {
    TEST_STRT(2);
    int i;
    int parent_tid = gettid();
    int f = fork();
    if (f < 0) {
        TEST_EXIT("Fork failed");
    } else if (f == 0) {
        for (i = 0; i < 1000; i++) {
            yield(parent_tid);
        }
        TEST_FINI("child"); /* success 1 */
    } else {
        for (i = 0; i < 1000; i++) {
            yield(f);
        }
        TEST_FINI("parent"); /* success 2 */
    }
    exit();
}
int main() {
  int i;
  void *s;
  TEST_STRT(1);
  for (i = 0; i < 10; i++) {
    TEST_EXIT_IF((s = malloc(STKSIZE)) == 0, "oom");
    s += STKSIZE;
    if (i == 0) {
      TEST_EXIT_IF(tspawn(s, baddie, ARG) < 0, 
        "spawn fail at %d", i);
    } else {
      TEST_EXIT_IF(tspawn(s, goodie, ARG) < 0, "spawn fail at %d", i);
    }
    sleep(10);
  }
  TEST_DIAG("You can see the thread being killed well"\
  " before this test finishes.");
  TEST_FINI();
  exit();
}