summaryrefslogtreecommitdiffstats
path: root/lib/libthr/thread/thr_create.c
diff options
context:
space:
mode:
authordavidxu <davidxu@FreeBSD.org>2006-01-05 13:51:22 +0000
committerdavidxu <davidxu@FreeBSD.org>2006-01-05 13:51:22 +0000
commitd6c88c0f27b6e6c0006896e7fb3e47f0f7e992d8 (patch)
tree7cdbbed3366ccd9eec189ba14d2d48ff355912e4 /lib/libthr/thread/thr_create.c
parente065d5a1853d5ac2323fc116b1b2462841c0160e (diff)
downloadFreeBSD-src-d6c88c0f27b6e6c0006896e7fb3e47f0f7e992d8.zip
FreeBSD-src-d6c88c0f27b6e6c0006896e7fb3e47f0f7e992d8.tar.gz
Refine thread suspension code, now thread suspension is a blockable
operation, the caller is blocked util target threads are really suspended, also avoid suspending a thread when it is holding a critical lock. Fix a bug in _thr_ref_delete which tests a never set flag.
Diffstat (limited to 'lib/libthr/thread/thr_create.c')
-rw-r--r--lib/libthr/thread/thr_create.c82
1 files changed, 53 insertions, 29 deletions
diff --git a/lib/libthr/thread/thr_create.c b/lib/libthr/thread/thr_create.c
index 8a59ef7..cc0d84e 100644
--- a/lib/libthr/thread/thr_create.c
+++ b/lib/libthr/thread/thr_create.c
@@ -37,9 +37,7 @@
#include "thr_private.h"
-static void free_thread(struct pthread *curthread, struct pthread *thread);
static int create_stack(struct pthread_attr *pattr);
-static void free_stack(struct pthread *curthread, struct pthread_attr *pattr);
static void thread_start(struct pthread *curthread);
__weak_reference(_pthread_create, pthread_create);
@@ -50,7 +48,8 @@ _pthread_create(pthread_t * thread, const pthread_attr_t * attr,
{
struct pthread *curthread, *new_thread;
struct thr_param param;
- int ret = 0, locked;
+ int ret = 0, locked, create_suspended;
+ sigset_t set, oset;
_thr_check_init();
@@ -133,11 +132,20 @@ _pthread_create(pthread_t * thread, const pthread_attr_t * attr,
TAILQ_INIT(&new_thread->pri_mutexq);
/* Initialise hooks in the thread structure: */
- if (new_thread->attr.suspend == THR_CREATE_SUSPENDED)
+ if (new_thread->attr.suspend == THR_CREATE_SUSPENDED) {
new_thread->flags = THR_FLAGS_NEED_SUSPEND;
+ create_suspended = 1;
+ } else {
+ create_suspended = 0;
+ }
+
new_thread->state = PS_RUNNING;
+ if (new_thread->attr.flags & PTHREAD_CREATE_DETACHED)
+ new_thread->tlflags |= TLFLAGS_DETACHED;
+
/* Add the new thread. */
+ new_thread->refcount = 1;
_thr_link(curthread, new_thread);
/* Return thread pointer eariler so that new thread can use it. */
(*thread) = new_thread;
@@ -157,13 +165,34 @@ _pthread_create(pthread_t * thread, const pthread_attr_t * attr,
param.flags = 0;
if (new_thread->attr.flags & PTHREAD_SCOPE_SYSTEM)
param.flags |= THR_SYSTEM_SCOPE;
+
/* Schedule the new thread. */
+ if (create_suspended) {
+ SIGFILLSET(set);
+ SIGDELSET(set, SIGTRAP);
+ __sys_sigprocmask(SIG_SETMASK, &set, &oset);
+ new_thread->sigmask = oset;
+ }
+
ret = thr_new(&param, sizeof(param));
+
+ if (create_suspended)
+ __sys_sigprocmask(SIG_SETMASK, &oset, NULL);
+
if (ret != 0) {
- if (locked)
- THR_THREAD_UNLOCK(curthread, new_thread);
- _thr_unlink(curthread, new_thread);
- free_thread(curthread, new_thread);
+ if (!locked)
+ THR_THREAD_LOCK(curthread, new_thread);
+ new_thread->state = PS_DEAD;
+ new_thread->tid = TID_TERMINATED;
+ if (new_thread->flags & THR_FLAGS_NEED_SUSPEND) {
+ new_thread->cycle++;
+ _thr_umtx_wake(&new_thread->cycle, INT_MAX);
+ }
+ THR_THREAD_UNLOCK(curthread, new_thread);
+ THREAD_LIST_LOCK(curthread);
+ new_thread->tlflags |= TLFLAGS_DETACHED;
+ _thr_ref_delete_unlocked(curthread, new_thread);
+ THREAD_LIST_UNLOCK(curthread);
(*thread) = 0;
ret = EAGAIN;
} else if (locked) {
@@ -173,14 +202,6 @@ _pthread_create(pthread_t * thread, const pthread_attr_t * attr,
return (ret);
}
-static void
-free_thread(struct pthread *curthread, struct pthread *thread)
-{
- free_stack(curthread, &thread->attr);
- curthread->tid = TID_TERMINATED;
- _thr_free(curthread, thread);
-}
-
static int
create_stack(struct pthread_attr *pattr)
{
@@ -198,22 +219,25 @@ create_stack(struct pthread_attr *pattr)
}
static void
-free_stack(struct pthread *curthread, struct pthread_attr *pattr)
-{
- if ((pattr->flags & THR_STACK_USER) == 0) {
- THREAD_LIST_LOCK(curthread);
- /* Stack routines don't use malloc/free. */
- _thr_stack_free(pattr);
- THREAD_LIST_UNLOCK(curthread);
- }
-}
-
-static void
thread_start(struct pthread *curthread)
{
- if (curthread->flags & THR_FLAGS_NEED_SUSPEND)
- _thr_suspend_check(curthread);
+ if (curthread->attr.suspend == THR_CREATE_SUSPENDED) {
+ sigset_t set = curthread->sigmask;
+ _thr_ast(curthread);
+
+ /*
+ * Parent thread have stored signal mask for us,
+ * we should restore it now.
+ */
+ sigprocmask(SIG_SETMASK, &set, NULL);
+ }
+
+ /*
+ * This is used as a serialization point to allow parent
+ * to report 'new thread' event to debugger before the thread
+ * does real work.
+ */
THR_LOCK(curthread);
THR_UNLOCK(curthread);
OpenPOWER on IntegriCloud