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

Threads not waking on pthread_cond_signal()



Hello,

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().

I believe on PowerPC the first attached patch fixes the problem --
since lll_futex_requeue wasn't returning the number of threads moved
no thread ever got woken up.

On i386, I see correct behaviour for a little while, but eventually
the second attached program (wakeup.c) ends up with both threads
hanging in pthread_cond_wait() after about 20 seconds or so.  I was
hoping someone more familar with the i386 implementation could have a
look.

For example :

MASTER LOCK MUTEX
FILLED
MASTER UNLOCK MUTEX
MASTER LOCK MUTEX
MASTER COND SIGNAL   <--- master signals
MASTER COND WAIT
THREAD TOUCH         <--- thread woken up
EMPTIED!             <--- thread empties queue
THREAD COND SIGNAL   <--- signals for master to wakeup
		     <--- master should wake up, but it just hangs!

-i
ianw gelato unsw edu au
http://www.gelato.unsw.edu.au

--- nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h.old	2003-06-23 10:25:38.617454632 +1000
+++ nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h	2003-06-23 10:25:51.141550680 +1000
@@ -72,7 +72,7 @@
     __ret = INTERNAL_SYSCALL (futex, __err, 5,				      \
 			      (futexp), FUTEX_REQUEUE, (nr_wake), (nr_move),  \
 			      (mutex));					      \
-    INTERNAL_SYSCALL_ERROR_P (__ret, __err)? -__ret: 0;			      \
+    INTERNAL_SYSCALL_ERROR_P (__ret, __err)? -__ret: __ret;		      \
   })
 
 #ifdef UP
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>

/* 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) {
    printf("THREAD LOCK MUTEX\n"); fflush(NULL);
    pthread_mutex_lock( &condition.mutex );
    while ( condition.value == 0 ) {
      printf("THREAD COND WAIT\n"); fflush(NULL);
      pthread_cond_wait( &condition.full, &condition.mutex );
    }
    printf("THREAD TOUCH\n"); fflush(NULL);
    (*data_accessed)++;
    condition.value = 0;
    printf("EMPTIED!\n"); fflush(NULL);
    printf("THREAD COND SIGNAL\n");  fflush(NULL);
    pthread_cond_signal( &condition.empty );
    printf("THREAD UNLOCK MUTEX\n"); fflush(NULL);
    pthread_mutex_unlock( &condition.mutex );
  }
}

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

  for ( ; i < 1 ; i++ ) 
    pthread_create( &threads[i], NULL, thread, (void*)NULL );


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

    printf("MASTER LOCK MUTEX\n"); fflush(NULL);
    pthread_mutex_lock( &condition.mutex );
    /* if the queue is full, signal for worker to clean it */
    if ( condition.value ) {
      printf("MASTER COND SIGNAL \n");  fflush(NULL);
      pthread_cond_signal( &condition.full );
      printf("MASTER COND WAIT\n");  fflush(NULL);
      pthread_cond_wait( &condition.empty , &condition.mutex);
    }
    printf("MASTER UNLOCK MUTEX\n"); fflush(NULL);
    pthread_mutex_unlock( &condition.mutex );
    
    /* fill it back up */
    printf("MASTER LOCK MUTEX\n");  fflush(NULL);
    pthread_mutex_lock( &condition.mutex );
    printf("FILLED\n");  fflush(NULL);
    condition.value = 1; 
    printf("MASTER UNLOCK MUTEX\n"); fflush(NULL);
    pthread_mutex_unlock( &condition.mutex );

  }    
    
}



/* main */
int main(int argc, char *argv[]) 
{
	do_test();
}

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