diff options
author | jasone <jasone@FreeBSD.org> | 2000-06-14 17:17:41 +0000 |
---|---|---|
committer | jasone <jasone@FreeBSD.org> | 2000-06-14 17:17:41 +0000 |
commit | 9f479e9f39861a77981b3e6234e796caa25cfe0f (patch) | |
tree | 25b4c819ee7794359e6c426e91cd15c2c56a2f49 /lib/libpthread/thread/thr_cond.c | |
parent | cc22f14b179a55f7686e798febd938bfef76c982 (diff) | |
download | FreeBSD-src-9f479e9f39861a77981b3e6234e796caa25cfe0f.zip FreeBSD-src-9f479e9f39861a77981b3e6234e796caa25cfe0f.tar.gz |
pthread_mutex_lock(), pthread_cond_trywait(), and pthread_cond_wait() are
not allowed to return EINTR, but use of pthread_suspend_np() could cause
EINTR to be returned. To fix this, restructure pthread_suspend_np() so that
it does not interrupt a thread that is waiting on a mutex or condition, and
keep enough state around that pthread_resume_np() can fix things up
afterwards.
Reviewed by: deischen
Diffstat (limited to 'lib/libpthread/thread/thr_cond.c')
-rw-r--r-- | lib/libpthread/thread/thr_cond.c | 28 |
1 files changed, 22 insertions, 6 deletions
diff --git a/lib/libpthread/thread/thr_cond.c b/lib/libpthread/thread/thr_cond.c index 78ee042..49062be 100644 --- a/lib/libpthread/thread/thr_cond.c +++ b/lib/libpthread/thread/thr_cond.c @@ -285,7 +285,6 @@ pthread_cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex) if (interrupted != 0) { if (_thread_run->continuation != NULL) _thread_run->continuation((void *) _thread_run); - rval = EINTR; } _thread_leave_cancellation_point(); @@ -455,7 +454,6 @@ pthread_cond_timedwait(pthread_cond_t * cond, pthread_mutex_t * mutex, if (interrupted != 0) { if (_thread_run->continuation != NULL) _thread_run->continuation((void *) _thread_run); - rval = EINTR; } _thread_leave_cancellation_point(); @@ -489,9 +487,18 @@ pthread_cond_signal(pthread_cond_t * cond) switch ((*cond)->c_type) { /* Fast condition variable: */ case COND_TYPE_FAST: - if ((pthread = cond_queue_deq(*cond)) != NULL) - /* Allow the thread to run: */ - PTHREAD_NEW_STATE(pthread,PS_RUNNING); + if ((pthread = cond_queue_deq(*cond)) != NULL) { + /* + * Unless the thread is currently suspended, + * allow it to run. If the thread is suspended, + * make a note that the thread isn't in a wait + * queue any more. + */ + if (pthread->state != PS_SUSPENDED) + PTHREAD_NEW_STATE(pthread,PS_RUNNING); + else + pthread->suspended = SUSP_NOWAIT; + } /* Check for no more waiters: */ if (TAILQ_FIRST(&(*cond)->c_queue) == NULL) @@ -546,7 +553,16 @@ pthread_cond_broadcast(pthread_cond_t * cond) * condition queue: */ while ((pthread = cond_queue_deq(*cond)) != NULL) { - PTHREAD_NEW_STATE(pthread,PS_RUNNING); + /* + * Unless the thread is currently suspended, + * allow it to run. If the thread is suspended, + * make a note that the thread isn't in a wait + * queue any more. + */ + if (pthread->state != PS_SUSPENDED) + PTHREAD_NEW_STATE(pthread,PS_RUNNING); + else + pthread->suspended = SUSP_NOWAIT; } /* There are no more waiting threads: */ |