text: #include "types.h"
  #include "mmu.h"
  #include "param.h"
  #include "proc.h"
  #include "user.h"
  
  #define USE_YIELD
  #define MAX_CHILDREN 32
  #define LARGE_TICKET_COUNT 100000
  #define MAX_YIELDS_FOR_SETUP 100
  
  __attribute__((noreturn))
  void yield_forever() {
      while (1) {
          yield();
      }
  }
  
  __attribute__((noreturn))
  void run_forever() {
      while (1) {
          __asm__("");
      }
  }
  
  int spawn(int tickets) {
      int pid = fork();
      if (pid == 0) {
          setticket(tickets);
          yield();
  #ifdef USE_YIELD
          yield_forever();
  #else
          run_forever();
  #endif
      } else if (pid != -1) {
          return pid;
      } else {
          printf(2, "error in fork\n");
          return -1;
      }
  }
  
  int find_index_of_pid(int *list, int list_size, int pid) {
      for (int i = 0; i < list_size; ++i) {
          if (list[i] == pid)
              return i;
      }
      return -1;
  }
  
  void wait_for_ticket_counts(int num_children, int *pids, int *tickets) {
      for (int yield_count = 0; yield_count < MAX_YIELDS_FOR_SETUP; ++yield_count) {
          yield();
          int done = 1;
          struct processes_info info;
          getprocessinfo(&info);
          for (int i = 0; i < num_children; ++i) {
              int index = find_index_of_pid(info.pids, info.num_processes, pids[i]);
              if (info.tickets[index] != tickets[i]) done = 0;
          }
          if (done)
              break;
      }
  }
  
  int main(int argc, char *argv[])
  {
      if (argc < 3) {
          printf(2, "usage: %s seconds tickets1 tickets2 ... ticketsN\n"
                    "       seconds is the number of time units to run for\n"
                    "       ticketsX is the number of tickets to give to subprocess N\n",
                    argv[0]);
          exit();
      }
      int tickets_for[MAX_CHILDREN];
      int active_pids[MAX_CHILDREN];
      int num_seconds = atoi(argv[1]);
      int num_children = argc - 2;
      if (num_children > MAX_CHILDREN) {
          printf(2, "only up to %d supported\n", MAX_CHILDREN);
          exit();
      }
      /* give us a lot of ticket so we don't get starved */
      setticket(LARGE_TICKET_COUNT);
      for (int i = 0; i < num_children; ++i) {
          int tickets = atoi(argv[i + 2]);
          tickets_for[i] = tickets;
          active_pids[i] = spawn(tickets);
      }
      wait_for_ticket_counts(num_children, active_pids, tickets_for);
      struct processes_info before, after;
      before.num_processes = after.num_processes = -1;
      getprocessinfo(&before);
      sleep(num_seconds);
      getprocessinfo(&after);
      for (int i = 0; i < num_children; ++i) {
          kill(active_pids[i]);
      }
      for (int i = 0; i < num_children; ++i) {
          wait();
      }
      if (before.num_processes >= NPROC || after.num_processes >= NPROC) {
          printf(2, "getprocessesinfo's num_processes is greater than NPROC before parent slept\n");
          return 1;
      }
      if (before.num_processes < 0 || after.num_processes < 0) {
          printf(2, "getprocessesinfo's num_processes is negative -- not changed by syscall?\n");
          return 1;
      }
      printf(1, "TICKETS\tTICKS\n");
      for (int i = 0; i < num_children; ++i) {
          int before_index = find_index_of_pid(before.pids, before.num_processes, active_pids[i]);
          int after_index = find_index_of_pid(after.pids, after.num_processes, active_pids[i]);
          if (before_index == -1)
              printf(2, "child %d did not exist for getprocessesinfo before parent slept\n", i);
          if (after_index == -1)
              printf(2, "child %d did not exist for getprocessesinfo after parent slept\n", i);
          if (before_index == -1 || after_index == -1) {
              printf(1, "%d\t--unknown--\n", tickets_for[i]);
          } else {
              if (before.tickets[before_index] != tickets_for[i]) {
                  printf(2, "child %d had wrong number of tickets in getprocessinfo before parent slept\n", i);
              }
              if (after.tickets[after_index] != tickets_for[i]) {
                  printf(2, "child %d had wrong number of tickets in getprocessinfo after parent slept\n", i);
              }
              printf(1, "%d\t%d\n", tickets_for[i], after.ticks[after_index] - before.ticks[before_index]);
          }
      }
      exit();
  }