-/* Copyright (C) 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
int oldtype;
pthread_cond_t *cond;
pthread_mutex_t *mutex;
+ unsigned int bc_seq;
};
/* We are going to modify shared data. */
lll_mutex_lock (cbuffer->cond->__data.__lock);
- /* This thread is not waiting anymore. Adjust the sequence counters
- appropriately. */
- ++cbuffer->cond->__data.__wakeup_seq;
- ++cbuffer->cond->__data.__woken_seq;
+ if (cbuffer->bc_seq == cbuffer->cond->__data.__broadcast_seq)
+ {
+ /* This thread is not waiting anymore. Adjust the sequence counters
+ appropriately. */
+ ++cbuffer->cond->__data.__wakeup_seq;
+ ++cbuffer->cond->__data.__woken_seq;
+ }
/* We are done. */
lll_mutex_unlock (cbuffer->cond->__data.__lock);
lll_mutex_lock (cond->__data.__lock);
/* Now we can release the mutex. */
- err = __pthread_mutex_unlock_internal (mutex);
- if (err)
+ err = __pthread_mutex_unlock_usercnt (mutex, 0);
+ if (__builtin_expect (err, 0))
{
lll_mutex_unlock (cond->__data.__lock);
return err;
++cond->__data.__total_seq;
/* Remember the mutex we are using here. If there is already a
- different address store this is a bad user bug. */
- cond->__data.__mutex = mutex;
+ different address store this is a bad user bug. Do not store
+ anything for pshared condvars. */
+ if (cond->__data.__mutex != (void *) ~0l)
+ cond->__data.__mutex = mutex;
/* Prepare structure passed to cancellation handler. */
cbuffer.cond = cond;
unsigned long long int val;
unsigned long long int seq;
val = seq = cond->__data.__wakeup_seq;
+ /* Remember the broadcast counter. */
+ cbuffer.bc_seq = cond->__data.__broadcast_seq;
/* The futex syscall operates on a 32-bit word. That is fine, we
just use the low 32 bits of the sequence counter. */
/* Disable asynchronous cancellation. */
__pthread_disable_asynccancel (cbuffer.oldtype);
+ /* If a broadcast happened, we are done. */
+ if (cbuffer.bc_seq != cond->__data.__broadcast_seq)
+ goto bc_out;
+
/* We are going to look at shared data again, so get the lock. */
lll_mutex_lock (cond->__data.__lock);
/* Check whether we are eligible for wakeup. */
val = cond->__data.__wakeup_seq;
}
- while (! (val > seq && cond->__data.__woken_seq < val));
+ while (val == seq || cond->__data.__woken_seq == val);
/* Another thread woken up. */
++cond->__data.__woken_seq;
+ bc_out:
/* We are done with the condvar. */
lll_mutex_unlock (cond->__data.__lock);