コード例 #1
0
ファイル: sasulock.cpp プロジェクト: leitao/sphde
// Destructor
SasUserLock::~SasUserLock(void)
{
// Unlike SasLock, we do not have to lock the lock object
// itself before destroying it.  The only time it will
// be destroyed is when its containing list is destroyed,
// which, in turn, is destroyed when the SasMasterLock
// object is destroyed.  During SasMasterLock destruction,
// each list is write-locked in its destructor, so there's
// no need to lock any of the lock objects on the list.
#ifdef mylockdebug
  pid_t this_thread = sphdeGetTID();
  pid_t this_task = getpid();
#endif
  spin_lock(&data_lock);
  sem_destroy(&readers_waiting_sem);
  sem_destroy(&writers_waiting_sem);
  if ((total_readers_count == 0) &&
      (readers_waiting == 0) &&
      (writers_waiting == 0))
  {
    return;
  }
  else
  {
    spin_unlock(&data_lock);
#ifdef mylockdebug
    fprintf (stderr, "%s\n", __FUNCTION__);
    fprintf (stderr, " thread[%ld,%ld]\n",
      (long int) this_task, (long int) this_thread);
    fprintf (stderr, " object  = %p\n", this);
#endif
  }
}
コード例 #2
0
ファイル: sphthread_t.c プロジェクト: frediz/sphde
int
timed_basic_test (void)
{
  int rc = 0;

  sphtimer_t timer_freg = sphfastcpufreq ();
  sphtimer_t timer_val = sphgettimer ();
  sphtimer_t before, after;
  double seconds;
  int i, max_cnt;

  max_cnt = 1000000;

  printf ("timed_basic_test Freq=%lld, timer=%lld\n", timer_freg, timer_val);
  before = sphgettimer ();

  for (i = 0; i < max_cnt; i++)
    {
      sphdeGetPID ();
      sphdeGetTID ();
      sphgettimer ();
    }
  after = sphgettimer ();

  seconds = (double) (after - before) / (double) timer_freg;
  printf ("timed_basic_test %d iterations %f seconds\n", max_cnt, seconds);

  return rc;
}
コード例 #3
0
ファイル: sphthread_t.c プロジェクト: frediz/sphde
static void *
tt1 (void *arg)
{
  pid_t th_pid, th_tid;
  char number[160];

#ifdef SPH_THREADINIT_CTOR
  SASThreadSetUp();
#endif
  th_pid = sphFastGetPID ();
  th_tid = sphFastGetTID ();

  sprintf (number, "tt1(%ld): begin[%d,%d]", (long) arg, th_pid, th_tid);
  puts (number);

  if (th_pid != main_pid)
    {
      sprintf (number, "tt1(%ld): sphdeGetPID=%d should be %d",
	       (long) arg, th_pid, main_pid);
      puts (number);
      (void)__sync_fetch_and_add (&thread_rc, (int) 1);
    }

  if (th_tid == main_tid)
    {
      sprintf (number, "tt1(%ld): sphdeGetTID=%d should be %d",
	       (long) arg, th_tid, main_tid);
      puts (number);
      (void)__sync_fetch_and_add (&thread_rc, (int) 1);
    }

  th_pid = sphdeGetPID ();
  th_tid = sphdeGetTID ();

  if (th_pid != main_pid)
    {
      sprintf (number, "tt1(%ld): sphdeGetPID=%d should be %d",
	       (long) arg, th_pid, main_pid);
      puts (number);
      (void)__sync_fetch_and_add (&thread_rc, (int) 1);
    }

  if (th_tid == main_tid)
    {
      sprintf (number, "tt1(%ld): sphdeGetTID=%d should be %d",
	       (long) arg, th_tid, main_tid);
      puts (number);
      (void)__sync_fetch_and_add (&thread_rc, (int) 1);
    }


  sprintf (number, "tt1(%ld): end", (long) arg);
  puts (number);
  return NULL;
}
コード例 #4
0
ファイル: sasulock.cpp プロジェクト: leitao/sphde
boolean_t
SasUserLock::waiters(void)
{
#ifdef mylockdebug
  pid_t this_thread = sphdeGetTID();
  pid_t this_task = getpid();
  fprintf (stderr, "%s\n", __FUNCTION__);
  fprintf (stderr, " thread[%ld,%ld]\n",
    (long int) this_task, (long int) this_thread);
#endif
  if ((readers_waiting) || (writers_waiting))
    return TRUE;
  else
    return FALSE;
}
コード例 #5
0
ファイル: sasulock.cpp プロジェクト: leitao/sphde
void
SasUserLock::thread_sleep (	vm_address_t event,
				sem_t       *sem,
  				spin_lock_t *lock)
{
#ifdef mylockdebug
    pid_t this_thread = sphdeGetTID();
    pid_t this_task = getpid();
    fprintf (stderr, "%s\n", __FUNCTION__);
    fprintf (stderr, "  thread[%ld,%ld] : %p, %p\n",
      (long int) this_task, (long int) this_thread, event, sem);
#endif
    spin_unlock(&data_lock);
    sem_wait(sem);
}
コード例 #6
0
ファイル: sasulock.cpp プロジェクト: leitao/sphde
int
SasUserLock::operator==(vm_address_t addrToLock)
{
#ifdef mylockdebug
    pid_t this_thread = sphdeGetTID();
    pid_t this_task = getpid();
    fprintf (stderr, "%s\n", __FUNCTION__);
    fprintf (stderr, " thread[%ld,%ld]\n",
      (long int) this_task, (long int) this_thread);
    fprintf (stderr, "  input address: %p", addrToLock);
    fprintf (stderr, " | lock object's address: %p\n", address);
#endif
    if (address == addrToLock)
        return TRUE;
    return FALSE;
}
コード例 #7
0
ファイル: sphthread_t.c プロジェクト: frediz/sphde
int
main (int argc, char *argv[])
{
  int rc = 0;

  rc += thread_basic_test (argv[0]);

  main_pid = sphdeGetPID ();
  main_tid = sphdeGetTID ();

  rc += thread_thread_test ();

  rc += timer_basic_test ();

  rc += timed_basic_test ();

  return rc;
}
コード例 #8
0
ファイル: sasulock.cpp プロジェクト: leitao/sphde
void
SasUserLock::thread_wakeup(	vm_address_t event,
				sem_t       *sem,
  				boolean_t wake_one)
{
    int	waiters = wake_one ? 1 : *(int*)event;
    int i;

#ifdef mylockdebug
    pid_t this_thread = sphdeGetTID();
    pid_t this_task = getpid();
    fprintf (stderr, "%s\n", __FUNCTION__);
    fprintf (stderr, "  thread[%ld,%ld] : %p %i\n",
      (long int) this_task, (long int) this_thread, event, waiters);
#endif

    for ( i = 0; i < waiters; i++ )
	sem_post(sem);
}
コード例 #9
0
ファイル: sasulock.cpp プロジェクト: leitao/sphde
void
SasUserLock::unlock(void)
{
  pid_t this_thread = sphdeGetTID();
  pid_t this_task = getpid();
#ifdef mylockdebug
  fprintf (stderr, "%s\n", __FUNCTION__);
  fprintf (stderr, " thread[%ld,%ld]\n",
    (long int) this_task, (long int) this_thread);
  fprintf (stderr, " object  = %p\n", this);
#endif
  boolean_t	wakeup_writers = FALSE;
  boolean_t	wakeup_readers = FALSE;
  // mach_thread_self() is a ukernel call so let's
  // issue it only once in this routine.  This is
  // a local automatic variable so it is also
  // thread-safe...
  spin_lock(&data_lock);

  // if there are any readers, then no write locks,
  // so unlock a read lock
  if (total_readers_count)
  {
    total_readers_count--;
// Zero-out the address datamember to indicate the lock object
// is available for use.
    if (total_readers_count==0)
	address = NullAddress;

#ifdef coherenceCheck
    if (total_readers_count < 0)
    {
      fprintf (stderr, "%s\n", __FUNCTION__);
      fprintf (stderr, " thread[%ld,%ld] - total readers count is negative: %i\n",
        (long int) this_task, (long int) this_thread,
        total_readers_count);
    }
#endif
    if ((total_readers_count==0) && (writers_waiting))
      wakeup_writers = TRUE;
    // unlock the reader that has it
    for (int i = 0; i < MAX_READER_THREADS; i++)
    {
      if ((readers[i].reader_thread_id ==
           this_thread) &&
          (readers[i].reader_task_id ==
           this_task))
      {
        readers[i].reader_thread_lock_count--;
#ifdef coherenceCheck
        if (readers[i].reader_thread_lock_count < 0)
        {
          fprintf (stderr, "%s\n", __FUNCTION__);
          fprintf (stderr, " thread[%ld,%ld] - lock count just went negative %i\n",
            (long int) this_task, (long int) this_thread,
            readers[i].reader_thread_lock_count);
        }
#endif
#ifdef mylockdebug
        fprintf (stderr, "%s\n", __FUNCTION__);
        fprintf (stderr, " thread[%ld,%ld]\n",
          (long int) this_task, (long int) this_thread);
        fprintf (stderr, " object  = %p | read thread count = %i\n",
          this, readers[i].reader_thread_lock_count);
#endif
        if (readers[i].reader_thread_lock_count == 0)
        {
          // remove the thread id
          readers[i].reader_thread_id = 0;
          readers[i].reader_task_id = 0;
        }
      }
    } // end for loop

  }     // end readers were waiting
  else
  {
    if (status == SasUserLock__exclusive)	// unlock a write lock
    {
      writer_thread_lock_count--;
#ifdef coherenceCheck
      if (writer_thread_lock_count < 0)
      {
        fprintf (stderr, "%s\n", __FUNCTION__);
        fprintf (stderr, " thread[%ld,%ld] - write lock count is negative %i\n",
          (long int) this_task, (long int) this_thread,
          writer_thread_lock_count);
      }
#endif
      if (writer_thread_lock_count)
      {
#ifdef mylockdebug
        fprintf (stderr, "%s\n", __FUNCTION__);
        fprintf (stderr, " thread[%ld,%ld]\n",
          (long int) this_task, (long int) this_thread);
        fprintf (stderr, " object  = %p | writer count = %i\n",
          this, writer_thread_lock_count);
#endif
        spin_unlock(&data_lock);
        return;
      }
      // Zero-out the address datamember to indicate the lock object
      // is available for use.
      address = NullAddress;

      writer_thread_id = 0;
      writer_task_id = 0;
      status = SasUserLock__not_exclusive;

      if (writers_waiting)
        wakeup_writers = TRUE;

      if (readers_waiting)
        wakeup_readers = TRUE;

    }       // end status==lock_exclusive (a write lock)
    else	// change this to coherency check later
    {
#ifdef coherenceCheck
      fprintf (stderr, "%s\n", __FUNCTION__);
      fprintf (stderr, " thread[%ld,%ld]\n",
        (long int) this_task, (long int) this_thread);
      fprintf (stderr, " object  = %p | writer count = %i | reader count = %i\n",
        this, writer_thread_lock_count, total_readers_count);
#endif
      spin_unlock(&data_lock);
      return;
    }
#ifdef mylockdebug
    fprintf (stderr, "%s\n", __FUNCTION__);
    fprintf (stderr, " thread[%ld,%ld]\n",
      (long int) this_task, (long int) this_thread);
    fprintf (stderr, " object  = %p | write count = %i\n",
      this, writer_thread_lock_count);
#endif

  } // end else no readers waiting
  spin_unlock(&data_lock);

  if (wakeup_writers)
  {
    SasUserLock::thread_wakeup(	(vm_address_t)&writers_waiting,
				&writers_waiting_sem, WAKE_ONE);
  }
  if (wakeup_readers)
  {
    SasUserLock::thread_wakeup(	(vm_address_t)&readers_waiting,
				&readers_waiting_sem, WAKE_ALL);
  }
}
コード例 #10
0
ファイル: sasulock.cpp プロジェクト: leitao/sphde
// Get non-shared write lock.  A thread can call this more than once.
// The lock count will be increamented.  In a thread you must
// unlock as many times as you lock.
// The lockObj pointer passed in allows us to release the
// lock on the list on which this SasUserLock object resides
// (see SasLockList class).
void
SasUserLock::write_lock(SasUserLock * lockObj, vm_address_t lockAddr)
{
  // mach_thread_self() is a ukernel call so let's
  // isue it only once in this routine.  This is
  // a local automatic variable so it is also
  // thread-safe...
  pid_t this_thread = sphdeGetTID();
  pid_t this_task = getpid();
#ifdef mylockdebug
  fprintf (stderr, "%s\n", __FUNCTION__);
  fprintf (stderr, " thread[%ld,%ld] - attempt\n",
    (long int) this_task, (long int) this_thread);
  fprintf (stderr, " object  = %p\n", this);
#endif

  boolean_t	wakeup_writers = FALSE;
  boolean_t	wakeup_readers = FALSE;
  spin_lock(&data_lock);

// OK--now that we've got the spin lock, we must check if we need
// to unlock another lock object.  If the caller did not
// specify a lock object, then by default, lockObj is set = NULL,
// so there's nothing to do.
  if (lockObj != NULL)
      lockObj->unlock();


  // if this thread already has the the write lock
  // then inc count and return
  if ((writer_thread_id == this_thread) &&
      (writer_task_id == this_task))
  {
    writer_thread_lock_count++;
#ifdef mylockdebug
    fprintf (stderr, "%s\n", __FUNCTION__);
    fprintf (stderr, " thread[%ld,%ld] - obtained\n",
    (long int) this_task, (long int) this_thread);
    fprintf (stderr, " object  = %p | count = %i\n",
      this, writer_thread_lock_count);
#endif
#ifdef collectstats
    ++useageCount;
#endif
    address = lockAddr;
    spin_unlock(&data_lock);
    return;
  }

  // wait until the other write lock is released
  while (status == SasUserLock__exclusive)
  {
    writers_waiting++;

    SasUserLock::thread_sleep(	(vm_address_t)&writers_waiting,
				&writers_waiting_sem, &data_lock);

    spin_lock(&data_lock);	// relock since sleep does an unlock
    if (writers_waiting)
      writers_waiting--;
  } // while

  // mark status so other threads can not aquire NEW read locks
  status = SasUserLock__exclusive;

  // now wait until all other users get done
  if (writers_waiting)
    wakeup_writers = TRUE;
  if (readers_waiting)
    wakeup_readers = TRUE;

  spin_unlock(&data_lock);

  // use local variables outside of spin lock
  if (wakeup_writers)
  {
    SasUserLock::thread_wakeup(	(vm_address_t)&writers_waiting,
				&writers_waiting_sem, WAKE_ONE);
  }

  if (wakeup_readers)
  {
    SasUserLock::thread_wakeup(	(vm_address_t)&readers_waiting,
				&readers_waiting_sem, WAKE_ALL);
  }

  spin_lock(&data_lock);
  // while still being used by the readers
  while (total_readers_count)
  {
    // look like a writer so that the unlock code wakes us up.
    writers_waiting++;

    SasUserLock::thread_sleep(	(vm_address_t)&writers_waiting,
				&writers_waiting_sem, &data_lock);

    spin_lock(&data_lock);
    if (writers_waiting)
      writers_waiting--;
  }
  // no more readers, so we now have the write lock

#ifdef coherenceCheck
  if (writer_thread_lock_count != 0)
    {
      fprintf (stderr, "%s\n", __FUNCTION__);
      fprintf (stderr, " thread[%ld,%ld] - just obtained write lock and "
        "writer lock count was not zero but was %i\n",
        (long int) this_task, (long int) this_thread,
        writer_thread_lock_count);
    }
#endif

#ifdef mylockdebug
  fprintf (stderr, "%s\n", __FUNCTION__);
  fprintf (stderr, " thread[%ld,%ld] - obtained\n",
    (long int) this_task, (long int) this_thread);
  fprintf (stderr, " object  = %p\n", this);
#endif
#ifdef collectstats
  ++useageCount;
#endif
  address = lockAddr;
  writer_thread_id = this_thread;
  writer_task_id = this_task;
  writer_thread_lock_count = 1;
  spin_unlock(&data_lock);
}
コード例 #11
0
ファイル: sasulock.cpp プロジェクト: leitao/sphde
// Get a shared read lock.  Many threads can have a read lock.
// While read locks are held no write lock will be granted.
// The lockObj pointer passed in allows us to release the
// lock on the list on which this SasUserLock object resides
// (see SasLockList class).
void
SasUserLock::read_lock(SasUserLock * lockObj, vm_address_t lockAddr)
{
  // mach_thread_self() is a ukernel call so let's
  // isue it only once in this routine.  This is
  // a local automatic variable so it is also
  // thread-safe...
  pid_t this_thread = sphdeGetTID();
  pid_t this_task = getpid();
#ifdef mylockdebug
  fprintf (stderr, "%s\n", __FUNCTION__);
  fprintf (stderr, " thread[%ld,%ld] - beggining attempt to lock",
      (long int) this_task, (long int) this_thread);
  fprintf (stderr, " object = %p\n", this);
#endif

  spin_lock(&data_lock);
// OK--now that we've got the spin lock, we must check if we need
// to unlock the SasLockList lock.  If the caller did not
// specify a lock object, then by default, lockObj is set = NULL.
// So, if lockObj == NULL, that implies the user did not pass in
// a lock object for their SasLockList and therefore, do not need us
// to unlock it.
  if (lockObj != NULL)
      lockObj->unlock();


  // if this thread already has a write lock then
  // just inc write lock count and return
  if ((writer_thread_id == this_thread) &&
      (writer_task_id == this_task))
  {
    writer_thread_lock_count++;
#ifdef mylockdebug
    fprintf (stderr, "%s\n", __FUNCTION__);
    fprintf (stderr, " thread[%ld,%ld] - lock obtained",
      (long int) this_task, (long int) this_thread);
    fprintf (stderr, " | object = %p", this);
    fprintf (stderr, " | writer thread count = %i\n",
      writer_thread_lock_count);
#endif
#ifdef collectstats
    ++useageCount;
#endif
    address = lockAddr;
    spin_unlock(&data_lock);
    return;
  }

  // Since here, this thread does NOT have a write lock.
  // It may however, already have a read lock.  If it
  // does, we want to let it get it again and get out.
  // If it does not, then we may or may not give it the
  // lock.  If a writer thread is waiting for the lock
  // we will not allow any new readers.  And of course,
  // if a writer thread had the lock, we obviously will
  // not give this thread the lock now.
  // So, first scan to see if this thread has a
  // read lock already.  Note that we still have
  // the spin lock.
  if (total_readers_count)
  { // only scan if there ARE readers
    for (int i = 0; i < MAX_READER_THREADS; i++)
    {
      if ((readers[i].reader_thread_id == this_thread) &&
          (readers[i].reader_task_id == this_task))
      {
        // this thread already has a read lock
        readers[i].reader_thread_lock_count++;
        total_readers_count++;
#ifdef mylockdebug
        fprintf (stderr, "%s\n", __FUNCTION__);
        fprintf (stderr, " thread[%ld,%ld] - lock obtained",
          (long int) this_task, (long int) this_thread);
        fprintf (stderr, " | object = %p", this);
        fprintf (stderr, " | reader count = %i", readers[i].reader_thread_lock_count);
        fprintf (stderr, " | total reader count = %i\n", total_readers_count);
#endif
#ifdef collectstats
	++useageCount;
#endif
	address = lockAddr;
        spin_unlock(&data_lock);
        return;
      }
    }  // end scan for has reader lock already
  }    // end if(total_readers_count)

  // wait until all the writers are done.
  while (status == SasUserLock__exclusive || writers_waiting)
    {
      readers_waiting++;

      SasUserLock::thread_sleep((vm_address_t)&readers_waiting,
				&readers_waiting_sem, &data_lock);

      spin_lock(&data_lock);	// need to relock since above unlocks
      if (readers_waiting)
          readers_waiting--;

    } // while

  // Ok, we have the spin lock here, AND
  // we have no exclusive or writer waiting flags
  // so this means WE GET THE LOCK.  We need
  // to track WHO we are so add it to the
  // list of reader locks.
  for (int j = 0; j < MAX_READER_THREADS; j++)
    {
      if (readers[j].reader_thread_lock_count > 0)
        {
          // not an open slot
#ifdef coherenceCheck
          if ((readers[j].reader_thread_id == this_thread) &&
              (readers[j].reader_task_id == this_task))
            {
              // should never already be in the table here.
              fprintf (stderr, "%s\n", __FUNCTION__);
              fprintf (stderr, " thread[%ld,%ld] - thread is already in",
                (long int) this_task, (long int) this_thread);
              fprintf (stderr, "the table with %d read thread lock count\n",
                total_readers_count++);
              // guess if this happens we will
              // just give it to him...
              readers[j].reader_thread_lock_count++;
              total_readers_count++;
            }
#endif
        }
      else
        {
          // an open slot - use it
#ifdef coherenceCheck
          if (readers[j].reader_thread_lock_count < 0)
            {
              fprintf (stderr, "%s\n", __FUNCTION__);
              fprintf (stderr, " thread[%ld,%ld] - reader thread count is "
                               "negative %i\n",
                (long int) this_task, (long int) this_thread,
                readers[j].reader_thread_lock_count);
            }
#endif
          readers[j].reader_thread_id =
            this_thread;
          readers[j].reader_task_id = this_task;
          readers[j].reader_thread_lock_count = 1;
          total_readers_count++;

#ifdef mylockdebug
          fprintf (stderr, "%s\n", __FUNCTION__);
          fprintf (stderr, " thread[%ld,%ld] - lock obtained\n",
            (long int) this_task, (long int) this_thread);
          fprintf (stderr, " object  = %p", this);
          fprintf (stderr, " | reader thread count = %i",
            readers[j].reader_thread_lock_count);
          fprintf (stderr, " | total readers count = %i\n",
            total_readers_count);
#endif
#ifdef collectstats
	  ++useageCount;
#endif
	  address = lockAddr;
          spin_unlock(&data_lock);
          return;
        }  // end open slot in table
    }   // end for loop looking for a slot

  // if we get here, we still have the spin lock,
  // and we did not find a slot to use.  I can't
  // readily hang this thread, but I CAN hang onto
  // the spin lock so that all other threads will
  // lock up.  Oughta notice that.  Thus,
  // I intentionally didn't release the spin lock
  // here.
#ifdef mylockdebug
  fprintf (stderr, "%s\n", __FUNCTION__);
  fprintf (stderr, " thread[%ld,%ld] - no opne slots in reader table\n",
    (long int) this_task, (long int) this_thread);
#endif
}
コード例 #12
0
ファイル: sphthread_t.c プロジェクト: frediz/sphde
int
thread_basic_test (const char *argv0)
{
  int rc = 0;
  pid_t pid, pid2, pid3;
  pid_t tid, tid2, tid3;
  char *cl;

  pid = sphdeGetPID ();
  tid = sphdeGetTID ();

  if ((pid != 0) && (tid != 0) && (pid == tid))
    {
      printf ("thread_basic_test PID=%d, TID=%d\n", pid, tid);
    }
  else
    {
      printf ("thread_basic_test failed sphdeGetPID=%d, sphdeGetTID=%d\n",
	      pid, tid);
      rc++;
    }

  cl = sphdeGetCmdLine ();
  if ((cl != NULL) && (*cl != 0))
    {
      printf ("thread_basic_test sphdeGetCmdLine=%s\n", cl);
      if (0 != strcmp (cl, argv0))
	{
	  printf
	    ("thread_basic_test failed sphdeGetCmdLine=%s != ./sphthread_t\n",
	     cl);
	  rc++;
	}
    }
  else
    {
      printf ("thread_basic_test failed sphdeGetCmdLine=%s\n", cl);
      rc++;
    }

  pid2 = sphdeGetPID ();
  tid2 = sphdeGetTID ();

  if ((pid2 != 0) && (tid2 != 0) && (pid2 == tid2))
    {
      printf ("thread_basic_test PID=%d, TID=%d\n", pid2, tid2);
      if ((pid != pid2) || (tid != tid2))
	{
	  printf ("thread_basic_test failed PID %d != %d, TID %d != %d\n",
		  pid, pid2, tid, tid2);
	}
    }
  else
    {
      printf ("thread_basic_test failed sphdeGetPID=%d, sphdeGetTID=%d\n",
	      pid2, tid2);
      rc++;
    }

  pid3 = sphFastGetPID ();
  tid3 = sphFastGetTID ();

  if ((pid3 != 0) && (tid3 != 0) && (pid3 == tid3))
    {
      printf ("thread_basic_test fast PID=%d, TID=%d\n", pid3, tid3);
      if ((pid != pid3) || (tid != tid3))
	{
	  printf
	    ("thread_basic_test fast failed PID %d != %d, TID %d != %d\n",
	     pid, pid3, tid, tid3);
	}
    }
  else
    {
      printf ("thread_basic_test failed sphFastGetPID=%d, sphFastGetTID=%d\n",
	      pid3, tid3);
      rc++;
    }

  return rc;
}