Re: Threads not waking on pthread_cond_signal()

Ian Wienand <[email protected]>
Newsgroups gmane.comp.lib.phil
Message-ID <[email protected]>
On Sun, Jun 22, 2003 at 06:42:03PM -0700, Ulrich Drepper wrote:
> > I am seeing a problem on PowerPC and i386 with NPTL 0.47 where a
> > thread waiting in pthread_cond_wait() doesn't get woken up on
> > pthread_cond_signal().
> 
> What kernel are you using?

2.5.72 -- but I get correct behaviour with NPTL 0.48 so it was
probably me.

However, i386 does seem to be a lot slower signalling threads than the
NPTL included in RedHat 9.

RUNNING REDHAT 9 WAKEUP TEST
718674 wakes ups in 4.99956 sec = 143748 per second
861807 wakes ups in 5 sec       = 172361 per second
841964 wakes ups in 5.00006 sec = 168391 per second
816596 wakes ups in 5.00003 sec = 163318 per second
624066 wakes ups in 5.00004 sec = 124812 per second

RUNNING NPTL 0.48 WAKEUP TEST
114766 wakes ups in 4.99935 sec = 22956 per second
168681 wakes ups in 4.99996 sec = 33736 per second
286987 wakes ups in 4.99985 sec = 57399 per second
286391 wakes ups in 4.99962 sec = 57283 per second
337517 wakes ups in 5.00024 sec = 67500 per second

My iBook running 2.5.72/NPTL0.48 (from
bk://ppc.bkbits.net/linuxppc-2.5) gives me figures comprable to the
Redhat 9 figures.

You should be able to replicate this with the attached two files.

gcc -O2 -lpthread -o wakeup wakeup.c

If you think the test is not measuring what it should I would be
interested in why.

-i
thread.c (text/plain, 1.3 KB)
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <signal.h>
#include <sys/time.h>

/* the time to run each test */
#define TIME_TO_WAIT 5

/* FOR EACH TEST DEFINE : */
/* define a ul in your test that says how many things it did */
extern unsigned long things_done;
/* define a string in your test to say what it wasd doing */
extern char * things;
/* a function (that doesn't return) to run your test */
void do_test(void);

struct timeval start,end;

/* on alarm print out results */
void on_alarm(int signo) 
{
  struct timeval diff ;
  double diff_secs;

  /* grab things done before we continue as we do not kill 
     the potentially running threads until we exit below */
  unsigned long stamp = things_done;
  
  gettimeofday(&end, NULL);
  timersub( &end, &start , &diff );
  diff_secs = diff.tv_sec + diff.tv_usec*1e-6;

  printf("%d %s in %.4g sec = ", stamp,  things, diff_secs);
  printf("%.0f per second\n", stamp / diff_secs );

  exit(0);
}


/* main */
int main(int argc, char *argv[]) 
{
	/* setup alarm handler */
	static struct sigaction alarm_m;
	alarm_m.sa_handler = on_alarm;
	sigfillset(&(alarm_m.sa_mask));
	sigaction(SIGALRM , &alarm_m, NULL);

	alarm( TIME_TO_WAIT );

	gettimeofday( &start , NULL );

	do_test();
	
	sleep(TIME_TO_WAIT + 10);
}
wakeup.c (text/plain, 1.6 KB)
#include "thread.c"

/* what are we doing */
char *things = "wakes ups";			
/* how many have we done */
unsigned long things_done=0;

/* threads */
pthread_t thread_id;
void *thread(void*);

/* globals */
unsigned long *data_accessed = &things_done;

typedef struct condition_struct {
  pthread_mutex_t mutex;
  pthread_cond_t empty;
  pthread_cond_t full;
  unsigned long value;
} condition_t;

condition_t condition = {PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER, 0};

/* clear a 'queue' */
void *thread(void *arg) {
  while (1) {
    pthread_mutex_lock( &condition.mutex );
    while ( condition.value == 0 )
      pthread_cond_wait( &condition.full, &condition.mutex );
    (*data_accessed)++;
    condition.value = 0;
#ifdef DEBUG
    printf("EMPTIED!");
#endif
    pthread_cond_signal( &condition.empty );
    
    pthread_mutex_unlock( &condition.mutex );
  }
}

void do_test(void) {
  pthread_t threads[10];
  int i = 0;

  /* have 10 workers */
  for ( ; i < 10 ; i++ ) 
    pthread_create( &threads[i], NULL, thread, (void*)NULL );


  /* fill a queue, signal to threads to empty it */
  while ( 1 ) {

    pthread_mutex_lock( &condition.mutex );
    /* if the queue is full, signal for worker to clean it */
    if ( condition.value ) {
      pthread_cond_signal( &condition.full );
      pthread_cond_wait( &condition.empty , &condition.mutex);
    }
    pthread_mutex_unlock( &condition.mutex );
    
    /* fill it back up */
    pthread_mutex_lock( &condition.mutex );
#ifdef DEBUG
    printf("FILLED\n");
#endif
    condition.value = 1; 
    pthread_mutex_unlock( &condition.mutex );

  }    
    
}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.