problems with pthread_cond_broadcast

Thorsten Kukuk kukuk at suse.de
Thu Apr 15 05:50:54 UTC 2004


Hi,

I have a problem with pthread_cond_wait/pthread_cond_broadcast
waiting sometimes forever on a fast SMP machine. Attached is a
simple test case.

If I use the order
  pthread_mutex_unlock (&lock);
  pthread_cond_broadcast (&pcond);

with NPTL, the program will hang after a short time running with
current glibc + NPTL + kernel 2.6.x on all architectures I tested.

If I revert the order to 
  pthread_cond_broadcast (&pcond);
  pthread_mutex_unlock (&lock);

it works fine.

Is this a problem of the test case (since pthread_cond_broadcast and
pthread_cond_wait will access pcond at the same time in different
threads) or is this a glibc/NPTL/kernel problem?

 Thanks for any hint,

    Thorsten
-- 
Thorsten Kukuk       http://www.suse.de/~kukuk/        kukuk at suse.de
SuSE Linux AG        Maxfeldstr. 5                 D-90409 Nuernberg
--------------------------------------------------------------------    
Key fingerprint = A368 676B 5E1B 3E46 CFCE  2D97 F8FD 4E23 56C6 FB4B
-------------- next part --------------
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <assert.h>

#define BROKEN 1

#define DEFAULT_NUM_THREADS 64

/* n_readers >= 0 means 0 or more readers */
/* n_readers < 0 means a writer */
pthread_mutex_t lock;
int n_readers;
pthread_cond_t pcond;

void
init_rwlock (void)
{
  n_readers = 0;
  pthread_mutex_init (&lock, NULL);
  pthread_cond_init (&pcond, NULL);
}

void
rw_lock_write ()
{

  pthread_mutex_lock (&lock);

  while (n_readers != 0)
    pthread_cond_wait (&pcond, &lock);

  n_readers = -1;

  pthread_mutex_unlock (&lock);
}

void
rw_unlock_write (void)
{
  pthread_mutex_lock (&lock);
  n_readers = 0;
#if BROKEN
  pthread_mutex_unlock (&lock);
  pthread_cond_broadcast (&pcond);
#else
  pthread_cond_broadcast (&pcond);
  pthread_mutex_unlock (&lock);
#endif
}


void *
thread_fn (void *data)
{
  for (;;)
    {
      rw_lock_write ();
      fprintf (stderr, ".");
      rw_unlock_write ();
    }
  return NULL;
}

int
main (int argc, char *argv[])
{
  pthread_t *threads = NULL;
  int num_threads = DEFAULT_NUM_THREADS;
  int i;

  init_rwlock ();

  threads = malloc (num_threads * sizeof (pthread_t));

  for (i = 0; i < num_threads; i++)
    {
      assert (pthread_create (&threads[i], NULL, thread_fn, NULL) == 0);
    }


  for (i = 0; i < num_threads; i++)
    {
      pthread_join (threads[i], NULL);
    }

  return 0;
}


More information about the Phil-list mailing list