diff options
Diffstat (limited to 'nsprpub/pr/src/pthreads/ptthread.c')
-rw-r--r-- | nsprpub/pr/src/pthreads/ptthread.c | 158 |
1 files changed, 149 insertions, 9 deletions
diff --git a/nsprpub/pr/src/pthreads/ptthread.c b/nsprpub/pr/src/pthreads/ptthread.c index 6046d5d8d2..9e12606ea3 100644 --- a/nsprpub/pr/src/pthreads/ptthread.c +++ b/nsprpub/pr/src/pthreads/ptthread.c @@ -9,7 +9,7 @@ ** Exports: ptthread.h */ -#if defined(_PR_PTHREADS) +#if defined(_PR_PTHREADS) || defined(_PR_DCETHREADS) #include "prlog.h" #include "primpl.h" @@ -58,7 +58,7 @@ static struct _PT_Bookeeping pthread_key_t key; /* thread private data key */ PRBool keyCreated; /* whether 'key' should be deleted */ PRThread *first, *last; /* list of threads we know about */ -#if _POSIX_THREAD_PRIORITY_SCHEDULING > 0 +#if defined(_PR_DCETHREADS) || _POSIX_THREAD_PRIORITY_SCHEDULING > 0 PRInt32 minPrio, maxPrio; /* range of scheduling priorities */ #endif } pt_book = {0}; @@ -67,7 +67,7 @@ static void _pt_thread_death(void *arg); static void _pt_thread_death_internal(void *arg, PRBool callDestructors); static void init_pthread_gc_support(void); -#if _POSIX_THREAD_PRIORITY_SCHEDULING > 0 +#if defined(_PR_DCETHREADS) || _POSIX_THREAD_PRIORITY_SCHEDULING > 0 static PRIntn pt_PriorityMap(PRThreadPriority pri) { #ifdef NTO @@ -148,6 +148,21 @@ static void *_pt_root(void *arg) } #endif + /* + ** DCE Threads can't detach during creation, so do it late. + ** I would like to do it only here, but that doesn't seem + ** to work. + */ +#if defined(_PR_DCETHREADS) + if (detached) + { + /* pthread_detach() modifies its argument, so we must pass a copy */ + pthread_t self = id; + rv = pthread_detach(&self); + PR_ASSERT(0 == rv); + } +#endif /* defined(_PR_DCETHREADS) */ + /* Set up the thread stack information */ _PR_InitializeStack(thred->stack); @@ -314,7 +329,7 @@ static PRThread* _PR_CreateThread( if (EPERM != pt_schedpriv) { -#if _POSIX_THREAD_PRIORITY_SCHEDULING > 0 +#if !defined(_PR_DCETHREADS) && _POSIX_THREAD_PRIORITY_SCHEDULING > 0 struct sched_param schedule; #endif @@ -325,7 +340,10 @@ static PRThread* _PR_CreateThread( /* Use the default scheduling policy */ -#if _POSIX_THREAD_PRIORITY_SCHEDULING > 0 +#if defined(_PR_DCETHREADS) + rv = pthread_attr_setprio(&tattr, pt_PriorityMap(priority)); + PR_ASSERT(0 == rv); +#elif _POSIX_THREAD_PRIORITY_SCHEDULING > 0 rv = pthread_attr_getschedparam(&tattr, &schedule); PR_ASSERT(0 == rv); schedule.sched_priority = pt_PriorityMap(priority); @@ -335,13 +353,19 @@ static PRThread* _PR_CreateThread( rv = pthread_attr_setschedpolicy(&tattr, SCHED_RR); /* Round Robin */ PR_ASSERT(0 == rv); #endif -#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING > 0 */ +#endif /* !defined(_PR_DCETHREADS) */ } + /* + * DCE threads can't set detach state before creating the thread. + * AIX can't set detach late. Why can't we all just get along? + */ +#if !defined(_PR_DCETHREADS) rv = pthread_attr_setdetachstate(&tattr, ((PR_JOINABLE_THREAD == state) ? PTHREAD_CREATE_JOINABLE : PTHREAD_CREATE_DETACHED)); PR_ASSERT(0 == rv); +#endif /* !defined(_PR_DCETHREADS) */ /* * If stackSize is 0, we use the default pthread stack size. @@ -432,6 +456,7 @@ static PRThread* _PR_CreateThread( */ rv = _PT_PTHREAD_CREATE(&id, tattr, _pt_root, thred); +#if !defined(_PR_DCETHREADS) if (EPERM == rv) { #if defined(IRIX) @@ -457,10 +482,15 @@ static PRThread* _PR_CreateThread( #endif /* IRIX */ rv = _PT_PTHREAD_CREATE(&id, tattr, _pt_root, thred); } +#endif if (0 != rv) { +#if defined(_PR_DCETHREADS) + PRIntn oserr = errno; +#else PRIntn oserr = rv; +#endif PR_Lock(pt_book.ml); if (thred->state & PT_THREAD_SYSTEM) pt_book.system -= 1; @@ -572,6 +602,10 @@ PR_IMPLEMENT(PRStatus) PR_JoinThread(PRThread *thred) PR_ASSERT(rv == 0 && result == NULL); if (0 == rv) { +#ifdef _PR_DCETHREADS + rv = pthread_detach(&id); + PR_ASSERT(0 == rv); +#endif /* * PR_FALSE, because the thread already called the TPD * destructors before exiting _pt_root. @@ -659,7 +693,10 @@ PR_IMPLEMENT(void) PR_SetThreadPriority(PRThread *thred, PRThreadPriority newPri else if ((PRIntn)PR_PRIORITY_LAST < (PRIntn)newPri) newPri = PR_PRIORITY_LAST; -#if _POSIX_THREAD_PRIORITY_SCHEDULING > 0 +#if defined(_PR_DCETHREADS) + rv = pthread_setprio(thred->id, pt_PriorityMap(newPri)); + /* pthread_setprio returns the old priority */ +#elif _POSIX_THREAD_PRIORITY_SCHEDULING > 0 if (EPERM != pt_schedpriv) { int policy; @@ -890,7 +927,7 @@ void _PR_InitThreads( pthread_init(); #endif -#if _POSIX_THREAD_PRIORITY_SCHEDULING > 0 +#if defined(_PR_DCETHREADS) || _POSIX_THREAD_PRIORITY_SCHEDULING > 0 #if defined(FREEBSD) { pthread_attr_t attr; @@ -1124,7 +1161,11 @@ PR_IMPLEMENT(void) PR_ProcessExit(PRIntn status) PR_IMPLEMENT(PRUint32) PR_GetThreadID(PRThread *thred) { +#if defined(_PR_DCETHREADS) + return (PRUint32)&thred->id; /* this is really a sham! */ +#else return (PRUint32)thred->id; /* and I don't know what they will do with it */ +#endif } /* @@ -1156,6 +1197,18 @@ PR_SetThreadDumpProc(PRThread* thread, PRThreadDumpProc dump, void *arg) * Garbage collection support follows. */ +#if defined(_PR_DCETHREADS) + +/* + * statics for Garbage Collection support. We don't need to protect these + * signal masks since the garbage collector itself is protected by a lock + * and multiple threads will not be garbage collecting at the same time. + */ +static sigset_t javagc_vtalarm_sigmask; +static sigset_t javagc_intsoff_sigmask; + +#else /* defined(_PR_DCETHREADS) */ + /* a bogus signal mask for forcing a timed wait */ /* Not so bogus in AIX as we really do a sigwait */ static sigset_t sigwait_set; @@ -1171,6 +1224,8 @@ static void suspend_signal_handler(PRIntn sig); static void null_signal_handler(PRIntn sig); #endif +#endif /* defined(_PR_DCETHREADS) */ + /* * Linux pthreads use SIGUSR1 and SIGUSR2 internally, which * conflict with the use of these two signals in our GC support. @@ -1181,6 +1236,12 @@ static void init_pthread_gc_support(void) #ifndef SYMBIAN PRIntn rv; +#if defined(_PR_DCETHREADS) + rv = sigemptyset(&javagc_vtalarm_sigmask); + PR_ASSERT(0 == rv); + rv = sigaddset(&javagc_vtalarm_sigmask, SIGVTALRM); + PR_ASSERT(0 == rv); +#else /* defined(_PR_DCETHREADS) */ { struct sigaction sigact_usr2; @@ -1208,6 +1269,7 @@ static void init_pthread_gc_support(void) PR_ASSERT(0 ==rv); } #endif /* defined(PT_NO_SIGTIMEDWAIT) */ +#endif /* defined(_PR_DCETHREADS) */ #endif /* SYMBIAN */ } @@ -1238,8 +1300,10 @@ PR_IMPLEMENT(PRStatus) PR_EnumerateThreads(PREnumerator func, void *arg) PRThread* thred = pt_book.first; #if defined(DEBUG) || defined(FORCE_PR_ASSERT) +#if !defined(_PR_DCETHREADS) PRThread *me = PR_GetCurrentThread(); #endif +#endif PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("Begin PR_EnumerateThreads\n")); /* @@ -1267,7 +1331,9 @@ PR_IMPLEMENT(PRStatus) PR_EnumerateThreads(PREnumerator func, void *arg) if (_PT_IS_GCABLE_THREAD(thred)) { +#if !defined(_PR_DCETHREADS) PR_ASSERT((thred == me) || (thred->suspend & PT_THREAD_SUSPENDED)); +#endif PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("In PR_EnumerateThreads callback thread %p thid = %X\n", thred, thred->id)); @@ -1295,6 +1361,8 @@ PR_IMPLEMENT(PRStatus) PR_EnumerateThreads(PREnumerator func, void *arg) * proceed until the thread is suspended or resumed. */ +#if !defined(_PR_DCETHREADS) + /* * In the signal handler, we can not use condition variable notify or wait. * This does not work consistently across all pthread platforms. We also can not @@ -1593,6 +1661,78 @@ PR_IMPLEMENT(void *)PR_GetSP(PRThread *thred) return thred->sp; } /* PR_GetSP */ +#else /* !defined(_PR_DCETHREADS) */ + +static pthread_once_t pt_gc_support_control = pthread_once_init; + +/* + * For DCE threads, there is no pthread_kill or a way of suspending or resuming a + * particular thread. We will just disable the preemption (virtual timer alarm) and + * let the executing thread finish the garbage collection. This stops all other threads + * (GC able or not) and is very inefficient but there is no other choice. + */ +PR_IMPLEMENT(void) PR_SuspendAll() +{ + PRIntn rv; + + rv = pthread_once(&pt_gc_support_control, init_pthread_gc_support); + PR_ASSERT(0 == rv); /* returns -1 on failure */ +#ifdef DEBUG + suspendAllOn = PR_TRUE; +#endif + PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("Begin PR_SuspendAll\n")); + /* + * turn off preemption - i.e add virtual alarm signal to the set of + * blocking signals + */ + rv = sigprocmask( + SIG_BLOCK, &javagc_vtalarm_sigmask, &javagc_intsoff_sigmask); + PR_ASSERT(0 == rv); + suspendAllSuspended = PR_TRUE; + PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("End PR_SuspendAll\n")); +} /* PR_SuspendAll */ + +PR_IMPLEMENT(void) PR_ResumeAll() +{ + PRIntn rv; + + suspendAllSuspended = PR_FALSE; + PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("Begin PR_ResumeAll\n")); + /* turn on preemption - i.e re-enable virtual alarm signal */ + + rv = sigprocmask(SIG_SETMASK, &javagc_intsoff_sigmask, (sigset_t *)NULL); + PR_ASSERT(0 == rv); +#ifdef DEBUG + suspendAllOn = PR_FALSE; +#endif + + PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("End PR_ResumeAll\n")); +} /* PR_ResumeAll */ + +/* Return the stack pointer for the given thread- used by the GC */ +PR_IMPLEMENT(void*)PR_GetSP(PRThread *thred) +{ + pthread_t tid = thred->id; + char *thread_tcb, *top_sp; + + /* + * For HPUX DCE threads, pthread_t is a struct with the + * following three fields (see pthread.h, dce/cma.h): + * cma_t_address field1; + * short int field2; + * short int field3; + * where cma_t_address is typedef'd to be either void* + * or char*. + */ + PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("Begin PR_GetSP\n")); + thread_tcb = (char*)tid.field1; + top_sp = *(char**)(thread_tcb + 128); + PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("End PR_GetSP %p \n", top_sp)); + return top_sp; +} /* PR_GetSP */ + +#endif /* !defined(_PR_DCETHREADS) */ + PR_IMPLEMENT(PRStatus) PR_SetCurrentThreadName(const char *name) { PRThread *thread; @@ -1677,6 +1817,6 @@ PR_IMPLEMENT(const char *) PR_GetThreadName(const PRThread *thread) return thread->name; } -#endif /* defined(_PR_PTHREADS) */ +#endif /* defined(_PR_PTHREADS) || defined(_PR_DCETHREADS) */ /* ptthread.c */ |