Threads not waking on pthread_cond_signal()
Ian Wienand <[email protected]>
| Newsgroups | gmane.comp.lib.phil |
|---|---|
| Message-ID | <[email protected]> |
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 [email protected] http://www.gelato.unsw.edu.au
lowlevellock.h.patch
(text/plain, 513 B)
--- 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
wakeup.c
(text/plain, 2.2 KB)
#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();
}