summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorMarco S Hyman <marc@cvs.openbsd.org>2003-01-24 21:03:16 +0000
committerMarco S Hyman <marc@cvs.openbsd.org>2003-01-24 21:03:16 +0000
commitc2d1f9d7206a0c18bda06f5221e4803b0c899249 (patch)
tree6f660d4c630b91051063dba780382b9b9beb9f7f /lib
parent0452d1ce15ba874fc9fe42f63b8e3a714ed3d91b (diff)
save and restore fp state when switching threads. This, with
an arch/i386 patch previously commited and arch/sparc64 patches from jason@ make the preemption_float test pass on those two architectures. Do not run signal handlers for a thread until the thread has been made current, ensuring the proper context. Solves several (if not all) of the '_pq_insert_tail: Already in priority queue' problems.
Diffstat (limited to 'lib')
-rw-r--r--lib/libpthread/uthread/pthread_private.h4
-rw-r--r--lib/libpthread/uthread/uthread_kern.c80
-rw-r--r--lib/libpthread/uthread/uthread_sig.c39
3 files changed, 46 insertions, 77 deletions
diff --git a/lib/libpthread/uthread/pthread_private.h b/lib/libpthread/uthread/pthread_private.h
index 83389b6008b..78d34b82804 100644
--- a/lib/libpthread/uthread/pthread_private.h
+++ b/lib/libpthread/uthread/pthread_private.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pthread_private.h,v 1.40 2002/12/11 23:21:19 marc Exp $ */
+/* $OpenBSD: pthread_private.h,v 1.41 2003/01/24 21:03:15 marc Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>.
* All rights reserved.
@@ -1073,7 +1073,7 @@ struct pthread *_get_curthread(void);
void _set_curthread(struct pthread *);
int _thread_create(pthread_t *, const pthread_attr_t *,
void *(*start_routine)(void *), void *,pthread_t);
-void _dispatch_signals(pthread_t, struct sigcontext *);
+void _dispatch_signals(struct sigcontext *);
void _thread_signal(pthread_t, int);
int _mutex_cv_lock(pthread_mutex_t *);
int _mutex_cv_unlock(pthread_mutex_t *);
diff --git a/lib/libpthread/uthread/uthread_kern.c b/lib/libpthread/uthread/uthread_kern.c
index cf1a6dcf6ac..9930098a974 100644
--- a/lib/libpthread/uthread/uthread_kern.c
+++ b/lib/libpthread/uthread/uthread_kern.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_kern.c,v 1.23 2002/11/04 21:28:49 marc Exp $ */
+/* $OpenBSD: uthread_kern.c,v 1.24 2003/01/24 21:03:15 marc Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -115,11 +115,6 @@ _thread_kern_sched(struct sigcontext * scp)
memcpy(&curthread->saved_sigcontext, scp,
sizeof(curthread->saved_sigcontext));
- /*
- * Save floating point state.
- */
- _thread_machdep_save_float_state(&curthread->_machdep);
-
/* Flag the signal context as the last state saved: */
curthread->sig_saved = 1;
} else
@@ -130,6 +125,9 @@ _thread_kern_sched(struct sigcontext * scp)
if ((curthread->flags & PTHREAD_FLAGS_PRIVATE) == 0)
_last_user_thread = curthread;
+ /* Save floating point state. */
+ _thread_machdep_save_float_state(&curthread->_machdep);
+
/* Save errno. */
curthread->error = errno;
@@ -501,41 +499,38 @@ _thread_kern_sched(struct sigcontext * scp)
/* Restore errno. */
errno = curthread->error;
+ /* Restore floating point state. */
+ _thread_machdep_restore_float_state(&curthread->_machdep);
+
/*
* Restore the new thread, saving current.
*/
_thread_machdep_switch(&curthread->_machdep,
- &old_thread_run->_machdep);
-
- /* Check if a signal context was saved: */
- if (curthread->sig_saved == 1) {
- /*
- * Restore floating point state.
- */
- _thread_machdep_restore_float_state(&curthread->_machdep);
-
- /*
- * Do a sigreturn to restart the thread that
- * was interrupted by a signal:
- */
- _thread_kern_in_sched = 0;
+ &old_thread_run->_machdep);
- /*
- * If we had a context switch, run any
- * installed switch hooks.
- */
- if ((_sched_switch_hook != NULL) &&
- (_last_user_thread != curthread)) {
- _thread_run_switch_hook(_last_user_thread,
- curthread);
- }
+ /*
+ * Process any pending signals for the thread we
+ * just switched to.
+ */
+ _thread_kern_in_sched = 0;
+ _dispatch_signals(scp);
+
+ /* run any installed switch-hooks */
+ if ((_sched_switch_hook != NULL) &&
+ (_last_user_thread != curthread)) {
+ _thread_run_switch_hook(_last_user_thread,
+ curthread);
+ }
- if (((curthread->cancelflags &
- PTHREAD_AT_CANCEL_POINT) == 0) &&
- ((curthread->cancelflags &
- PTHREAD_CANCEL_ASYNCHRONOUS) != 0))
- pthread_testcancel();
+ /* check for thread cancellation */
+ if (((curthread->cancelflags &
+ PTHREAD_AT_CANCEL_POINT) == 0) &&
+ ((curthread->cancelflags &
+ PTHREAD_CANCEL_ASYNCHRONOUS) != 0))
+ pthread_testcancel();
+ /* Check if a signal context was saved: */
+ if (curthread->sig_saved == 1) {
/* return to signal handler. This code
should be:
_thread_sys_sigreturn(&curthread->saved_sigcontext);
@@ -543,22 +538,7 @@ _thread_kern_sched(struct sigcontext * scp)
sparc */
return;
} else {
- /*
- * This is the normal way out of the scheduler.
- */
- _thread_kern_in_sched = 0;
-
- if (_sched_switch_hook != NULL) {
- /* Run the installed switch hook: */
- _thread_run_switch_hook(_last_user_thread,
- curthread);
- }
-
- if (((curthread->cancelflags &
- PTHREAD_AT_CANCEL_POINT) == 0) &&
- ((curthread->cancelflags &
- PTHREAD_CANCEL_ASYNCHRONOUS) != 0))
- pthread_testcancel();
+ /* This is the normal way out */
return;
}
diff --git a/lib/libpthread/uthread/uthread_sig.c b/lib/libpthread/uthread/uthread_sig.c
index 1d64e077cde..17eef3fa38e 100644
--- a/lib/libpthread/uthread/uthread_sig.c
+++ b/lib/libpthread/uthread/uthread_sig.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_sig.c,v 1.16 2002/11/08 23:18:25 todd Exp $ */
+/* $OpenBSD: uthread_sig.c,v 1.17 2003/01/24 21:03:15 marc Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -75,8 +75,8 @@ _thread_sig_process(int sig, struct sigcontext * scp)
locked = 1;
if (locked || _thread_sigact[sig - 1].sa_flags & SA_NODEFER) {
- _thread_sig_handle(sig, scp);
pending_sigs[sig - 1] = 0;
+ _thread_sig_handle(sig, scp);
} else
check_pending = 1;
if (locked)
@@ -167,7 +167,7 @@ _thread_sig_handler(int sig, siginfo_t *info, struct sigcontext * scp)
signal_lock = _SPINLOCK_UNLOCKED;
for (i = 1; i < NSIG; i++)
if (pending_sigs[i - 1])
- _thread_sig_process(i, scp);
+ _thread_sig_process(i, scp);
}
}
@@ -268,22 +268,14 @@ _thread_sig_handle(int sig, struct sigcontext * scp)
pthread->sig_defer_count--;
}
/*
- * give each thread a chance to dispatch pending
- * signals.
+ * Give the current thread a chance to dispatch
+ * the signals. Other threads will get thier
+ * chance (if the signal is still pending) later.
*/
- TAILQ_FOREACH(pthread, &_thread_list, tle) {
- /* Current thread inside critical region? */
- if (curthread->sig_defer_count > 0)
- pthread->sig_defer_count++;
- _dispatch_signals(pthread, scp);
- if (curthread->sig_defer_count > 0)
- pthread->sig_defer_count--;
- }
+ _dispatch_signals(scp);
+
}
}
-
- /* Returns nothing. */
- return;
}
/* Perform thread specific actions in response to a signal: */
@@ -385,12 +377,12 @@ _thread_signal(pthread_t pthread, int sig)
}
/*
- * possibly dispatch a signal to the given thread.
+ * possibly dispatch a signal to the current thread.
*/
void
-_dispatch_signals(pthread_t pthread, struct sigcontext * scp)
+_dispatch_signals(struct sigcontext * scp)
{
- pthread_t pthread_saved;
+ struct pthread *curthread = _get_curthread();
struct sigaction act;
void (*action)(int, siginfo_t *, void *);
int i;
@@ -399,7 +391,7 @@ _dispatch_signals(pthread_t pthread, struct sigcontext * scp)
* Check if there are pending signals for the running
* thread that aren't blocked:
*/
- if ((pthread->sigpend & ~pthread->sigmask) != 0)
+ if ((curthread->sigpend & ~curthread->sigmask) != 0)
/* Look for all possible pending signals: */
for (i = 1; i < NSIG; i++)
/*
@@ -408,8 +400,8 @@ _dispatch_signals(pthread_t pthread, struct sigcontext * scp)
*/
if (_thread_sigact[i - 1].sa_handler != SIG_DFL &&
_thread_sigact[i - 1].sa_handler != SIG_IGN &&
- sigismember(&pthread->sigpend,i) &&
- !sigismember(&pthread->sigmask,i)) {
+ sigismember(&curthread->sigpend,i) &&
+ !sigismember(&curthread->sigmask,i)) {
action = _thread_sigact[i - 1].sa_sigaction;
_clear_pending_flag(i);
@@ -426,10 +418,7 @@ _dispatch_signals(pthread_t pthread, struct sigcontext * scp)
* Dispatch the signal via the custom signal
* handler.
*/
- pthread_saved = _get_curthread();
- _set_curthread(pthread);
(*action)(i, &info_queue[i - 1], scp);
- _set_curthread(pthread_saved);
}
}
#endif