Index: nspr/pr/src/pthreads/ptthread.c |
=================================================================== |
--- nspr/pr/src/pthreads/ptthread.c (revision 257452) |
+++ nspr/pr/src/pthreads/ptthread.c (working copy) |
@@ -122,21 +122,11 @@ |
PRIntn rv; |
PRThread *thred = (PRThread*)arg; |
PRBool detached = (thred->state & PT_THREAD_DETACHED) ? PR_TRUE : PR_FALSE; |
+ pthread_t id = pthread_self(); |
#ifdef _PR_NICE_PRIORITY_SCHEDULING |
pid_t tid; |
#endif |
- /* |
- * Both the parent thread and this new thread set thred->id. |
- * The new thread must ensure that thred->id is set before |
- * it executes its startFunc. The parent thread must ensure |
- * that thred->id is set before PR_CreateThread() returns. |
- * Both threads set thred->id without holding a lock. Since |
- * they are writing the same value, this unprotected double |
- * write should be safe. |
- */ |
- thred->id = pthread_self(); |
- |
#ifdef _PR_NICE_PRIORITY_SCHEDULING |
/* |
* We need to know the kernel thread ID of each thread in order to |
@@ -152,11 +142,6 @@ |
setpriority(PRIO_PROCESS, tid, |
pt_RelativePriority(rv, thred->priority)); |
} |
- |
- PR_Lock(pt_book.ml); |
- thred->tid = tid; |
- PR_NotifyAllCondVar(pt_book.cv); |
- PR_Unlock(pt_book.ml); |
#endif |
/* |
@@ -168,7 +153,7 @@ |
if (detached) |
{ |
/* pthread_detach() modifies its argument, so we must pass a copy */ |
- pthread_t self = thred->id; |
+ pthread_t self = id; |
rv = pthread_detach(&self); |
PR_ASSERT(0 == rv); |
} |
@@ -187,7 +172,29 @@ |
/* make the thread visible to the rest of the runtime */ |
PR_Lock(pt_book.ml); |
+ /* |
+ * Both the parent thread and this new thread set thred->id. |
+ * The new thread must ensure that thred->id is set before |
+ * it executes its startFunc. The parent thread must ensure |
+ * that thred->id is set before PR_CreateThread() returns. |
+ * Both threads set thred->id while holding pt_book.ml and |
+ * use thred->idSet to ensure thred->id is written only once. |
+ */ |
+ if (!thred->idSet) |
+ { |
+ thred->id = id; |
+ thred->idSet = PR_TRUE; |
+ } |
+ else |
+ { |
+ PR_ASSERT(pthread_equal(thred->id, id)); |
+ } |
+#ifdef _PR_NICE_PRIORITY_SCHEDULING |
+ thred->tid = tid; |
+ PR_NotifyAllCondVar(pt_book.cv); |
+#endif |
+ |
/* If this is a GCABLE thread, set its state appropriately */ |
if (thred->suspend & PT_THREAD_SETGCABLE) |
thred->state |= PT_THREAD_GCABLE; |
@@ -209,7 +216,7 @@ |
/* |
* At this moment, PR_CreateThread() may not have set thred->id yet. |
* It is safe for a detached thread to free thred only after |
- * PR_CreateThread() has set thred->id. |
+ * PR_CreateThread() has accessed thred->id and thred->idSet. |
*/ |
if (detached) |
{ |
@@ -273,6 +280,7 @@ |
thred->priority = PR_PRIORITY_NORMAL; |
thred->id = pthread_self(); |
+ thred->idSet = PR_TRUE; |
#ifdef _PR_NICE_PRIORITY_SCHEDULING |
thred->tid = gettid(); |
#endif |
@@ -493,24 +501,32 @@ |
goto done; |
} |
+ PR_Lock(pt_book.ml); |
/* |
* Both the parent thread and this new thread set thred->id. |
* The parent thread must ensure that thred->id is set before |
* PR_CreateThread() returns. (See comments in _pt_root().) |
*/ |
- thred->id = id; |
+ if (!thred->idSet) |
+ { |
+ thred->id = id; |
+ thred->idSet = PR_TRUE; |
+ } |
+ else |
+ { |
+ PR_ASSERT(pthread_equal(thred->id, id)); |
+ } |
/* |
- * If the new thread is detached, tell it that PR_CreateThread() |
- * has set thred->id so it's ok to delete thred. |
+ * If the new thread is detached, tell it that PR_CreateThread() has |
+ * accessed thred->id and thred->idSet so it's ok to delete thred. |
*/ |
if (PR_UNJOINABLE_THREAD == state) |
{ |
- PR_Lock(pt_book.ml); |
thred->okToDelete = PR_TRUE; |
PR_NotifyAllCondVar(pt_book.cv); |
- PR_Unlock(pt_book.ml); |
} |
+ PR_Unlock(pt_book.ml); |
} |
done: |
@@ -940,6 +956,7 @@ |
thred->startFunc = NULL; |
thred->priority = priority; |
thred->id = pthread_self(); |
+ thred->idSet = PR_TRUE; |
#ifdef _PR_NICE_PRIORITY_SCHEDULING |
thred->tid = gettid(); |
#endif |