summaryrefslogtreecommitdiff
path: root/nsprpub/pr/src/pthreads/ptthread.c
diff options
context:
space:
mode:
Diffstat (limited to 'nsprpub/pr/src/pthreads/ptthread.c')
-rw-r--r--nsprpub/pr/src/pthreads/ptthread.c158
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 */