diff options
author | deischen <deischen@FreeBSD.org> | 2003-05-24 02:29:25 +0000 |
---|---|---|
committer | deischen <deischen@FreeBSD.org> | 2003-05-24 02:29:25 +0000 |
commit | dc5114efb5a7accba1140bb50db1def228a37531 (patch) | |
tree | e99d3167d044ff37cf6b26fa4f4fe83140c8af79 /lib/libpthread/thread/thr_sig.c | |
parent | d8dec9f72fc70ddb0f6dc6547bc8207a1061187d (diff) | |
download | FreeBSD-src-dc5114efb5a7accba1140bb50db1def228a37531.zip FreeBSD-src-dc5114efb5a7accba1140bb50db1def228a37531.tar.gz |
Change low-level locking a bit so that we can tell if
a lock is being waitied on.
Fix a races in join and cancellation.
When trying to wait on a CV and the library is not yet
threaded, make it threaded so that waiting actually works.
When trying to nanosleep() and we're not threaded, just
call the system call nanosleep instead of adding the thread
to the wait queue.
Clean up adding/removing new threads to the "all threads queue",
assigning them unique ids, and tracking how many active threads
there are. Do it all when the thread is added to the scheduling
queue instead of making pthread_create() know how to do it.
Fix a race where a thread could be marked for signal delivery
but it could be exited before we actually add the signal to it.
Other minor cleanups and bug fixes.
Submitted by: davidxu
Approved by: re@ (blanket for libpthread)
Diffstat (limited to 'lib/libpthread/thread/thr_sig.c')
-rw-r--r-- | lib/libpthread/thread/thr_sig.c | 30 |
1 files changed, 22 insertions, 8 deletions
diff --git a/lib/libpthread/thread/thr_sig.c b/lib/libpthread/thread/thr_sig.c index 3ec0eca..da5b0b6 100644 --- a/lib/libpthread/thread/thr_sig.c +++ b/lib/libpthread/thread/thr_sig.c @@ -151,15 +151,24 @@ _thr_sig_dispatch(struct kse *curkse, int sig, siginfo_t *info) /* Some signals need special handling: */ handle_special_signals(curkse, sig); - - if ((thread = thr_sig_find(curkse, sig, info)) != NULL) { + stderr_debug("dispatch sig:%d\n", sig); + while ((thread = thr_sig_find(curkse, sig, info)) != NULL) { /* * Setup the target thread to receive the signal: */ DBG_MSG("Got signal %d, selecting thread %p\n", sig, thread); KSE_SCHED_LOCK(curkse, thread->kseg); - _thr_sig_add(thread, sig, info); - KSE_SCHED_UNLOCK(curkse, thread->kseg); + if ((thread->state == PS_DEAD) || + (thread->state == PS_DEADLOCK) || + THR_IS_EXITING(thread) || THR_IS_SUSPENDED(thread)) { + KSE_SCHED_UNLOCK(curkse, thread->kseg); + _thr_ref_delete(NULL, thread); + } else { + _thr_sig_add(thread, sig, info); + KSE_SCHED_UNLOCK(curkse, thread->kseg); + _thr_ref_delete(NULL, thread); + break; + } } } @@ -321,10 +330,14 @@ thr_sig_find(struct kse *curkse, int sig, siginfo_t *info) else if ((handler_installed != 0) && !sigismember(&pthread->tmbx.tm_context.uc_sigmask, sig)) { if (pthread->state == PS_SIGSUSPEND) { - if (suspended_thread == NULL) + if (suspended_thread == NULL) { suspended_thread = pthread; - } else if (signaled_thread == NULL) + suspended_thread->refcount++; + } + } else if (signaled_thread == NULL) { signaled_thread = pthread; + signaled_thread->refcount++; + } } KSE_SCHED_UNLOCK(curkse, pthread->kseg); } @@ -359,9 +372,10 @@ thr_sig_find(struct kse *curkse, int sig, siginfo_t *info) * We only deliver the signal to one thread; * give preference to the suspended thread: */ - if (suspended_thread != NULL) + if (suspended_thread != NULL) { pthread = suspended_thread; - else + _thr_ref_delete(NULL, signaled_thread); + } else pthread = signaled_thread; return (pthread); } |