diff options
author | mtm <mtm@FreeBSD.org> | 2003-06-29 21:21:52 +0000 |
---|---|---|
committer | mtm <mtm@FreeBSD.org> | 2003-06-29 21:21:52 +0000 |
commit | a810bddc153bedad5167855ef52ee1f9bc9f57cc (patch) | |
tree | be0db3a8ab1b26666404e965e5bd32a14afe8dd1 /lib/libthr/thread/thr_kern.c | |
parent | 44509f207ffb90a4c042b0c0dc5a3e9d028286e1 (diff) | |
download | FreeBSD-src-a810bddc153bedad5167855ef52ee1f9bc9f57cc.zip FreeBSD-src-a810bddc153bedad5167855ef52ee1f9bc9f57cc.tar.gz |
In a critical section, separate the aquisition of the thread lock
and the disabling of signals. What we are really interested in is
keeping track of recursive disabling of signals. We should not
be recursively acquiring thread locks. Any such situations should
be reorganized to not require a recursive lock.
Separating the two out also allows us to block signals independent of
acquiring thread locks. This will be needed in libthr in the near future when
we put the pieces together to protect libc functions that use pthread mutexes
and low level locks.
Diffstat (limited to 'lib/libthr/thread/thr_kern.c')
-rw-r--r-- | lib/libthr/thread/thr_kern.c | 40 |
1 files changed, 24 insertions, 16 deletions
diff --git a/lib/libthr/thread/thr_kern.c b/lib/libthr/thread/thr_kern.c index f45cae5..4a60bfe 100644 --- a/lib/libthr/thread/thr_kern.c +++ b/lib/libthr/thread/thr_kern.c @@ -55,6 +55,20 @@ static sigset_t restore; void _thread_critical_enter(pthread_t pthread) { + _thread_sigblock(); + _SPINLOCK(&pthread->lock); +} + +void +_thread_critical_exit(pthread_t pthread) +{ + _SPINUNLOCK(&pthread->lock); + _thread_sigunblock(); +} + +void +_thread_sigblock() +{ sigset_t set; sigset_t sav; @@ -62,18 +76,13 @@ _thread_critical_enter(pthread_t pthread) * Block all signals. */ SIGFILLSET(set); + SIGADDSET(set, SIGTHR); - /* - * We can not use the global 'restore' set until after we have - * acquired the giant lock. - */ - _SPINLOCK(&pthread->lock); - - /* If we are already in a critical section, just up the refcount */ - if (++curthread->crit_ref > 1) + /* If we have already blocked signals, just up the refcount */ + if (++curthread->signest > 1) return; - PTHREAD_ASSERT(curthread->crit_ref == 1, - ("Critical section reference count must be 1!")); + PTHREAD_ASSERT(curthread->signest == 1, + ("Blocked signal nesting level must be 1!")); if (__sys_sigprocmask(SIG_SETMASK, &set, &sav)) { _thread_printf(STDERR_FILENO, "Critical Enter: sig err %d\n", @@ -84,15 +93,15 @@ _thread_critical_enter(pthread_t pthread) } void -_thread_critical_exit(pthread_t pthread) +_thread_sigunblock() { sigset_t set; - /* We might be in a nested critical section */ - if (--curthread->crit_ref > 0) + /* We might be in a nested 'blocked signal' section */ + if (--curthread->signest > 0) return; - PTHREAD_ASSERT(curthread->crit_ref == 0, - ("Non-Zero critical section reference count.")); + PTHREAD_ASSERT(curthread->signest == 0, + ("Non-Zero blocked signal nesting level.")); /* * Restore signals. @@ -103,7 +112,6 @@ _thread_critical_exit(pthread_t pthread) errno); abort(); } - _SPINUNLOCK(&pthread->lock); } void |