[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: Threads not waking on pthread_cond_signal()



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
#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);
}
#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 );

  }    
    
}

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]