aboutsummaryrefslogtreecommitdiff
path: root/linuxthreads/condvar.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>1998-06-25 19:36:00 +0000
committerUlrich Drepper <drepper@redhat.com>1998-06-25 19:36:00 +0000
commit3387a425e65b839b68bd2973f6bc5ab22315cc5d (patch)
tree375713a0b865b10b9eddd9c9877ad68cf0bdc851 /linuxthreads/condvar.c
parentd47aac39992cb1dd705d8c584f4d3979d7ce4602 (diff)
downloadglibc-3387a425e65b839b68bd2973f6bc5ab22315cc5d.zip
glibc-3387a425e65b839b68bd2973f6bc5ab22315cc5d.tar.gz
glibc-3387a425e65b839b68bd2973f6bc5ab22315cc5d.tar.bz2
Finish user stack support. Change locking code to be safe in situations with different priorities.
1998-06-25 19:27 Ulrich Drepper <drepper@cygnus.com> * attr.c: Finish user stack support. Change locking code to be safe in situations with different priorities. * cancel.c: Likewise. * condvar.c: Likewise. * internals.h: Likewise. * join.c: Likewise. * manager.c: Likewise. * mutex.c: Likewise. * pthread.c: Likewise. * ptlongjmp.c: Likewise. * queue.h: Likewise. * rwlock.c: Likewise. * semaphore.c: Likewise. * semaphore.h: Likewise. * signals.c: Likewise. * spinlock.c: Likewise. * spinlock.h: Likewise. Patches by Xavier leroy. 1998-06-25 Ulrich Drepper <drepper@cygnus.com> * sysdeps/pthread/pthread.h: Make [sg]et_stacksize and [sg]et_stackaddr prototypes always available. * sysdeps/unix/sysv/linux/bits/posix_opt.h: Define _POSIX_THREAD_ATTR_STACKSIZE and _POSIX_THREAD_ATTR_STACKADDR.
Diffstat (limited to 'linuxthreads/condvar.c')
-rw-r--r--linuxthreads/condvar.c79
1 files changed, 24 insertions, 55 deletions
diff --git a/linuxthreads/condvar.c b/linuxthreads/condvar.c
index 6807522..91067d2 100644
--- a/linuxthreads/condvar.c
+++ b/linuxthreads/condvar.c
@@ -25,42 +25,36 @@
#include "queue.h"
#include "restart.h"
-static void remove_from_queue(pthread_queue * q, pthread_descr th);
-
int pthread_cond_init(pthread_cond_t *cond,
const pthread_condattr_t *cond_attr)
{
- cond->c_spinlock = 0;
- queue_init(&cond->c_waiting);
+ __pthread_init_lock(&cond->c_lock);
+ cond->c_waiting = NULL;
return 0;
}
int pthread_cond_destroy(pthread_cond_t *cond)
{
- pthread_descr head;
-
- acquire(&cond->c_spinlock);
- head = cond->c_waiting.head;
- release(&cond->c_spinlock);
- if (head != NULL) return EBUSY;
+ if (cond->c_waiting != NULL) return EBUSY;
return 0;
}
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
{
volatile pthread_descr self = thread_self();
- acquire(&cond->c_spinlock);
+
+ __pthread_lock(&cond->c_lock);
enqueue(&cond->c_waiting, self);
- release(&cond->c_spinlock);
+ __pthread_unlock(&cond->c_lock);
pthread_mutex_unlock(mutex);
suspend_with_cancellation(self);
pthread_mutex_lock(mutex);
/* This is a cancellation point */
if (self->p_canceled && self->p_cancelstate == PTHREAD_CANCEL_ENABLE) {
/* Remove ourselves from the waiting queue if we're still on it */
- acquire(&cond->c_spinlock);
+ __pthread_lock(&cond->c_lock);
remove_from_queue(&cond->c_waiting, self);
- release(&cond->c_spinlock);
+ __pthread_unlock(&cond->c_lock);
pthread_exit(PTHREAD_CANCELED);
}
return 0;
@@ -77,15 +71,14 @@ pthread_cond_timedwait_relative(pthread_cond_t *cond,
sigjmp_buf jmpbuf;
/* Wait on the condition */
- acquire(&cond->c_spinlock);
+ __pthread_lock(&cond->c_lock);
enqueue(&cond->c_waiting, self);
- release(&cond->c_spinlock);
+ __pthread_unlock(&cond->c_lock);
pthread_mutex_unlock(mutex);
- /* Set up a longjmp handler for the restart signal */
- /* No need to save the signal mask, since PTHREAD_SIG_RESTART will be
- blocked when doing the siglongjmp, and we'll just leave it blocked. */
- if (sigsetjmp(jmpbuf, 0) == 0) {
+ /* Set up a longjmp handler for the restart and cancel signals */
+ if (sigsetjmp(jmpbuf, 1) == 0) {
self->p_signal_jmp = &jmpbuf;
+ self->p_cancel_jmp = &jmpbuf;
self->p_signal = 0;
/* Check for cancellation */
if (self->p_canceled && self->p_cancelstate == PTHREAD_CANCEL_ENABLE) {
@@ -104,28 +97,28 @@ pthread_cond_timedwait_relative(pthread_cond_t *cond,
retsleep = -1;
}
self->p_signal_jmp = NULL;
+ self->p_cancel_jmp = NULL;
/* Here, either the condition was signaled (self->p_signal != 0)
or we got canceled (self->p_canceled != 0)
or the timeout occurred (retsleep == 0)
or another interrupt occurred (retsleep == -1) */
- /* Re-acquire the spinlock */
- acquire(&cond->c_spinlock);
/* This is a cancellation point */
if (self->p_canceled && self->p_cancelstate == PTHREAD_CANCEL_ENABLE) {
+ __pthread_lock(&cond->c_lock);
remove_from_queue(&cond->c_waiting, self);
- release(&cond->c_spinlock);
+ __pthread_unlock(&cond->c_lock);
pthread_mutex_lock(mutex);
pthread_exit(PTHREAD_CANCELED);
}
/* If not signaled: also remove ourselves and return an error code */
if (self->p_signal == 0) {
+ __pthread_lock(&cond->c_lock);
remove_from_queue(&cond->c_waiting, self);
- release(&cond->c_spinlock);
+ __pthread_unlock(&cond->c_lock);
pthread_mutex_lock(mutex);
return retsleep == 0 ? ETIMEDOUT : EINTR;
}
/* Otherwise, return normally */
- release(&cond->c_spinlock);
pthread_mutex_lock(mutex);
return 0;
}
@@ -151,23 +144,22 @@ int pthread_cond_signal(pthread_cond_t *cond)
{
pthread_descr th;
- acquire(&cond->c_spinlock);
+ __pthread_lock(&cond->c_lock);
th = dequeue(&cond->c_waiting);
- release(&cond->c_spinlock);
+ __pthread_unlock(&cond->c_lock);
if (th != NULL) restart(th);
return 0;
}
int pthread_cond_broadcast(pthread_cond_t *cond)
{
- pthread_queue tosignal;
- pthread_descr th;
+ pthread_descr tosignal, th;
- acquire(&cond->c_spinlock);
+ __pthread_lock(&cond->c_lock);
/* Copy the current state of the waiting queue and empty it */
tosignal = cond->c_waiting;
- queue_init(&cond->c_waiting);
- release(&cond->c_spinlock);
+ cond->c_waiting = NULL;
+ __pthread_unlock(&cond->c_lock);
/* Now signal each process in the queue */
while ((th = dequeue(&tosignal)) != NULL) restart(th);
return 0;
@@ -182,26 +174,3 @@ int pthread_condattr_destroy(pthread_condattr_t *attr)
{
return 0;
}
-
-/* Auxiliary function on queues */
-
-static void remove_from_queue(pthread_queue * q, pthread_descr th)
-{
- pthread_descr t;
-
- if (q->head == NULL) return;
- if (q->head == th) {
- q->head = th->p_nextwaiting;
- if (q->head == NULL) q->tail = NULL;
- th->p_nextwaiting = NULL;
- return;
- }
- for (t = q->head; t->p_nextwaiting != NULL; t = t->p_nextwaiting) {
- if (t->p_nextwaiting == th) {
- t->p_nextwaiting = th->p_nextwaiting;
- if (th->p_nextwaiting == NULL) q->tail = t;
- th->p_nextwaiting = NULL;
- return;
- }
- }
-}