diff options
author | deischen <deischen@FreeBSD.org> | 2003-05-29 17:10:45 +0000 |
---|---|---|
committer | deischen <deischen@FreeBSD.org> | 2003-05-29 17:10:45 +0000 |
commit | cccb8a341841afbb6950f77adfed8b5bf81138ae (patch) | |
tree | dd986910f07eda0fc0f920fe954d097068627fef /lib/libpthread | |
parent | 48c0de19de35c62a5516be4fe25f5dcf738dd5db (diff) | |
download | FreeBSD-src-cccb8a341841afbb6950f77adfed8b5bf81138ae.zip FreeBSD-src-cccb8a341841afbb6950f77adfed8b5bf81138ae.tar.gz |
Don't really spin on a spinlock; silently convert it to the same
low-level lock used by the libpthread implementation. In the
future, we'll eliminate spinlocks from libc but that will wait
until after 5.1-release.
Don't call an application signal handler if the handler is
the same as the library-installed handler. This seems to
be possible after a fork and is the cause of konsole hangs.
Approved by: re@ (jhb)
Diffstat (limited to 'lib/libpthread')
-rw-r--r-- | lib/libpthread/thread/thr_init.c | 1 | ||||
-rw-r--r-- | lib/libpthread/thread/thr_private.h | 3 | ||||
-rw-r--r-- | lib/libpthread/thread/thr_sig.c | 5 | ||||
-rw-r--r-- | lib/libpthread/thread/thr_spinlock.c | 78 |
4 files changed, 71 insertions, 16 deletions
diff --git a/lib/libpthread/thread/thr_init.c b/lib/libpthread/thread/thr_init.c index 5bfb3c7..433f246 100644 --- a/lib/libpthread/thread/thr_init.c +++ b/lib/libpthread/thread/thr_init.c @@ -515,6 +515,7 @@ init_private(void) if (_lock_init(&_keytable_lock, LCK_ADAPTIVE, _thr_lock_wait, _thr_lock_wakeup) != 0) PANIC("Cannot initialize thread specific keytable lock"); + _thr_spinlock_init(); /* Clear pending signals and get the process signal mask. */ sigemptyset(&_thr_proc_sigpending); diff --git a/lib/libpthread/thread/thr_private.h b/lib/libpthread/thread/thr_private.h index a6e8653..a6d3494 100644 --- a/lib/libpthread/thread/thr_private.h +++ b/lib/libpthread/thread/thr_private.h @@ -1114,6 +1114,7 @@ void _thr_sched_frame(struct pthread_sigframe *); void _thr_sched_switch(struct pthread *); void _thr_sched_switch_unlocked(struct pthread *); void _thr_set_timeout(const struct timespec *); +void _thr_seterrno(struct pthread *, int); void _thr_sig_handler(int, siginfo_t *, ucontext_t *); void _thr_sig_check_pending(struct pthread *); void _thr_sig_rundown(struct pthread *, ucontext_t *, @@ -1121,7 +1122,7 @@ void _thr_sig_rundown(struct pthread *, ucontext_t *, void _thr_sig_send(struct pthread *pthread, int sig); void _thr_sig_wrapper(void); void _thr_sigframe_restore(struct pthread *thread, struct pthread_sigframe *psf); -void _thr_seterrno(struct pthread *, int); +void _thr_spinlock_init(void); void _thr_enter_cancellation_point(struct pthread *); void _thr_leave_cancellation_point(struct pthread *); int _thr_setconcurrency(int new_level); diff --git a/lib/libpthread/thread/thr_sig.c b/lib/libpthread/thread/thr_sig.c index da5b0b6..49a1c39 100644 --- a/lib/libpthread/thread/thr_sig.c +++ b/lib/libpthread/thread/thr_sig.c @@ -175,7 +175,7 @@ _thr_sig_dispatch(struct kse *curkse, int sig, siginfo_t *info) void _thr_sig_handler(int sig, siginfo_t *info, ucontext_t *ucp) { - void (*sigfunc)(int, siginfo_t *, void *); + __siginfohandler_t *sigfunc; struct kse *curkse; curkse = _get_curkse(); @@ -184,7 +184,8 @@ _thr_sig_handler(int sig, siginfo_t *info, ucontext_t *ucp) sigfunc = _thread_sigact[sig - 1].sa_sigaction; ucp->uc_sigmask = _thr_proc_sigmask; if (((__sighandler_t *)sigfunc != SIG_DFL) && - ((__sighandler_t *)sigfunc != SIG_IGN)) { + ((__sighandler_t *)sigfunc != SIG_IGN) && + (sigfunc != (__siginfohandler_t *)_thr_sig_handler)) { if (((_thread_sigact[sig - 1].sa_flags & SA_SIGINFO) != 0) || (info == NULL)) (*(sigfunc))(sig, info, ucp); diff --git a/lib/libpthread/thread/thr_spinlock.c b/lib/libpthread/thread/thr_spinlock.c index 56691dd..6beaf66 100644 --- a/lib/libpthread/thread/thr_spinlock.c +++ b/lib/libpthread/thread/thr_spinlock.c @@ -40,6 +40,20 @@ #include "spinlock.h" #include "thr_private.h" +#define MAX_SPINLOCKS 5 + +struct spinlock_extra { + struct lock lock; + kse_critical_t crit; +}; + +static void init_spinlock(spinlock_t *lck); + +static struct lock spinlock_static_lock; +static struct spinlock_extra extra[MAX_SPINLOCKS]; +static int spinlock_count = 0; +static int initialized = 0; + /* * These are for compatability only. Spinlocks of this type * are deprecated. @@ -48,12 +62,13 @@ void _spinunlock(spinlock_t *lck) { + struct spinlock_extra *extra; kse_critical_t crit; - crit = (kse_critical_t)lck->fname; - atomic_store_rel_long(&lck->access_lock, 0); - if (crit != NULL) - _kse_critical_leave(crit); + extra = (struct spinlock_extra *)lck->fname; + crit = extra->crit; + KSE_LOCK_RELEASE(_get_curkse(), &extra->lock); + _kse_critical_leave(crit); } @@ -66,21 +81,21 @@ _spinunlock(spinlock_t *lck) void _spinlock(spinlock_t *lck) { + struct spinlock_extra *extra; kse_critical_t crit; + THR_ASSERT(__isthreaded != 0, "Spinlock called when not threaded."); + THR_ASSERT(initialized != 0, "Spinlocks not initialized."); /* * Try to grab the lock and loop if another thread grabs * it before we do. */ - if (_kse_isthreaded()) - crit = _kse_critical_enter(); - else - crit = NULL; - while(_atomic_lock(&lck->access_lock)) { - while (lck->access_lock) - ; - } - lck->fname = (char *)crit; + crit = _kse_critical_enter(); + if (lck->fname == NULL) + init_spinlock(lck); + extra = (struct spinlock_extra *)lck->fname; + KSE_LOCK_ACQUIRE(_get_curkse(), &extra->lock); + extra->crit = crit; } /* @@ -98,3 +113,40 @@ _spinlock_debug(spinlock_t *lck, char *fname, int lineno) { _spinlock(lck); } + +static void +init_spinlock(spinlock_t *lck) +{ + struct kse *curkse = _get_curkse(); + + KSE_LOCK_ACQUIRE(curkse, &spinlock_static_lock); + if ((lck->fname == NULL) && (spinlock_count < MAX_SPINLOCKS)) { + lck->fname = (char *)&extra[spinlock_count]; + spinlock_count++; + } + KSE_LOCK_RELEASE(curkse, &spinlock_static_lock); + THR_ASSERT(lck->fname != NULL, "Exceeded max spinlocks"); +} + +void +_thr_spinlock_init(void) +{ + int i; + + if (initialized != 0) { + _lock_destroy(&spinlock_static_lock); + for (i = 0; i < MAX_SPINLOCKS; i++) { + _lock_destroy(&extra[i].lock); + } + } + + if (_lock_init(&spinlock_static_lock, LCK_ADAPTIVE, + _kse_lock_wait, _kse_lock_wakeup) != 0) + PANIC("Cannot initialize spinlock_static_lock"); + for (i = 0; i < MAX_SPINLOCKS; i++) { + if (_lock_init(&extra[i].lock, LCK_ADAPTIVE, + _kse_lock_wait, _kse_lock_wakeup) != 0) + PANIC("Cannot initialize spinlock extra"); + } + initialized = 1; +} |