1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-12-24 17:51:17 +03:00

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.
This commit is contained in:
Ulrich Drepper
1998-06-25 19:36:00 +00:00
parent d47aac3999
commit 3387a425e6
23 changed files with 633 additions and 512 deletions

View File

@@ -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;
}
}
}