void  doReadThread (void* arg)
{
  PRInt32 last;
  Arg_t *args = (Arg_t*)arg;
  PRInt32 aWorkDelay = args->a, aWaitDelay = args->b;
  PR_Sleep(0);

  while (1)
  {
    // -- enter read lock
    PR_EnterMonitor (gMonitor); 

    if (0 < gWriteWaiting)  // give up the monitor to waiting writes
    {
      PRIntervalTime fiveSecs = PR_SecondsToInterval(5);

      gReadWaiting++;
      if (gReadWaiting > gMaxReadWaits) // stats
        gMaxReadWaits = gReadWaiting;
      while (0 < gWriteWaiting)
        PR_Wait (gMonitor, fiveSecs);
      gReadWaiting--;
    }

    gReading++;

    gReads++;   // stats
    if (gReading > gMaxReads) // stats
      gMaxReads = gReading;

    PR_ExitMonitor (gMonitor);
    // -- read lock entered

    last = gCounter;

    spin (aWorkDelay);

    PR_ASSERT (gCounter == last); // test invariance

    // -- exit read lock
    PR_EnterMonitor (gMonitor);  // read unlock
    gReading--;

//    if ((0 == gReading) && (0 < gWriteWaiting))  // notify waiting writes  (do it anyway to show off the CondWait bug)
      PR_NotifyAll (gMonitor);
    PR_ExitMonitor (gMonitor);
    // -- read lock exited

    spin (aWaitDelay);
  }
}
void  doWriteThread (void* arg)
{
  PRInt32 last;
  Arg_t *args = (Arg_t*)arg;
  PRInt32 aWorkDelay = args->a, aWaitDelay = args->b;
  PR_Sleep(0);

  while (1)
  {
    // -- enter write lock
    PR_EnterMonitor (gMonitor);

    if (0 < gReading)     // wait for read locks to go away
    {
      PRIntervalTime fiveSecs = PR_SecondsToInterval(5);

      gWriteWaiting++;
      if (gWriteWaiting > gMaxWriteWaits) // stats
        gMaxWriteWaits = gWriteWaiting;
      while (0 < gReading)
        PR_Wait (gMonitor, fiveSecs);
      gWriteWaiting--;
    }
    // -- write lock entered

    last = gCounter;
    gCounter++;

    spin (aWorkDelay);

    PR_ASSERT (gCounter == (last + 1)); // test invariance

    // -- exit write lock        
//    if (0 < gReadWaiting)   // notify waiting reads (do it anyway to show off the CondWait bug)
      PR_NotifyAll (gMonitor);

    PR_ExitMonitor (gMonitor);
    // -- write lock exited

    spin (aWaitDelay);
  }
}
JD_METHOD_(JDBool) CNSAdapter_NSPR::JD_NotifyAll(void* mon)
{
  return PR_NotifyAll((PRMonitor*)mon);
}