summaryrefslogtreecommitdiffstats
path: root/lib/libpthread/thread/thr_exit.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libpthread/thread/thr_exit.c')
-rw-r--r--lib/libpthread/thread/thr_exit.c39
1 files changed, 30 insertions, 9 deletions
diff --git a/lib/libpthread/thread/thr_exit.c b/lib/libpthread/thread/thr_exit.c
index c54dbda..a5f706d 100644
--- a/lib/libpthread/thread/thr_exit.c
+++ b/lib/libpthread/thread/thr_exit.c
@@ -29,6 +29,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
+ * $Id$
*/
#include <errno.h>
#include <unistd.h>
@@ -92,7 +93,12 @@ _thread_exit(char *fname, int lineno, char *string)
_thread_sys_write(2, s, strlen(s));
/* Force this process to exit: */
+ /* XXX - Do we want abort to be conditional on _PTHREADS_INVARIANTS? */
+#if defined(_PTHREADS_INVARIANTS)
+ abort();
+#else
_exit(1);
+#endif
}
void
@@ -129,22 +135,24 @@ pthread_exit(void *status)
}
/*
- * Guard against preemption by a scheduling signal. A change of
- * thread state modifies the waiting and priority queues.
+ * Defer signals to protect the scheduling queues from access
+ * by the signal handler:
*/
- _thread_kern_sched_defer();
+ _thread_kern_sig_defer();
/* Check if there are any threads joined to this one: */
- while ((pthread = _thread_queue_deq(&(_thread_run->join_queue))) != NULL) {
+ while ((pthread = TAILQ_FIRST(&(_thread_run->join_queue))) != NULL) {
+ /* Remove the thread from the queue: */
+ TAILQ_REMOVE(&_thread_run->join_queue, pthread, qe);
+
/* Wake the joined thread and let it detach this thread: */
PTHREAD_NEW_STATE(pthread,PS_RUNNING);
}
/*
- * Reenable preemption and yield if a scheduling signal
- * occurred while in the critical region.
+ * Undefer and handle pending signals, yielding if necessary:
*/
- _thread_kern_sched_undefer();
+ _thread_kern_sig_undefer();
/*
* Lock the garbage collector mutex to ensure that the garbage
@@ -154,8 +162,21 @@ pthread_exit(void *status)
PANIC("Cannot lock gc mutex");
/* Add this thread to the list of dead threads. */
- _thread_run->nxt_dead = _thread_dead;
- _thread_dead = _thread_run;
+ TAILQ_INSERT_HEAD(&_dead_list, _thread_run, dle);
+
+ /*
+ * Defer signals to protect the scheduling queues from access
+ * by the signal handler:
+ */
+ _thread_kern_sig_defer();
+
+ /* Remove this thread from the thread list: */
+ TAILQ_REMOVE(&_thread_list, _thread_run, tle);
+
+ /*
+ * Undefer and handle pending signals, yielding if necessary:
+ */
+ _thread_kern_sig_undefer();
/*
* Signal the garbage collector thread that there is something
OpenPOWER on IntegriCloud