mirror of
https://sourceware.org/git/glibc.git
synced 2024-12-12 19:13:34 +08:00
3e976b962a
2003-03-11 Ulrich Drepper <drepper@redhat.com> * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S (__condvar_cleanup): Wake up all waiters in case we got signaled after being woken up but before disabling asynchronous cancellation. * sysdeps/pthread/pthread_cond_wait.c (__condvar_cleanup): Likewise. * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S (__condvar_cleanup): Likewise. * init.c (__NR_set_tid_address): If already defined, don't redefine. Make it an error if architecture has no #if case. Add x86-64. * sysdeps/unix/sysv/linux/x86_64/Makefile: Add flags for pt-initfini.s generation. * sysdeps/x86_64/tls.h: Include <asm/prctl.h>. (TLS_INIT_TP): Fix typo.
113 lines
1.7 KiB
Plaintext
113 lines
1.7 KiB
Plaintext
Conditional Variable pseudocode.
|
|
================================
|
|
|
|
int pthread_cond_timedwait (pthread_cond_t *cv, pthread_mutex_t *mutex);
|
|
int pthread_cond_signal (pthread_cond_t *cv);
|
|
int pthread_cond_broadcast (pthread_cond_t *cv);
|
|
|
|
struct pthread_cond_t {
|
|
|
|
unsigned int cond_lock;
|
|
|
|
internal mutex
|
|
|
|
uint64_t total_seq;
|
|
|
|
Total number of threads using the conditional variable.
|
|
|
|
uint64_t wakeup_seq;
|
|
|
|
sequence number for next wakeup.
|
|
|
|
uint64_t woken_seq;
|
|
|
|
sequence number of last woken thread.
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup_handler(cv)
|
|
{
|
|
lll_lock(cv->lock);
|
|
|
|
++cv->wakeup_seq;
|
|
++cv->woken_seq;
|
|
|
|
/* make sure no signal gets lost. */
|
|
FUTEX_WAKE(cv->wakeup_seq, ALL);
|
|
|
|
lll_unlock(cv->lock);
|
|
}
|
|
|
|
|
|
cond_timedwait(cv, mutex, timeout):
|
|
{
|
|
lll_lock(cv->lock);
|
|
mutex_unlock(mutex);
|
|
|
|
cleanup_push
|
|
|
|
++cv->total_seq;
|
|
val = seq = cv->wakeup_seq;
|
|
|
|
while (1) {
|
|
|
|
lll_unlock(cv->lock);
|
|
|
|
enable_async
|
|
|
|
ret = FUTEX_WAIT(cv->wakeup_seq, val, timeout);
|
|
|
|
restore_async
|
|
|
|
lll_lock(cv->lock);
|
|
|
|
val = cv->wakeup_seq;
|
|
|
|
if (cv->woken_seq >= seq && cv->woken_seq < val) {
|
|
ret = 0;
|
|
break;
|
|
}
|
|
|
|
if (ret == TIMEDOUT) {
|
|
++cv->wakeup_seq;
|
|
break;
|
|
}
|
|
}
|
|
|
|
++cv->woken_seq;
|
|
|
|
lll_unlock(cv->lock);
|
|
|
|
cleanup_pop
|
|
|
|
mutex_lock(mutex);
|
|
|
|
return ret;
|
|
}
|
|
|
|
cond_signal(cv)
|
|
{
|
|
lll_lock(cv->lock);
|
|
|
|
if (cv->total_seq > cv->wakeup_seq) {
|
|
++cv->wakeup_seq;
|
|
FUTEX_WAKE(cv->wakeup_seq, 1);
|
|
}
|
|
|
|
lll_unlock(cv->lock);
|
|
}
|
|
|
|
cond_broadcast(cv)
|
|
{
|
|
lll_lock(cv->lock);
|
|
|
|
if (cv->total_seq > cv->wakeup_seq) {
|
|
cv->wakeup_seq = cv->total_seq;
|
|
FUTEX_WAKE(cv->wakeup_seq, ALL);
|
|
}
|
|
|
|
lll_unlock(cv->lock);
|
|
}
|