summaryrefslogtreecommitdiffstats
path: root/lib/libpthread
diff options
context:
space:
mode:
authordeischen <deischen@FreeBSD.org>2003-05-29 17:10:45 +0000
committerdeischen <deischen@FreeBSD.org>2003-05-29 17:10:45 +0000
commitcccb8a341841afbb6950f77adfed8b5bf81138ae (patch)
treedd986910f07eda0fc0f920fe954d097068627fef /lib/libpthread
parent48c0de19de35c62a5516be4fe25f5dcf738dd5db (diff)
downloadFreeBSD-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.c1
-rw-r--r--lib/libpthread/thread/thr_private.h3
-rw-r--r--lib/libpthread/thread/thr_sig.c5
-rw-r--r--lib/libpthread/thread/thr_spinlock.c78
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;
+}
OpenPOWER on IntegriCloud