Exemple #1
0
/*===========================================================================*
 *				test_event				     *
 *===========================================================================*/
static void test_event(void)
{
  thread_t t[2];
  int i;

  if (mthread_event_init(&event) != 0) err(23, 1);

  /* Try with faulty memory locations */
  if (mthread_event_wait(NULL) == 0) err(23, 2);
  if (mthread_event_fire(NULL) == 0) err(23, 3);

  /* create threads */
  if (mthread_create(&t[0], NULL, event_a, NULL) != 0) err(23, 4);
  if (mthread_create(&t[1], NULL, event_b, NULL) != 0) err(23, 5);

  /* wait for them to block on event */
  mthread_yield_all();
  VERIFY_EVENT(0, 0, 23, 6);

  /* Fire event to wakeup thread a */
  if (mthread_event_fire(&event) != 0) err(23, 7);
  mthread_yield_all();
  VERIFY_EVENT(1, 1, 23, 6);

  /* Fire all to wakeup both a and b */
  if (mthread_event_fire_all(&event) != 0) err(23, 7);
  mthread_yield_all();
  VERIFY_EVENT(2, 2, 23, 8);

  /* We are done here */
  for (i = 0; i < 2; i++)
	if (mthread_join(t[i], NULL) != 0) err(23, 9);

  if (mthread_event_destroy(&event) != 0) err(23, 10);
}
Exemple #2
0
void* tab_sum(void* arg) {
  struct indices* indice = (struct indices*) arg;
  unsigned int a, b, m;
  a = indice->a;
  b = indice->b;
  
  if (b<=a) {
    if (affiche_arg)
      printf("%u:%u %lu\t",a,b, tableau[a]);
    return NULL; 
  }

  m = (b+a)/2;
  
  mthread_t th1, th2;
  struct indices i1;
  struct indices i2;
  i1.a = a;
  i1.b = m;
  i2.a = m+1;
  i2.b = b;

  mthread_create(&th1, &tab_sum, (void*)(&i1));
  mthread_create(&th2, &tab_sum, (void*)(&i2));
  mthread_join(th1, NULL); 
  mthread_join(th2, NULL);

  if (affiche_arg)
    printf("%u:%u %lu\t",a,b, tableau[a] + tableau[m+1]);
  tableau[a] += tableau[m+1];  

  return NULL;
}
Exemple #3
0
//int main(int argc, char *argv[])
int main()
{
  time_start(); {
    mthread_t thread1, thread2;
    void *retval1, *retval2;
    int err;
    
    printf("le main lance 2 threads...\n");
    err = mthread_create(&thread1, threadfunc, "thread1");
    assert(!err);
    err = mthread_create(&thread2, threadfunc, "thread2");
    assert(!err);
    printf("le main a lancé les threads %p et %p\n",
	   thread1, thread2);
    
    printf("le main attend les threads\n");
    err = mthread_join(thread2, &retval2);
    assert(!err);
    err = mthread_join(thread1, &retval1);
    assert(!err);
    printf("les threads ont terminé en renvoyant '%s' and '%s'\n",
	   (char *) retval1, (char *) retval2);
  }
  time_end() ;
  return 0;
}
Exemple #4
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
}
Exemple #5
0
/*===========================================================================*
 *				worker_init				     *
 *===========================================================================*/
PUBLIC void worker_init(struct worker_thread *wp)
{
/* Initialize worker thread */
  if (!init) {
	threads_init();
	if (mthread_attr_init(&tattr) != 0)
		panic("failed to initialize attribute");
	if (mthread_attr_setstacksize(&tattr, TH_STACKSIZE) != 0)
		panic("couldn't set default thread stack size");
	if (mthread_attr_setdetachstate(&tattr, MTHREAD_CREATE_DETACHED) != 0)
		panic("couldn't set default thread detach state");
	pending = 0;
	init = 1;
  }

  ASSERTW(wp);

  wp->w_job.j_func = NULL;		/* Mark not in use */
  wp->w_next = NULL;
  if (mutex_init(&wp->w_event_mutex, NULL) != 0)
	panic("failed to initialize mutex");
  if (cond_init(&wp->w_event, NULL) != 0)
	panic("failed to initialize conditional variable");
  if (mthread_create(&wp->w_tid, &tattr, worker_main, (void *) wp) != 0)
	panic("unable to start thread");
  yield();
}
Exemple #6
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
}
Exemple #7
0
/*===========================================================================*
 *				test_rwlock				     *
 *===========================================================================*/
static void test_rwlock(void)
{
  thread_t t[2];
  int i;

  if (mthread_rwlock_init(&rwlock) != 0) err(26, 1);

  /* Try with faulty memory locations */
  if (mthread_rwlock_rdlock(NULL) == 0) err(26, 2);
  if (mthread_rwlock_wrlock(NULL) == 0) err(26, 3);
  if (mthread_rwlock_unlock(NULL) == 0) err(26, 4);

  /* Create the threads and start testing */
  if (mthread_create(&t[0], NULL, rwlock_a, NULL) != 0) err(26, 5);
  if (mthread_create(&t[1], NULL, rwlock_b, NULL) != 0) err(26, 6);

  mthread_yield_all();

  for (i = 0; i < 2; i++)
	if (mthread_join(t[i], NULL) != 0) err(26, 7);

  if (mthread_rwlock_destroy(&rwlock) != 0) err(26, 8);
}
Exemple #8
0
/*===========================================================================*
 *				test_keys				     *
 *===========================================================================*/
static void test_keys(void)
{
  thread_t t[24];
  int i, j;

  /* Make sure that we can create exactly MTHREAD_KEYS_MAX keys. */
  memset(key, 0, sizeof(key));

  for (i = 0; i < MTHREAD_KEYS_MAX; i++) {
	if (mthread_key_create(&key[i], NULL) != 0) err(20, 1);

	for (j = 0; j < i - 1; j++)
		if (key[i] == key[j]) err(20, 2);
  }

  if (mthread_key_create(&key[i], NULL) != EAGAIN) err(20, 3);

  for (i = 3; i < MTHREAD_KEYS_MAX; i++)
	if (mthread_key_delete(key[i]) != 0) err(20, 4);

  /* Test basic good and bad value assignment and retrieval. */
  if (mthread_setspecific(key[0], (void *) 1) != 0) err(20, 5);
  if (mthread_setspecific(key[1], (void *) 2) != 0) err(20, 6);
  if (mthread_setspecific(key[2], (void *) 3) != 0) err(20, 7);
  if (mthread_setspecific(key[1], NULL) != 0) err(20, 8);
  if (mthread_getspecific(key[0]) != (void *) 1) err(20, 9);
  if (mthread_getspecific(key[1]) != NULL) err(20, 10);
  if (mthread_getspecific(key[2]) != (void *) 3) err(20, 11);
  if (mthread_setspecific(key[3], (void *) 4) != EINVAL) err(20, 12);
  if (mthread_setspecific(key[3], NULL) != EINVAL) err(20, 13);

  if (mthread_key_delete(key[1]) != 0) err(20, 14);
  if (mthread_key_delete(key[2]) != 0) err(20, 15);

  /* Test thread locality and destructors. */
  if (mthread_key_create(&key[1], destr_a) != 0) err(20, 16);
  if (mthread_key_create(&key[2], destr_a) != 0) err(20, 17);
  if (mthread_key_create(&key[3], destr_b) != 0) err(20, 18);
  if (mthread_key_create(&key[4], destr_b) != 0) err(20, 19);

  if (mthread_getspecific(key[2]) != NULL) err(20, 20);

  for (i = 0; i < 4; i++)
	values[i] = 1;
  first = 0;

  if (mthread_create(&t[0], NULL, key_a, NULL) != 0) err(20, 21);
  if (mthread_create(&t[1], NULL, key_b, NULL) != 0) err(20, 22);

  for (i = 0; i < 2; i++) 
	if (mthread_join(t[i], NULL) != 0) err(20, 23);

  /* The destructors must have changed all these values now. */
  for (i = 0; i < 4; i++)
	if (values[i] != 2) err(20, 24);

  /* The original values must not have changed. */
  if (mthread_getspecific(key[0]) != (void *) 1) err(20, 25);

  /* Deleting a deleted key should not cause any problems either. */
  if (mthread_key_delete(key[3]) != EINVAL) err(20, 26);

  /* Make sure everything still works when using a larger number of threads.
   * This should trigger reallocation code within libmthread's key handling.
   */
  for (i = 0; i < 24; i++)
	if (mthread_create(&t[i], NULL, key_c, NULL) != 0) err(20, 27);

  for (i = 0; i < 24; i++) 
	if (mthread_join(t[i], NULL) != 0) err(20, 28);
}
Exemple #9
0
/*===========================================================================*
 *				test_attributes				     *
 *===========================================================================*/
static void test_attributes(void)
{
  attr_t tattr;
  thread_t tid;
  int detachstate = -1, status = 0;
  unsigned int i, no_ints, stack_untouched = 1;
  void *stackaddr, *newstackaddr;
  int *stackp;
  size_t stacksize, newstacksize;

#ifdef MDEBUG
  mthread_verify();
#endif

  /* Initialize thread attribute and try to read the default values */
  if (mthread_attr_init(&tattr) != 0) err(11, 1);
  if (mthread_attr_getdetachstate(&tattr, &detachstate) != 0) err(11, 2);
  if (detachstate != MTHREAD_CREATE_JOINABLE) err(11, 3);
  if (mthread_attr_getstack(&tattr, &stackaddr, &stacksize) != 0) err(11, 4);
  if (stackaddr != NULL) err(11, 5);
  if (stacksize != (size_t) 0) err(11, 6);

  /* Modify the attribute ... */
  /* Try bogus detach state value */
  if (mthread_attr_setdetachstate(&tattr, 0xc0ffee) == 0) err(11, 7);
  if (mthread_attr_setdetachstate(&tattr, MTHREAD_CREATE_DETACHED) != 0)
  	err(11, 8);
  newstacksize = (size_t) MEG;
  if ((newstackaddr = malloc(newstacksize)) == NULL) err(11, 9);
  if (mthread_attr_setstack(&tattr, newstackaddr, newstacksize) != 0)
  	err(11, 10);
   /* ... and read back the new values. */
  if (mthread_attr_getdetachstate(&tattr, &detachstate) != 0) err(11, 11);
  if (detachstate != MTHREAD_CREATE_DETACHED) err(11, 12);
  if (mthread_attr_getstack(&tattr, &stackaddr, &stacksize) != 0) err(11, 13);
  if (stackaddr != newstackaddr) err(11, 14);
  if (stacksize != newstacksize) err(11, 15);
  if (mthread_attr_destroy(&tattr) != 0) err(11, 16);
  free(newstackaddr);

  /* Try to allocate too small a stack; it should fail and the attribute 
   * values should remain as is.
   */
  newstacksize = MTHREAD_STACK_MIN - 1;
  stackaddr = NULL;
  stacksize = 0;
  if (mthread_attr_init(&tattr) != 0) err(11, 17);
  if ((newstackaddr = malloc(newstacksize)) == NULL) err(11, 18);
  if (mthread_attr_setstack(&tattr, newstackaddr, newstacksize) != EINVAL)
  	err(11, 19);
  if (mthread_attr_getstack(&tattr, &stackaddr, &stacksize) != 0) err(11, 21);
  if (stackaddr == newstackaddr) err(11, 22);
  if (stacksize == newstacksize) err(11, 23);
  if (mthread_attr_destroy(&tattr) != 0) err(11, 24);
  free(newstackaddr);

  /* Tell attribute to let the system allocate a stack for the thread and only
   * dictate how big that stack should be (2 megabyte, not actually allocated
   * yet).
   */
  if (mthread_attr_init(&tattr) != 0) err(11, 25);
  if (mthread_attr_setstack(&tattr, NULL /* System allocated */, 2*MEG) != 0)
  	err(11, 26);
  if (mthread_attr_getstack(&tattr, &stackaddr, &stacksize) != 0) err(11, 27);
  if (stackaddr != NULL) err(11, 28);
  if (stacksize != 2*MEG) err(11, 29);

  /* Use set/getstacksize to set and retrieve new stack sizes */
  stacksize = 0;
  if (mthread_attr_getstacksize(&tattr, &stacksize) != 0) err(11, 30);
  if (stacksize != 2*MEG) err(11, 31);
  newstacksize = MEG;
  if (mthread_attr_setstacksize(&tattr, newstacksize) != 0) err(11, 32);
  if (mthread_attr_getstacksize(&tattr, &stacksize) != 0) err(11, 33);
  if (stacksize != newstacksize) err(11, 34);
  if (mthread_attr_destroy(&tattr) != 0) err(11, 35);

  /* Perform same tests, but also actually use them in a thread */
  if (mthread_attr_init(&tattr) != 0) err(11, 36);
  if (mthread_attr_setdetachstate(&tattr, MTHREAD_CREATE_DETACHED) != 0)
  	err(11, 37);
  condition_mutex = &mu[0];
  if (mthread_mutex_init(condition_mutex, NULL) != 0) err(11, 38);
  if (mthread_cond_init(&condition, NULL) != 0) err(11, 39);
  if (mthread_mutex_lock(condition_mutex) != 0) err(11, 40);
  if (mthread_create(&tid, &tattr, thread_f, NULL) != 0) err(11, 41);
  /* Wait for thread_f to finish */
  if (mthread_cond_wait(&condition, condition_mutex) != 0) err(11, 42);
  if (mthread_mutex_unlock(condition_mutex) != 0) err(11, 43);
  if (th_f != 1) err(11, 44);
  /* Joining a detached thread should fail */
  if (mthread_join(tid, NULL) == 0) err(11, 45);
  if (mthread_attr_destroy(&tattr) != 0) err(11, 46);

  /* Try telling the attribute how large the stack should be */
  if (mthread_attr_init(&tattr) != 0) err(11, 47);
  if (mthread_attr_setstack(&tattr, NULL, 2 * MTHREAD_STACK_MIN) != 0)
  	err(11, 48);
  if (mthread_mutex_lock(condition_mutex) != 0) err(11, 49);
  if (mthread_create(&tid, &tattr, thread_g, NULL) != 0) err(11, 50);
  /* Wait for thread_g to finish */
  if (mthread_cond_wait(&condition, condition_mutex) != 0) err(11, 51);
  if (mthread_mutex_unlock(condition_mutex) != 0) err(11, 52);
  if (th_g != 1) err(11, 53);
  if (mthread_attr_setdetachstate(&tattr, MTHREAD_CREATE_DETACHED) != 0)
  	err(11, 54); /* Shouldn't affect the join below, as thread is already
  		      * running as joinable. If this attribute should be 
  		      * modified after thread creation, use mthread_detach().
  		      */
  if (mthread_join(tid, NULL) != 0) err(11, 55);
  if (mthread_attr_destroy(&tattr) != 0) err(11, 56);

  /* Try telling the attribute how large the stack should be and where it is
   * located.
   */
  if (mthread_attr_init(&tattr) != 0) err(11, 57);
  stacksize = 3 * MEG;
  /* Make sure this test is meaningful. We have to verify that we actually
   * use a custom stack. So we're going to allocate an array on the stack in
   * thread_h that should at least be bigger than the default stack size
   * allocated by the system.
   */
  if (2 * MEG <= MTHREAD_STACK_MIN) err(11, 58);
  if ((stackaddr = malloc(stacksize)) == NULL) err(11, 59);
  /* Fill stack with pattern. We assume that the beginning of the stack
   * should be overwritten with something and that the end should remain
   * untouched. The thread will zero-fill around two-thirds of the stack with
   * zeroes, so we can check if that's true. 
   */
  stackp = stackaddr;
  no_ints = stacksize / sizeof(int);
  for (i = 0; i < no_ints ; i++) 
	stackp[i] = MAGIC;
  if (mthread_attr_setstack(&tattr, stackaddr, stacksize) != 0) err(11, 60);
  if (mthread_mutex_lock(condition_mutex) != 0) err(11, 61);
  if (mthread_create(&tid, &tattr, thread_h, (void *) &stacksize) != 0)	
  	err(11, 62);
  /* Wait for thread h to finish */
  if (mthread_cond_wait(&condition, condition_mutex) != 0) err(11, 63);
  if (th_h != 1) err(11, 64);
  if (mthread_mutex_unlock(condition_mutex) != 0) err(11, 65);

  /* Verify stack hypothesis; we assume a stack is used from the top and grows
   * downwards.
   */
#if (_MINIX_CHIP == _CHIP_INTEL)
  if (stackp[0] != MAGIC) err(11, 66); /* End of the stack */
  for (i = no_ints - 1 - 16; i < no_ints; i++)
  	if (stackp[i] != MAGIC) stack_untouched = 0;
  if (stack_untouched) err(11, 67); /* Beginning of the stack */
  if (stackp[no_ints / 2] != 0) err(11, 68);/*Zero half way through the stack*/
#else
#error "Unsupported chip for this test"
#endif

  if (mthread_join(tid, (void *) &status) != 0) err(11, 69);
  if ((size_t) status != stacksize) err(11, 70);
  if (mthread_attr_destroy(&tattr) != 0) err(11, 71); 
  if (mthread_mutex_destroy(condition_mutex) != 0) err(11, 72);
  if (mthread_cond_destroy(&condition) != 0) err(11, 73);
  free(stackaddr);

#ifdef MDEBUG
  mthread_verify();
#endif
}
Exemple #10
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
}