diff options
author | Ulrich Drepper <drepper@redhat.com> | 1998-06-25 19:36:00 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 1998-06-25 19:36:00 +0000 |
commit | 3387a425e65b839b68bd2973f6bc5ab22315cc5d (patch) | |
tree | 375713a0b865b10b9eddd9c9877ad68cf0bdc851 /linuxthreads/condvar.c | |
parent | d47aac39992cb1dd705d8c584f4d3979d7ce4602 (diff) | |
download | glibc-3387a425e65b839b68bd2973f6bc5ab22315cc5d.tar.gz glibc-3387a425e65b839b68bd2973f6bc5ab22315cc5d.tar.xz glibc-3387a425e65b839b68bd2973f6bc5ab22315cc5d.zip |
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.c | 79 |
1 files changed, 24 insertions, 55 deletions
diff --git a/linuxthreads/condvar.c b/linuxthreads/condvar.c index 6807522edc..91067d2d17 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; - } - } -} |