// Here's a sample kernel C code snippet.  It could be used by parts of the
// kernel which create new processes, and need to assign a process ID (PID)
// to a new process/task.  There are several serious bugs and some smaller
// problems in this code.  Identify them as best you can.  You may sketch
// out new code below.

// WORST bug: lack of synchronization/locking for this data structure!
#define MAX 1024
int process_list[MAX]; // how is this initialized? at boot time.
int get_new_process_id(void)
{
  int i;
  lock_t L;

  lock(L);
  for (i=0; i<MAX; i++) { //  "i<=MAX" causes a buf overflow
    if (process_list[i]==0) { // use "==" not "="!
      process_list[i]=1;
      unlock(L);
      return(i);
    }
  }
  // implicit return, if I get here, the lock could be HELD!  So anyone else
  // trying to grab this lock, will deadlock!
  unlock(L);
  // need a proper return value here IF no free slot found
  return(-1); // don't return 0, b/c that is a valid slot #
}

// efficiency issues

// 1. always searching from start, and low PID numbers are more likely to be
// in use.  Instead, maybe keep a "last used" PID, and start searching from
// there, but then you'll have to remember to "cycle back" from 0, and check
// from there, if got to the end of the array.  It's possible that a low-PID
// process ended, and freed up a slot.

// 2. we're waiting a 32-bit integer, to record essentially a single bit
// (slot is used or unused).  Better: decide a compact bitmap for all the
// processes you need to allocate.  You're waiting 32x the kernel RAM you
// need.
