Add support for creating bound threads. Bug 338607.
authorsrinivas%netscape.com
Mon, 01 Feb 1999 00:41:51 +0000
changeset 413 1f293cd5ab9867702440e7296fb7454cdc4f4d71
parent 412 b3370af381b7793132b39d1d84dce48dd83bb877
child 414 3b574d3918bc7014fd016424088649d3fe8504be
push idunknown
push userunknown
push dateunknown
bugs338607
Add support for creating bound threads. Bug 338607.
pr/include/private/primpl.h
pr/include/prthread.h
pr/src/md/unix/solaris.c
pr/src/md/unix/unixware.c
pr/src/pthreads/ptthread.c
pr/src/threads/combined/pruthr.c
pr/src/threads/prcthr.c
--- a/pr/include/private/primpl.h
+++ b/pr/include/private/primpl.h
@@ -153,16 +153,17 @@ struct _PT_Notified
 #define PT_THREAD_DETACHED  0x01    /* thread can't be joined */
 #define PT_THREAD_GLOBAL    0x02    /* a global thread (unlikely) */
 #define PT_THREAD_SYSTEM    0x04    /* system (not user) thread */
 #define PT_THREAD_PRIMORD   0x08    /* this is the primordial thread */
 #define PT_THREAD_ABORTED   0x10    /* thread has been interrupted */
 #define PT_THREAD_GCABLE    0x20    /* thread is garbage collectible */
 #define PT_THREAD_SUSPENDED 0x40    /* thread has been suspended */
 #define PT_THREAD_FOREIGN   0x80    /* thread is not one of ours */
+#define PT_THREAD_BOUND     0x100    /* a bound-global thread */
 
 /* 
 ** Possible values for thread's suspend field
 ** Note that the first two can be the same as they are really mutually exclusive,
 ** i.e. both cannot be happening at the same time. We have two symbolic names
 ** just as a mnemonic.
 **/
 #define PT_THREAD_RESUMED   0x80    /* thread has been resumed */
--- a/pr/include/prthread.h
+++ b/pr/include/prthread.h
@@ -66,17 +66,18 @@ typedef struct PRThreadStack PRThreadSta
 
 typedef enum PRThreadType {
     PR_USER_THREAD,
     PR_SYSTEM_THREAD
 } PRThreadType;
 
 typedef enum PRThreadScope {
     PR_LOCAL_THREAD,
-    PR_GLOBAL_THREAD
+    PR_GLOBAL_THREAD,
+    PR_GLOBAL_BOUND_THREAD
 } PRThreadScope;
 
 typedef enum PRThreadState {
     PR_JOINABLE_THREAD,
     PR_UNJOINABLE_THREAD
 } PRThreadState;
 
 typedef enum PRThreadPriority
--- a/pr/src/md/unix/solaris.c
+++ b/pr/src/md/unix/solaris.c
@@ -195,17 +195,18 @@ PRStatus _MD_CreateThread(PRThread *thre
      * - We use a termination condition variable in the PRThread
      *   structure to implement PR_JoinThread across all classic
      *   nspr implementation strategies.
      * - The native threads may be recycled by NSPR to run other
      *   new NSPR threads, so the native threads may not terminate
      *   when the corresponding NSPR threads terminate.  
      */
     flags = THR_SUSPENDED|THR_DETACHED;
-    if (thread->flags & (_PR_GCABLE_THREAD|_PR_BOUND_THREAD))
+    if ((thread->flags & (_PR_GCABLE_THREAD|_PR_BOUND_THREAD)) ||
+    							(scope == PR_GLOBAL_BOUND_THREAD))
 		flags |= THR_BOUND;
 
     if (thr_create(NULL, thread->stack->stackSize,
                   (void *(*)(void *)) start, (void *) thread, 
 				  flags,
                   &thread->md.handle)) {
         thr_sigsetmask(SIG_SETMASK, &oldset, NULL); 
         return PR_FAILURE;
@@ -214,18 +215,18 @@ PRStatus _MD_CreateThread(PRThread *thre
     /* When the thread starts running, then the lwpid is set to the right
      * value. Until then we want to mark this as 'uninit' so that
      * its register state is initialized properly for GC */
 
     thread->md.lwpid = -1;
     thr_sigsetmask(SIG_SETMASK, &oldset, NULL); 
     _MD_NEW_SEM(&thread->md.waiter_sem, 0);
 
-    if (scope == PR_GLOBAL_THREAD) {
-	thread->flags |= _PR_GLOBAL_SCOPE;
+    if ((scope == PR_GLOBAL_THREAD) || (scope == PR_GLOBAL_BOUND_THREAD)) {
+		thread->flags |= _PR_GLOBAL_SCOPE;
     }
 
     _MD_SET_PRIORITY(&(thread->md), priority);
 
     /* Activate the thread */
     if (thr_continue( thread->md.handle ) ) {
 	return PR_FAILURE;
     }
--- a/pr/src/md/unix/unixware.c
+++ b/pr/src/md/unix/unixware.c
@@ -251,17 +251,18 @@ PRStatus _MD_CREATE_THREAD(PRThread *thr
 {
 	long flags;
 	
     /* mask out SIGALRM for native thread creation */
     thr_sigsetmask(SIG_BLOCK, &set, &oldset); 
 
     flags = (state == PR_JOINABLE_THREAD ? THR_SUSPENDED/*|THR_NEW_LWP*/ 
 			   : THR_SUSPENDED|THR_DETACHED/*|THR_NEW_LWP*/);
-	if (thread->flags & _PR_GCABLE_THREAD)
+	if ((thread->flags & _PR_GCABLE_THREAD) ||
+							(scope == PR_GLOBAL_BOUND_THREAD))
 		flags |= THR_BOUND;
 
     if (thr_create(NULL, thread->stack->stackSize,
                   (void *(*)(void *)) start, (void *) thread, 
 				  flags,
                   &thread->md.handle)) {
         thr_sigsetmask(SIG_SETMASK, &oldset, NULL); 
 	return PR_FAILURE;
@@ -271,18 +272,18 @@ PRStatus _MD_CREATE_THREAD(PRThread *thr
     /* When the thread starts running, then the lwpid is set to the right
      * value. Until then we want to mark this as 'uninit' so that
      * its register state is initialized properly for GC */
 
     thread->md.lwpid = -1;
     thr_sigsetmask(SIG_SETMASK, &oldset, NULL); 
     _MD_NEW_SEM(&thread->md.waiter_sem, 0);
 
-    if (scope == PR_GLOBAL_THREAD) {
-	thread->flags |= _PR_GLOBAL_SCOPE;
+	if ((scope == PR_GLOBAL_THREAD) || (scope == PR_GLOBAL_BOUND_THREAD)) {
+		thread->flags |= _PR_GLOBAL_SCOPE;
     }
 
     /* 
     ** Set the thread priority.  This will also place the thread on 
     ** the runQ.
     **
     ** Force PR_SetThreadPriority to set the priority by
     ** setting thread->priority to 100.
--- a/pr/src/pthreads/ptthread.c
+++ b/pr/src/pthreads/ptthread.c
@@ -306,16 +306,18 @@ static PRThread* _PR_CreateThread(
 
         thred->arg = arg;
         thred->startFunc = start;
         thred->priority = priority;
         if (PR_UNJOINABLE_THREAD == state)
             thred->state |= PT_THREAD_DETACHED;
         if (PR_GLOBAL_THREAD == scope)
             thred->state |= PT_THREAD_GLOBAL;
+        if (PR_GLOBAL_BOUND_THREAD == scope)
+            thred->state |= (PT_THREAD_GLOBAL | PT_THREAD_BOUND);
         if (PR_SYSTEM_THREAD == type)
             thred->state |= PT_THREAD_SYSTEM;
 
         thred->suspend =(isGCAble) ? PT_THREAD_SETGCABLE : 0;
 
         thred->stack = PR_NEWZAP(PRThreadStack);
         if (thred->stack == NULL) {
             PRIntn oserr = errno;
@@ -334,16 +336,19 @@ static PRThread* _PR_CreateThread(
 
         /* make the thread counted to the rest of the runtime */
         PR_Lock(pt_book.ml);
         if (PR_SYSTEM_THREAD == type)
             pt_book.system += 1;
         else pt_book.user += 1;
         PR_Unlock(pt_book.ml);
 
+        if (thred->state & PT_THREAD_BOUND) {
+    		rv = pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM);
+		}
         /*
          * We pass a pointer to a local copy (instead of thred->id)
          * to pthread_create() because who knows what wacky things
          * pthread_create() may be doing to its argument.
          */
         rv = PTHREAD_CREATE(&id, tattr, _pt_root, thred);
 
 #if !defined(_PR_DCETHREADS)
@@ -513,17 +518,18 @@ PR_IMPLEMENT(PRThread*) PR_GetCurrentThr
     PTHREAD_GETSPECIFIC(pt_book.key, thred);
     if (NULL == thred) thred = pt_AttachThread();
     PR_ASSERT(NULL != thred);
     return (PRThread*)thred;
 }  /* PR_GetCurrentThread */
 
 PR_IMPLEMENT(PRThreadScope) PR_GetThreadScope(const PRThread *thred)
 {
-    return PR_GLOBAL_THREAD;
+    return (thred->state & PT_THREAD_BOUND) ?
+        PR_GLOBAL_BOUND_THREAD : PR_GLOBAL_THREAD;
 }  /* PR_GetThreadScope() */
 
 PR_IMPLEMENT(PRThreadType) PR_GetThreadType(const PRThread *thred)
 {
     return (thred->state & PT_THREAD_SYSTEM) ?
         PR_SYSTEM_THREAD : PR_USER_THREAD;
 }
 
--- a/pr/src/threads/combined/pruthr.c
+++ b/pr/src/threads/combined/pruthr.c
@@ -1083,20 +1083,25 @@ PR_IMPLEMENT(PRThread*) _PR_CreateThread
     }
         
     if (!_pr_initialized) _PR_ImplicitInitialization();
 
     if (! (flags & _PR_IDLE_THREAD))
         me = _PR_MD_CURRENT_THREAD();
 
 #if    defined(_PR_GLOBAL_THREADS_ONLY)
-    scope = PR_GLOBAL_THREAD;
+	/*
+	 * can create global threads only
+	 */
+    if (scope == PR_LOCAL_THREAD)
+    	scope = PR_GLOBAL_THREAD;
 #endif
 
-    native = ((scope == PR_GLOBAL_THREAD) && _PR_IS_NATIVE_THREAD_SUPPORTED());
+    native = (((scope == PR_GLOBAL_THREAD)|| (scope == PR_GLOBAL_BOUND_THREAD))
+							&& _PR_IS_NATIVE_THREAD_SUPPORTED());
 
     _PR_ADJUST_STACKSIZE(stackSize);
 
     if (native) {
     /*
      * clear the IDLE_THREAD flag which applies to LOCAL
      * threads only
      */
--- a/pr/src/threads/prcthr.c
+++ b/pr/src/threads/prcthr.c
@@ -398,19 +398,20 @@ PR_IMPLEMENT(void) PR_ClearThreadGCAble(
 
 PR_IMPLEMENT(PRThreadScope) PR_GetThreadScope(const PRThread *thread)
 {
 #ifdef XP_MAC
 #pragma unused( thread )
 #endif
     if (!_pr_initialized) _PR_ImplicitInitialization();
 
-    if (_PR_IS_NATIVE_THREAD(thread))
-        return PR_GLOBAL_THREAD;
-    else
+    if (_PR_IS_NATIVE_THREAD(thread)) {
+    	return (thread->flags & _PR_BOUND_THREAD) ? PR_GLOBAL_BOUND_THREAD :
+										PR_GLOBAL_THREAD;
+    } else
         return PR_LOCAL_THREAD;
 }
 
 PR_IMPLEMENT(PRThreadType) PR_GetThreadType(const PRThread *thread)
 {
     return (thread->flags & _PR_SYSTEM) ? PR_SYSTEM_THREAD : PR_USER_THREAD;
 }