Index: thread/thr_create.c =================================================================== RCS file: /home/ncvs/src/lib/libpthread/thread/thr_create.c,v retrieving revision 1.57 diff -u -r1.57 thr_create.c --- thread/thr_create.c 12 Aug 2004 12:12:12 -0000 1.57 +++ thread/thr_create.c 23 Oct 2004 05:40:25 -0000 @@ -234,6 +234,7 @@ new_thread->specific_data_count = 0; new_thread->cleanup = NULL; new_thread->flags = 0; + new_thread->tlflags = 0; new_thread->continuation = NULL; new_thread->wakeup_time.tv_sec = -1; new_thread->lock_switch = 0; Index: thread/thr_exit.c =================================================================== RCS file: /home/ncvs/src/lib/libpthread/thread/thr_exit.c,v retrieving revision 1.38 diff -u -r1.38 thr_exit.c --- thread/thr_exit.c 12 Aug 2004 12:12:12 -0000 1.38 +++ thread/thr_exit.c 23 Oct 2004 05:40:25 -0000 @@ -105,7 +105,20 @@ THR_SCHED_LOCK(curthread, curthread); curthread->flags |= THR_FLAGS_EXITING; THR_SCHED_UNLOCK(curthread, curthread); - + + /* + * To avoid signal-lost problem, if signals had already been + * delivered to us, handle it. we have already set EXITING flag + * so no new signals should be delivered to us. + * XXX this is not enough if signal was delivered just before + * thread called sigprocmask and masked it! in this case, we + * might have to re-post the signal by kill() if the signal + * is targeting process (not for a specified thread). + * Kernel has same signal-lost problem, a signal may be delivered + * to a thread which is on the way to call sigprocmask or thr_exit()! + */ + if (curthread->check_pending) + _thr_sig_check_pending(curthread); /* Save the return value: */ curthread->ret = status; while (curthread->cleanup != NULL) { Index: thread/thr_find_thread.c =================================================================== RCS file: /home/ncvs/src/lib/libpthread/thread/thr_find_thread.c,v retrieving revision 1.13 diff -u -r1.13 thr_find_thread.c --- thread/thr_find_thread.c 17 Jul 2003 23:02:30 -0000 1.13 +++ thread/thr_find_thread.c 23 Oct 2004 05:40:25 -0000 @@ -90,7 +90,7 @@ if (curthread != NULL) curthread->critical_count--; if ((thread->refcount == 0) && - (thread->flags & THR_FLAGS_GC_SAFE) != 0) + (thread->tlflags & TLFLAGS_GC_SAFE) != 0) THR_GCLIST_ADD(thread); KSE_LOCK_RELEASE(curkse, &_thread_list_lock); _kse_critical_leave(crit); Index: thread/thr_kern.c =================================================================== RCS file: /home/ncvs/src/lib/libpthread/thread/thr_kern.c,v retrieving revision 1.114 diff -u -r1.114 thr_kern.c --- thread/thr_kern.c 8 Oct 2004 22:57:30 -0000 1.114 +++ thread/thr_kern.c 23 Oct 2004 05:40:27 -0000 @@ -166,7 +166,7 @@ struct pthread_sigframe *psf); static int thr_timedout(struct pthread *thread, struct timespec *curtime); static void thr_unlink(struct pthread *thread); -static void thr_destroy(struct pthread *thread); +static void thr_destroy(struct pthread *curthread, struct pthread *thread); static void thread_gc(struct pthread *thread); static void kse_gc(struct pthread *thread); static void kseg_gc(struct pthread *thread); @@ -240,7 +240,7 @@ _thr_stack_free(&thread->attr); if (thread->specific != NULL) free(thread->specific); - thr_destroy(thread); + thr_destroy(curthread, thread); } } @@ -285,14 +285,14 @@ /* Free the free threads. */ while ((thread = TAILQ_FIRST(&free_threadq)) != NULL) { TAILQ_REMOVE(&free_threadq, thread, tle); - thr_destroy(thread); + thr_destroy(curthread, thread); } free_thread_count = 0; /* Free the to-be-gc'd threads. */ while ((thread = TAILQ_FIRST(&_thread_gc_list)) != NULL) { TAILQ_REMOVE(&_thread_gc_list, thread, gcle); - thr_destroy(thread); + thr_destroy(curthread, thread); } TAILQ_INIT(&gc_ksegq); _gc_count = 0; @@ -381,6 +381,7 @@ if (_lock_init(&_thread_list_lock, LCK_ADAPTIVE, _kse_lock_wait, _kse_lock_wakeup) != 0) PANIC("Unable to initialize thread list lock"); + _pthread_mutex_init(&_thr_ctor_mutex, NULL); active_kse_count = 0; active_kseg_count = 0; _gc_count = 0; @@ -1207,7 +1208,6 @@ thread->kseg = _kse_initial->k_kseg; thread->kse = _kse_initial; } - thread->flags |= THR_FLAGS_GC_SAFE; /* * We can't hold the thread list lock while holding the @@ -1216,6 +1216,7 @@ KSE_SCHED_UNLOCK(curkse, curkse->k_kseg); DBG_MSG("Adding thread %p to GC list\n", thread); KSE_LOCK_ACQUIRE(curkse, &_thread_list_lock); + thread->tlflags |= TLFLAGS_GC_SAFE; THR_GCLIST_ADD(thread); KSE_LOCK_RELEASE(curkse, &_thread_list_lock); if (sys_scope) { @@ -1255,7 +1256,7 @@ /* Check the threads waiting for GC. */ for (td = TAILQ_FIRST(&_thread_gc_list); td != NULL; td = td_next) { td_next = TAILQ_NEXT(td, gcle); - if ((td->flags & THR_FLAGS_GC_SAFE) == 0) + if ((td->tlflags & TLFLAGS_GC_SAFE) == 0) continue; else if (((td->attr.flags & PTHREAD_SCOPE_SYSTEM) != 0) && ((td->kse->k_kcb->kcb_kmbx.km_flags & KMF_DONE) == 0)) { @@ -2384,10 +2385,16 @@ if ((thread == NULL) && ((thread = malloc(sizeof(struct pthread))) != NULL)) { bzero(thread, sizeof(struct pthread)); + if (curthread) + _pthread_mutex_lock(&_thr_ctor_mutex); if ((thread->tcb = _tcb_ctor(thread, curthread == NULL)) == NULL) { + if (curthread) + _pthread_mutex_unlock(&_thr_ctor_mutex); free(thread); thread = NULL; } else { + if (curthread) + _pthread_mutex_unlock(&_thr_ctor_mutex); thread->siginfo = calloc(_SIG_MAXSIG, sizeof(siginfo_t)); /* @@ -2420,7 +2427,7 @@ thread->name = NULL; } if ((curthread == NULL) || (free_thread_count >= MAX_CACHED_THREADS)) { - thr_destroy(thread); + thr_destroy(curthread, thread); } else { /* Add the thread to the free thread list. */ crit = _kse_critical_enter(); @@ -2433,14 +2440,18 @@ } static void -thr_destroy(struct pthread *thread) +thr_destroy(struct pthread *curthread, struct pthread *thread) { int i; for (i = 0; i < MAX_THR_LOCKLEVEL; i++) _lockuser_destroy(&thread->lockusers[i]); _lock_destroy(&thread->lock); + if (curthread) + _pthread_mutex_lock(&_thr_ctor_mutex); _tcb_dtor(thread->tcb); + if (curthread) + _pthread_mutex_unlock(&_thr_ctor_mutex); free(thread->siginfo); free(thread); } Index: thread/thr_private.h =================================================================== RCS file: /home/ncvs/src/lib/libpthread/thread/thr_private.h,v retrieving revision 1.118 diff -u -r1.118 thr_private.h --- thread/thr_private.h 7 Aug 2004 15:15:38 -0000 1.118 +++ thread/thr_private.h 23 Oct 2004 05:40:28 -0000 @@ -753,9 +753,13 @@ #define THR_FLAGS_IN_RUNQ 0x0004 /* in run queue using pqe link */ #define THR_FLAGS_EXITING 0x0008 /* thread is exiting */ #define THR_FLAGS_SUSPENDED 0x0010 /* thread is suspended */ -#define THR_FLAGS_GC_SAFE 0x0020 /* thread safe for cleaning */ -#define THR_FLAGS_IN_TDLIST 0x0040 /* thread in all thread list */ -#define THR_FLAGS_IN_GCLIST 0x0080 /* thread in gc list */ + + /* Thread list flags; only set with thread list lock held. */ +#define TLFLAGS_GC_SAFE 0x0001 /* thread safe for cleaning */ +#define TLFLAGS_IN_TDLIST 0x0002 /* thread in all thread list */ +#define TLFLAGS_IN_GCLIST 0x0004 /* thread in gc list */ + int tlflags; + /* * Base priority is the user setable and retrievable priority * of the thread. It is only affected by explicit calls to @@ -897,30 +901,30 @@ * the gc list. */ #define THR_LIST_ADD(thrd) do { \ - if (((thrd)->flags & THR_FLAGS_IN_TDLIST) == 0) { \ + if (((thrd)->tlflags & TLFLAGS_IN_TDLIST) == 0) { \ TAILQ_INSERT_HEAD(&_thread_list, thrd, tle); \ _thr_hash_add(thrd); \ - (thrd)->flags |= THR_FLAGS_IN_TDLIST; \ + (thrd)->tlflags |= TLFLAGS_IN_TDLIST; \ } \ } while (0) #define THR_LIST_REMOVE(thrd) do { \ - if (((thrd)->flags & THR_FLAGS_IN_TDLIST) != 0) { \ + if (((thrd)->tlflags & TLFLAGS_IN_TDLIST) != 0) { \ TAILQ_REMOVE(&_thread_list, thrd, tle); \ _thr_hash_remove(thrd); \ - (thrd)->flags &= ~THR_FLAGS_IN_TDLIST; \ + (thrd)->tlflags &= ~TLFLAGS_IN_TDLIST; \ } \ } while (0) #define THR_GCLIST_ADD(thrd) do { \ - if (((thrd)->flags & THR_FLAGS_IN_GCLIST) == 0) { \ + if (((thrd)->tlflags & TLFLAGS_IN_GCLIST) == 0) { \ TAILQ_INSERT_HEAD(&_thread_gc_list, thrd, gcle);\ - (thrd)->flags |= THR_FLAGS_IN_GCLIST; \ + (thrd)->tlflags |= TLFLAGS_IN_GCLIST; \ _gc_count++; \ } \ } while (0) #define THR_GCLIST_REMOVE(thrd) do { \ - if (((thrd)->flags & THR_FLAGS_IN_GCLIST) != 0) { \ + if (((thrd)->tlflags & TLFLAGS_IN_GCLIST) != 0) { \ TAILQ_REMOVE(&_thread_gc_list, thrd, gcle); \ - (thrd)->flags &= ~THR_FLAGS_IN_GCLIST; \ + (thrd)->tlflags &= ~TLFLAGS_IN_GCLIST; \ _gc_count--; \ } \ } while (0) @@ -1006,6 +1010,9 @@ SCLASS TAILQ_HEAD(atfork_head, pthread_atfork) _thr_atfork_list; SCLASS pthread_mutex_t _thr_atfork_mutex; + +/* Lock for thread tcb constructor/destructor */ +SCLASS pthread_mutex_t _thr_ctor_mutex; /* Default thread attributes: */ SCLASS struct pthread_attr _pthread_attr_default Index: thread/thr_sig.c =================================================================== RCS file: /home/ncvs/src/lib/libpthread/thread/thr_sig.c,v retrieving revision 1.80 diff -u -r1.80 thr_sig.c --- thread/thr_sig.c 21 Oct 2004 03:42:24 -0000 1.80 +++ thread/thr_sig.c 23 Oct 2004 05:40:29 -0000 @@ -1199,8 +1199,7 @@ thr_sigframe_save(struct pthread *thread, struct pthread_sigframe *psf) { /* This has to initialize all members of the sigframe. */ - psf->psf_flags = - thread->flags & (THR_FLAGS_PRIVATE | THR_FLAGS_IN_TDLIST); + psf->psf_flags = thread->flags & THR_FLAGS_PRIVATE; psf->psf_interrupted = thread->interrupted; psf->psf_timeout = thread->timeout; psf->psf_state = thread->state;