Beispiel #1
0
/*===========================================================================*
 *				key_a					     *
 *===========================================================================*/
static void *key_a(void *arg)
{
  int i;

  if (!first) mthread_yield();

  /* Each new threads gets NULL-initialized values. */
  for (i = 0; i < 5; i++)
	if (mthread_getspecific(key[i]) != NULL) err(17, 1);

  /* Make sure that the local values persist despite other threads' actions. */
  for (i = 1; i < 5; i++)
	if (mthread_setspecific(key[i], (void *) i) != 0) err(17, 2);

  mthread_yield();

  for (i = 1; i < 5; i++)
	if (mthread_getspecific(key[i]) != (void *) i) err(17, 3);

  mthread_yield();

  /* The other thread has deleted this key by now. */
  if (mthread_setspecific(key[3], NULL) != EINVAL) err(17, 4);

  /* If a key's value is set to NULL, its destructor must not be called. */
  if (mthread_setspecific(key[4], NULL) != 0) err(17, 5);
  return(NULL);
}
Beispiel #2
0
/*===========================================================================*
 *				mutex_b					     *
 *===========================================================================*/
static void *mutex_b(void *arg)
{
  mutex_t *mu = (mutex_t *) arg;

  /* At this point mutex_a thread should have acquired a lock on mu[0]. We
   * should not be able to unlock it on behalf of that thread.
   */

  VERIFY_MUTEX(1, 0, 0, 4, 1);
  if (mthread_mutex_unlock(&mu[0]) != EPERM) err(4, 2);

  /* Probing mu[0] to lock it should tell us it's locked */
  if (mthread_mutex_trylock(&mu[0]) != EBUSY) err(4, 4);

  if (mthread_mutex_lock(&mu[0]) != 0) err(4, 5);
  mutex_b_step = 1;
  VERIFY_MUTEX(2, 1, 0, 4, 6);
  if (mthread_mutex_lock(&mu[1]) != 0) err(4, 6);
  mutex_b_step = 2;
  VERIFY_MUTEX(3, 2, 2, 4, 7);
  mthread_yield();
  VERIFY_MUTEX(3, 2, 2, 4, 8);

  if (mthread_mutex_unlock(&mu[0]) != 0) err(4, 7);
  mutex_b_step = 3;
  mthread_yield();

  if (mthread_mutex_unlock(&mu[1]) != 0) err(4, 8);
  mutex_b_step = 4;
  return(NULL);
}
Beispiel #3
0
/*===========================================================================*
 *				rwlock_a				     *
 *===========================================================================*/
static void *rwlock_a(void *arg)
{
  /* acquire read lock */
  VERIFY_RWLOCK(0, 0, 24, 1);
  if (mthread_rwlock_rdlock(&rwlock) != 0) err(24, 2);
  rwlock_a_step = 1;
  mthread_yield();

  /* release read lock */
  VERIFY_RWLOCK(1, 1, 24, 3);
  if (mthread_rwlock_unlock(&rwlock) != 0) err(24, 4);
  rwlock_a_step = 2;

  /* get write lock */
  if (mthread_rwlock_wrlock(&rwlock) != 0) err(24, 5);
  rwlock_a_step = 3;
  VERIFY_RWLOCK(3, 2, 24, 6);

  /* release write lock */
  if (mthread_rwlock_unlock(&rwlock) != 0) err(24, 7);
  mthread_yield();

  VERIFY_RWLOCK(3, 3, 24, 8);

  return(NULL);
}
Beispiel #4
0
/*===========================================================================*
 *				mutex_a					     *
 *===========================================================================*/
static void *mutex_a(void *arg)
{
  mutex_t *mu = (mutex_t *) arg;

  VERIFY_MUTEX(0, 0, 0, 3, 1);
  if (mthread_mutex_lock(&mu[0]) != 0) err(3, 2);

  /* Trying to acquire lock again should fail with EDEADLK */
  if (mthread_mutex_lock(&mu[0]) != EDEADLK) err(3, 2);
  
#ifdef MTHREAD_STRICT 
  /* Try to acquire lock on uninitialized mutex; should fail with EINVAL */
  /* Note: this check only works when libmthread is compiled with
   * MTHREAD_STRICT turned on. In POSIX this situation is a MAY fail if... */
  if (mthread_mutex_lock(&mu2) != EINVAL) {
  	err(3, 4);
  	mthread_mutex_unlock(&mu2);
  }

  if (mthread_mutex_trylock(&mu2) != EINVAL) {
  	err(3, 6);
  	mthread_mutex_unlock(&mu2);
  }
#endif

  if (mthread_mutex_trylock(&mu[1]) != 0) err(3, 8);
  mutex_a_step = 1;
  mthread_yield();
  VERIFY_MUTEX(1, 0, 0, 3, 9);
  if (mthread_mutex_trylock(&mu[2]) != EBUSY) err(3, 10);
  if (mthread_mutex_lock(&mu[2]) != 0) err(3, 12); /* Transfer control to main
  						    * loop.
  						    */
  VERIFY_MUTEX(1, 0, 0, 3, 13);

  if (mthread_mutex_unlock(&mu[0]) != 0) err(3, 14);
  mutex_a_step = 2;
  mthread_yield();

  VERIFY_MUTEX(2, 1, 0, 3, 15);
  if (mthread_mutex_unlock(&mu[1]) != 0) err(3, 16);
  mutex_a_step = 3;

  /* Try with faulty memory locations */
  if (mthread_mutex_lock(NULL) == 0) err(3, 17);
  if (mthread_mutex_trylock(NULL) == 0) err(3, 18);
  if (mthread_mutex_unlock(NULL) == 0) err(3, 19);

  if (mthread_mutex_unlock(&mu[2]) != 0) err(3, 20);
  return(NULL);
}
Beispiel #5
0
/*===========================================================================*
 *				test_scheduling				     *
 *===========================================================================*/
static void test_scheduling(void)
{
  unsigned int i;
  thread_t t[7];

#ifdef MDEBUG
  mthread_verify();
#endif
  th_a = th_b = th_c = th_d = th_e = 0;

  if (mthread_create(&t[0], NULL, thread_a, NULL) != 0) err(1, 1);
  if (mthread_create(&t[1], NULL, thread_a, NULL) != 0) err(1, 2);
  if (mthread_create(&t[2], NULL, thread_a, NULL) != 0) err(1, 3);
  if (mthread_create(&t[3], NULL, thread_d, NULL) != 0) err(1, 4);
  if (mthread_once(&once, thread_e) != 0) err(1, 5);

  mthread_yield();

  if (mthread_create(&t[4], NULL, thread_c, NULL) != 0) err(1, 6);
  mthread_yield();
  if (mthread_create(&t[5], NULL, thread_b, NULL) != 0) err(1, 7);
  if (mthread_create(&t[6], NULL, thread_a, NULL) != 0) err(1, 8);
  mthread_yield();
  mthread_yield();
  if (mthread_once(&once, thread_e) != 0) err(1, 9);
  if (mthread_once(&once, thread_e) != 0) err(1, 10);

  if (th_a != 4) err(1, 11);
  if (th_b != 1) err(1, 12);
  if (th_c != 1) err(1, 13);
  if (th_d != 1) err(1, 14);
  if (th_e != 1) err(1, 15);

  for (i = 0; i < (sizeof(t) / sizeof(thread_t)); i++) {
	if (mthread_join(t[i], NULL) != 0) err(1, 16);
	if (mthread_join(t[i], NULL) == 0) err(1, 17); /*Shouldn't work twice*/
  }

#ifdef MDEBUG
  mthread_verify();
#endif
  if (mthread_create(NULL, NULL, NULL, NULL) == 0) err(1, 18);
  mthread_yield();

#ifdef MDEBUG
  mthread_verify();
#endif
  if (mthread_create(&t[6], NULL, NULL, NULL) == 0) err(1, 19);
  mthread_yield();
#ifdef MDEBUG
  mthread_verify();
#endif
  if (mthread_join(0xc0ffee, NULL) == 0) err(1, 20);
  mthread_yield();
  mthread_yield();

#ifdef MDEBUG
  mthread_verify();
#endif
}
Beispiel #6
0
/*===========================================================================*
 *				key_c					     *
 *===========================================================================*/
static void *key_c(void *arg)
{
  /* The only thing that this thread should do, is set a value. */
  if (mthread_setspecific(key[0], (void *) mthread_self()) != 0) err(19, 1);

  mthread_yield();

  if (!mthread_equal((thread_t) mthread_getspecific(key[0]), mthread_self()))
	err(19, 2);
  return(NULL);
}
Beispiel #7
0
static void * threadfunc(void * arg)
{
  char *name = arg;
  printf("je suis le thread %p, lancé avec l'argument %s\n",
	 mthread_self(), name);
  mthread_yield();
  printf("je suis encore le thread %p, lancé avec l'argument %s\n",
	 mthread_self(), name);
  mthread_exit(arg);
  return NULL;
}
Beispiel #8
0
/*===========================================================================*
 *				key_b					     *
 *===========================================================================*/
static void *key_b(void *arg)
{
  int i;

  first = 1;
  mthread_yield();

  /* Each new threads gets NULL-initialized values. */
  for (i = 0; i < 5; i++)
	if (mthread_getspecific(key[i]) != NULL) err(18, 1);

  for (i = 0; i < 4; i++)
	if (mthread_setspecific(key[i], (void *) (i + 2)) != 0) err(18, 2);

  mthread_yield();

  /* Deleting a key will not cause a call its destructor at any point. */
  if (mthread_key_delete(key[3]) != 0) err(18, 3);

  mthread_exit(NULL);
  return(NULL);
}
Beispiel #9
0
/*===========================================================================*
 *				mutex_c					     *
 *===========================================================================*/
static void *mutex_c(void *arg)
{
  mutex_t *mu = (mutex_t *) arg;

  VERIFY_MUTEX(1, 0, 0, 5, 1);
  if (mthread_mutex_lock(&mu[1]) != 0) err(5, 2);
  mutex_c_step = 1;
  VERIFY_MUTEX(3, 1, 1, 5, 3);
  mthread_yield();
  VERIFY_MUTEX(3, 1, 1, 5, 4);

  if (mthread_mutex_unlock(&mu[1]) != 0) err(5, 5);
  mutex_c_step = 2;
  if (mthread_mutex_lock(&mu[0]) != 0) err(5, 6);
  mutex_c_step = 3;
  VERIFY_MUTEX(3, 3, 3, 5, 7);
  mthread_yield();
  VERIFY_MUTEX(3, 4, 3, 5, 8);

  if (mthread_mutex_unlock(&mu[0]) != 0) err(5, 9);
  mutex_c_step = 4;
  return(NULL);
}
Beispiel #10
0
/*===========================================================================*
 *					cond_a				     *
 *===========================================================================*/
static void *cond_a(void *arg)
{
  cond_t c;
  int did_count = 0;
  while(1) {
  	if (mthread_mutex_lock(condition_mutex) != 0) err(6, 1);
  	while (count >= THRESH1 && count <= THRESH2) {
  		if (mthread_cond_wait(&condition, condition_mutex) != 0)
  			err(6, 2);
  	}
  	if (mthread_mutex_unlock(condition_mutex) != 0) err(6, 3);

	mthread_yield(); 

  	if (mthread_mutex_lock(count_mutex) != 0) err(6, 4);
  	count++;
  	did_count++;
  	if (mthread_mutex_unlock(count_mutex) != 0) err(6, 5);

  	if (count >= ROUNDS) break;
  }
  if (!(did_count <= count - (THRESH2 - THRESH1 + 1))) err(6, 6);

  /* Try faulty addresses */
  if (mthread_mutex_lock(condition_mutex) != 0) err(6, 7);
#ifdef MTHREAD_STRICT
  /* Condition c is not initialized, so whatever we do with it should fail. */
  if (mthread_cond_wait(&c, condition_mutex) == 0) err(6, 8);
  if (mthread_cond_wait(NULL, condition_mutex) == 0) err(6, 9);
  if (mthread_cond_signal(&c) == 0) err(6, 10);
  if (mthread_mutex_unlock(condition_mutex) != 0) err(6, 11);

  /* Try again with an unlocked mutex */
  if (mthread_cond_wait(&c, condition_mutex) == 0) err(6, 12);
  if (mthread_cond_signal(&c) == 0) err(6, 13);
#endif

  /* And again with an unlocked mutex, but initialized c */
  if (mthread_cond_init(&c, NULL) != 0) err(6, 14);
  if (mthread_cond_wait(&c, condition_mutex) == 0) err(6, 15);
  if (mthread_cond_signal(&c) != 0) err(6, 16);/*c.f., 6.10 this should work!*/
  if (mthread_cond_destroy(&c) != 0) err(6, 17);
  return(NULL);
}
Beispiel #11
0
/*===========================================================================*
 *				event_a					     *
 *===========================================================================*/
static void *event_a(void *arg)
{
  VERIFY_EVENT(0, 0, 21, 1);

  /* Wait for main thread to signal us */
  if (mthread_event_wait(&event) != 0) err(21, 2);

  /* Mark state transition and wakeup thread b */
  event_a_step = 1;
  if (mthread_event_fire(&event) != 0) err(21, 3);
  mthread_yield();
  VERIFY_EVENT(1, 1, 21, 4);

  /* Wait for main thread to signal again with fireall  */
  if (mthread_event_wait(&event) != 0) err(21, 5);

  /* Marks state transition and exit */
  event_a_step = 2;
  return(NULL);
}
Beispiel #12
0
/*===========================================================================*
 *				test_mutex				     *
 *===========================================================================*/
static void test_mutex(void)
{
  unsigned int i;
  thread_t t[3];
#ifdef MDEBUG
  mthread_verify();
#endif
  if (mthread_mutex_init(&mu[0], NULL) != 0) err(2, 1);
  if (mthread_mutex_init(&mu[1], NULL) != 0) err(2, 2);
  if (mthread_mutex_init(&mu[2], NULL) != 0) err(2, 3);

  if (mthread_create(&t[0], NULL, mutex_a, (void *) mu) != 0) err(2, 3);
  if (mthread_create(&t[1], NULL, mutex_b, (void *) mu) != 0) err(2, 4);
  if (mthread_create(&t[2], NULL, mutex_c, (void *) mu) != 0) err(2, 5);

  if (mthread_mutex_lock(&mu[2]) != 0) err(2, 6);

  mthread_yield_all(); /* Should result in a RUNNABLE mutex_a, and a blocked
  			* on mutex mutex_b and mutex_c.
  			*/ 

  VERIFY_MUTEX(1, 0, 0, 2, 7); /* err(2, 7) */
  if (mthread_mutex_unlock(&mu[2]) != 0) err(2, 8);

  mthread_yield();	/* Should schedule mutex_a to release the lock on the
			 * mu[0] mutex. Consequently allowing mutex_b and mutex_c
  			* to acquire locks on the mutexes and exit.
  			*/
  VERIFY_MUTEX(2, 0, 0, 2, 9);

  for (i = 0; i < (sizeof(t) / sizeof(thread_t)); i++) 
	if (mthread_join(t[i], NULL) != 0) err(2, 10);

  if (mthread_mutex_destroy(&mu[0]) != 0) err(2, 11);
  if (mthread_mutex_destroy(&mu[1]) != 0) err(2, 12);
  if (mthread_mutex_destroy(&mu[2]) != 0) err(2, 13);

#ifdef MDEBUG
  mthread_verify();
#endif
}
Beispiel #13
0
/*===========================================================================*
 *				rwlock_b				     *
 *===========================================================================*/
static void *rwlock_b(void *arg)
{
  /* Step 1: acquire the read lock */
  VERIFY_RWLOCK(1, 0, 25, 1);
  if (mthread_rwlock_rdlock(&rwlock) != 0) err(25, 2);
  rwlock_b_step = 1;
  mthread_yield();

  /* We return back with first thread blocked on wrlock */
  VERIFY_RWLOCK(2, 1, 25, 3);
  rwlock_b_step = 2;

  /* Release read lock and acquire write lock */
  if (mthread_rwlock_unlock(&rwlock) != 0) err(25, 4);
  if (mthread_rwlock_wrlock(&rwlock) != 0) err(25, 5);
  rwlock_b_step = 3;

  VERIFY_RWLOCK(3, 3, 25, 6);
  if (mthread_rwlock_unlock(&rwlock) != 0) err(25, 6);

  return(NULL);
}
Beispiel #14
0
/*===========================================================================*
 *					cond_b				     *
 *===========================================================================*/
static void *cond_b(void *arg)
{
  int did_count = 0;
  while(1) {
  	if (mthread_mutex_lock(condition_mutex) != 0) err(7, 1);
  	if (count < THRESH1 || count > THRESH2) 
  		if (mthread_cond_signal(&condition) != 0) err(7, 2);
  	if (mthread_mutex_unlock(condition_mutex) != 0) err(7, 3);

	mthread_yield();

  	if (mthread_mutex_lock(count_mutex) != 0) err(7, 4);
  	count++;
  	did_count++;
  	if (mthread_mutex_unlock(count_mutex) != 0) err(7, 5);

  	if (count >= ROUNDS) break;
  }

  if (!(did_count >= count - (THRESH2 - THRESH1 + 1))) err(7, 6);

  return(NULL);
}
Beispiel #15
0
/*===========================================================================*
 *				test_condition				     *
 *===========================================================================*/
static void test_condition(void)
{
#define NTHREADS 10
  int i;
  thread_t t[2], s[NTHREADS];
  count_mutex = &mu[0];
  condition_mutex = &mu[1];

  /* Test simple condition variable behavior: Two threads increase a counter.
   * At some point one thread waits for a condition and the other thread
   * signals the condition. Consequently, one thread increased the counter a
   * few times less than other thread. Although the difference is 'random', 
   * there is a guaranteed minimum difference that we can measure.
   */

#ifdef MDEBUG
  mthread_verify();
#endif

  if (mthread_mutex_init(count_mutex, NULL) != 0) err(8, 1);
  if (mthread_mutex_init(condition_mutex, NULL) != 0) err(8, 2);
  if (mthread_cond_init(&condition, NULL) != 0) err(8, 3);
  count = 0;

  if (mthread_create(&t[0], NULL, cond_a, NULL) != 0) err(8, 4);
  if (mthread_create(&t[1], NULL, cond_b, NULL) != 0) err(8, 5);

  for (i = 0; i < (sizeof(t) / sizeof(thread_t)); i++)
	if (mthread_join(t[i], NULL) != 0) err(8, 6);

  if (mthread_mutex_destroy(count_mutex) != 0) err(8, 7);
  if (mthread_mutex_destroy(condition_mutex) != 0) err(8, 8);
  if (mthread_cond_destroy(&condition) != 0) err(8, 9);

#ifdef MTHREAD_STRICT
  /* Let's try to destroy it again. Should fails as it's uninitialized. */
  /* Note: this only works when libmthread is compiled with MTHREAD_STRICT. In
   * POSIX this situation is a MAY fail if... */
  if (mthread_cond_destroy(&condition) == 0) err(8, 10); 
#endif

#ifdef MDEBUG
  mthread_verify();
#endif

  /* Test signal broadcasting: spawn N threads that will increase a counter
   * after a condition has been signaled. The counter must equal N. */
  if (mthread_mutex_init(count_mutex, NULL) != 0) err(8, 11);
  if (mthread_mutex_init(condition_mutex, NULL) != 0) err(8, 12);
  if (mthread_cond_init(&condition, NULL) != 0) err(8, 13);
  condition_met = count = 0;

  for (i = 0; i < NTHREADS; i++) 
	if (mthread_create(&s[i], NULL, cond_broadcast, NULL) != 0) err(8, 14);

  /* Allow other threads to block on the condition variable. If we don't yield,
   * the threads will only start running when we call mthread_join below. In
   * that case the while loop in cond_broadcast will never evaluate to true.
   */
  mthread_yield();

  if (mthread_mutex_lock(condition_mutex) != 0) err(8, 15);
  condition_met = 1;
  if (mthread_cond_broadcast(&condition) != 0) err(8, 16);
  if (mthread_mutex_unlock(condition_mutex) != 0) err(8, 17);

  for (i = 0; i < (sizeof(s) / sizeof(thread_t)); i++) 
	if (mthread_join(s[i], NULL) != 0) err(8, 18);

  if (count != NTHREADS) err(8, 19);
  if (mthread_mutex_destroy(count_mutex) != 0) err(8, 20);
  if (mthread_mutex_destroy(condition_mutex) != 0) err(8, 21);
  if (mthread_cond_destroy(&condition) != 0) err(8, 22); 

#ifdef MTHREAD_STRICT 
  /* Again, destroying the condition variable twice shouldn't work */
  /* See previous note about MTHREAD_STRICT */
  if (mthread_cond_destroy(&condition) == 0) err(8, 23); 
#endif

#ifdef MDEBUG
  mthread_verify();
#endif
}