Backed out changeset ed9194eec73b (bug 958796) for multiple OSX debug failures on a CLOSED TREE
authorWes Kocher <wkocher@mozilla.com>
Tue, 04 Feb 2014 19:26:24 -0800
changeset 185064 0880728975f7a7db09ec2be54185bb83ce4fa5b0
parent 185063 f28aaa1b3df5f7c14176c9992ff09a65646569f9
child 185065 55dcd2a5362e630f6709cc0c4486bb655da595b8
push id474
push userasasaki@mozilla.com
push dateMon, 02 Jun 2014 21:01:02 +0000
treeherdermozilla-release@967f4cf1b31c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs958796
milestone30.0a1
backs outed9194eec73b51ed39670ad6740dd3eb06e97f1f
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out changeset ed9194eec73b (bug 958796) for multiple OSX debug failures on a CLOSED TREE
nsprpub/TAG-INFO
nsprpub/config/prdepend.h
nsprpub/configure
nsprpub/configure.in
nsprpub/pr/include/prinit.h
nsprpub/pr/include/private/primpl.h
nsprpub/pr/src/md/windows/ntthread.c
nsprpub/pr/src/md/windows/w95thred.c
nsprpub/pr/src/pthreads/ptsynch.c
nsprpub/pr/src/pthreads/ptthread.c
nsprpub/pr/tests/attach.c
nsprpub/pr/tests/foreign.c
nsprpub/pr/tests/provider.c
nsprpub/pr/tests/socket.c
nsprpub/pr/tests/testfile.c
nsprpub/pr/tests/vercheck.c
--- a/nsprpub/TAG-INFO
+++ b/nsprpub/TAG-INFO
@@ -1,1 +1,1 @@
-NSPR_4_10_4_BETA1
+NSPR_4_10_3_BETA3
--- a/nsprpub/config/prdepend.h
+++ b/nsprpub/config/prdepend.h
@@ -5,9 +5,8 @@
 
 /*
  * A dummy header file that is a dependency for all the object files.
  * Used to force a full recompilation of NSPR in Mozilla's Tinderbox
  * depend builds.  See comments in rules.mk.
  */
 
 #error "Do not include this header file."
-
--- a/nsprpub/configure
+++ b/nsprpub/configure
@@ -731,17 +731,17 @@ echo "$ac_t""$build" 1>&6
 test "$host_alias" != "$target_alias" &&
   test "$program_prefix$program_suffix$program_transform_name" = \
     NONENONEs,x,x, &&
   program_prefix=${target_alias}-
 
 
 MOD_MAJOR_VERSION=4
 MOD_MINOR_VERSION=10
-MOD_PATCH_VERSION=4
+MOD_PATCH_VERSION=3
 NSPR_MODNAME=nspr20
 _HAVE_PTHREADS=
 USE_PTHREADS=
 USE_USER_PTHREADS=
 USE_NSPR_THREADS=
 USE_N32=
 USE_64=
 USE_CPLUS=
--- a/nsprpub/configure.in
+++ b/nsprpub/configure.in
@@ -10,17 +10,17 @@ AC_INIT(config/libc_r.h)
 AC_CONFIG_AUX_DIR(${srcdir}/build/autoconf)
 AC_CANONICAL_SYSTEM
 
 dnl ========================================================
 dnl = Defaults
 dnl ========================================================
 MOD_MAJOR_VERSION=4
 MOD_MINOR_VERSION=10
-MOD_PATCH_VERSION=4
+MOD_PATCH_VERSION=3
 NSPR_MODNAME=nspr20
 _HAVE_PTHREADS=
 USE_PTHREADS=
 USE_USER_PTHREADS=
 USE_NSPR_THREADS=
 USE_N32=
 USE_64=
 USE_CPLUS=
--- a/nsprpub/pr/include/prinit.h
+++ b/nsprpub/pr/include/prinit.h
@@ -26,20 +26,20 @@ PR_BEGIN_EXTERN_C
 /*
 ** NSPR's version is used to determine the likelihood that the version you
 ** used to build your component is anywhere close to being compatible with
 ** what is in the underlying library.
 **
 ** The format of the version string is
 **     "<major version>.<minor version>[.<patch level>] [<Beta>]"
 */
-#define PR_VERSION  "4.10.4 Beta"
+#define PR_VERSION  "4.10.3 Beta"
 #define PR_VMAJOR   4
 #define PR_VMINOR   10
-#define PR_VPATCH   4
+#define PR_VPATCH   3
 #define PR_BETA     PR_TRUE
 
 /*
 ** PRVersionCheck
 **
 ** The basic signature of the function that is called to provide version
 ** checking. The result will be a boolean that indicates the likelihood
 ** that the underling library will perform as the caller expects.
--- a/nsprpub/pr/include/private/primpl.h
+++ b/nsprpub/pr/include/private/primpl.h
@@ -1441,29 +1441,19 @@ struct PRCondVar {
 #endif
 };
 
 /************************************************************************/
 
 struct PRMonitor {
     const char* name;           /* monitor name for debugging */
 #if defined(_PR_PTHREADS)
-    PRIntn notifyTimes;         /* number of pending notifies for waitCV.
-                                 * The special value -1 means a broadcast
-                                 * (PR_NotifyAll). */
-
-    pthread_mutex_t lock;       /* lock is only held when accessing fields
-                                 * of the PRMonitor, instead of being held
-                                 * while the monitor is entered. The only
-                                 * exception is notifyTimes, which is
-                                 * protected by the monitor. */
-    pthread_t owner;            /* the owner of the monitor or invalid */
-    pthread_cond_t entryCV;     /* for threads waiting to enter the monitor */
-
-    pthread_cond_t waitCV;      /* for threads waiting on the monitor */
+    PRLock lock;                /* the lock structure */
+    pthread_t owner;            /* the owner of the lock or invalid */
+    PRCondVar *cvar;            /* condition variable queue */
 #else  /* defined(_PR_PTHREADS) */
     PRCondVar *cvar;            /* associated lock and condition variable queue */
 #endif /* defined(_PR_PTHREADS) */
     PRUint32 entryCount;        /* # of times re-entered */
 };
 
 /************************************************************************/
 
@@ -1560,18 +1550,16 @@ struct PRThread {
     PRInt32 osErrorCode;            /* mapping of errorCode | zero */
     PRIntn  errorStringLength;      /* textLength from last call to PR_SetErrorText() */
     PRInt32 errorStringSize;        /* malloc()'d size of buffer | zero */
     char *errorString;              /* current error string | NULL */
     char *name;                     /* thread's name */
 
 #if defined(_PR_PTHREADS)
     pthread_t id;                   /* pthread identifier for the thread */
-    PRBool idSet;                   /* whether 'id' has been set. Protected by
-                                     * pt_book.ml. */
 #ifdef _PR_NICE_PRIORITY_SCHEDULING
     pid_t tid;                      /* Linux-specific kernel thread ID */
 #endif
     PRBool okToDelete;              /* ok to delete the PRThread struct? */
     PRCondVar *waiting;             /* where the thread is waiting | NULL */
     void *sp;                       /* recorded sp for garbage collection */
     PRThread *next, *prev;          /* simple linked list of all threads */
     PRUint32 suspend;               /* used to store suspend and resume flags */
--- a/nsprpub/pr/src/md/windows/ntthread.c
+++ b/nsprpub/pr/src/md/windows/ntthread.c
@@ -177,17 +177,17 @@ PRStatus
 {
 
     thread->md.start = start;
     thread->md.handle = (HANDLE) _beginthreadex(
                     NULL,
                     thread->stack->stackSize,
                     pr_root,
                     (void *)thread,
-                    CREATE_SUSPENDED | STACK_SIZE_PARAM_IS_A_RESERVATION,
+                    CREATE_SUSPENDED,
                     &(thread->id));
     if(!thread->md.handle) {
         PRErrorCode prerror;
         thread->md.fiber_last_error = GetLastError();
         switch (errno) {
             case ENOMEM:
                 prerror = PR_OUT_OF_MEMORY_ERROR;
                 break;
--- a/nsprpub/pr/src/md/windows/w95thred.c
+++ b/nsprpub/pr/src/md/windows/w95thred.c
@@ -101,17 +101,17 @@ PRStatus
 {
 
     thread->md.start = start;
     thread->md.handle = (HANDLE) _beginthreadex(
                     NULL,
                     thread->stack->stackSize,
                     pr_root,
                     (void *)thread,
-                    CREATE_SUSPENDED | STACK_SIZE_PARAM_IS_A_RESERVATION,
+                    CREATE_SUSPENDED,
                     &(thread->id));
     if(!thread->md.handle) {
         return PR_FAILURE;
     }
 
     thread->md.id = thread->id;
     /*
      * On windows, a thread is created with a thread priority of
--- a/nsprpub/pr/src/pthreads/ptsynch.c
+++ b/nsprpub/pr/src/pthreads/ptsynch.c
@@ -164,19 +164,16 @@ PR_IMPLEMENT(void) PR_DestroyLock(PRLock
     memset(lock, 0xaf, sizeof(PRLock));
     pt_debug.locks_destroyed += 1;
 #endif
     PR_Free(lock);
 }  /* PR_DestroyLock */
 
 PR_IMPLEMENT(void) PR_Lock(PRLock *lock)
 {
-    /* Nb: PR_Lock must not call PR_GetCurrentThread to access the |id| or
-     * |tid| field of the current thread's PRThread structure because
-     * _pt_root calls PR_Lock before setting thred->id and thred->tid. */
     PRIntn rv;
     PR_ASSERT(lock != NULL);
     rv = pthread_mutex_lock(&lock->mutex);
     PR_ASSERT(0 == rv);
     PR_ASSERT(0 == lock->notified.length);
     PR_ASSERT(NULL == lock->notified.link);
     PR_ASSERT(PR_FALSE == lock->locked);
     /* Nb: the order of the next two statements is not critical to
@@ -187,25 +184,24 @@ PR_IMPLEMENT(void) PR_Lock(PRLock *lock)
     lock->locked = PR_TRUE;
 #if defined(DEBUG)
     pt_debug.locks_acquired += 1;
 #endif
 }  /* PR_Lock */
 
 PR_IMPLEMENT(PRStatus) PR_Unlock(PRLock *lock)
 {
-    pthread_t self = pthread_self();
     PRIntn rv;
 
     PR_ASSERT(lock != NULL);
     PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(lock->mutex));
     PR_ASSERT(PR_TRUE == lock->locked);
-    PR_ASSERT(pthread_equal(lock->owner, self));
+    PR_ASSERT(pthread_equal(lock->owner, pthread_self()));
 
-    if (!lock->locked || !pthread_equal(lock->owner, self))
+    if (!lock->locked || !pthread_equal(lock->owner, pthread_self()))
         return PR_FAILURE;
 
     lock->locked = PR_FALSE;
     if (0 == lock->notified.length)  /* shortcut */
     {
         rv = pthread_mutex_unlock(&lock->mutex);
         PR_ASSERT(0 == rv);
     }
@@ -292,33 +288,37 @@ static void pt_PostNotifyToCvar(PRCondVa
         for (index = 0; index < notified->length; ++index)
         {
             if (notified->cv[index].cv == cvar)
             {
                 if (broadcast)
                     notified->cv[index].times = -1;
                 else if (-1 != notified->cv[index].times)
                     notified->cv[index].times += 1;
-                return;  /* we're finished */
+                goto finished;  /* we're finished */
             }
         }
         /* if not full, enter new CV in this array */
         if (notified->length < PT_CV_NOTIFIED_LENGTH) break;
 
         /* if there's no link, create an empty array and link it */
         if (NULL == notified->link)
             notified->link = PR_NEWZAP(_PT_Notified);
         notified = notified->link;
     }
 
     /* A brand new entry in the array */
     (void)PR_ATOMIC_INCREMENT(&cvar->notify_pending);
     notified->cv[index].times = (broadcast) ? -1 : 1;
     notified->cv[index].cv = cvar;
     notified->length += 1;
+
+finished:
+    PR_ASSERT(PR_TRUE == cvar->lock->locked);
+    PR_ASSERT(pthread_equal(cvar->lock->owner, pthread_self()));
 }  /* pt_PostNotifyToCvar */
 
 PR_IMPLEMENT(PRCondVar*) PR_NewCondVar(PRLock *lock)
 {
     PRCondVar *cv = PR_NEW(PRCondVar);
     PR_ASSERT(lock != NULL);
     if (cv != NULL)
     {
@@ -422,295 +422,204 @@ PR_IMPLEMENT(PRStatus) PR_NotifyAllCondV
 }  /* PR_NotifyAllCondVar */
 
 /**************************************************************/
 /**************************************************************/
 /***************************MONITORS***************************/
 /**************************************************************/
 /**************************************************************/
 
-/*
- * Notifies just get posted to the monitor. The actual notification is done
- * when the monitor is exited so that MP systems don't contend for a monitor
- * that they can't enter.
- */
-static void pt_PostNotifyToMonitor(PRMonitor *mon, PRBool broadcast)
-{
-    PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mon);
-
-    /* mon->notifyTimes is protected by the monitor, so we don't need to
-     * acquire mon->lock.
-     */
-    if (broadcast)
-        mon->notifyTimes = -1;
-    else if (-1 != mon->notifyTimes)
-        mon->notifyTimes += 1;
-}  /* pt_PostNotifyToMonitor */
-
-static void pt_PostNotifiesFromMonitor(pthread_cond_t *cv, PRIntn times)
-{
-    PRIntn rv;
-
-    /*
-     * Time to actually notify any waits that were affected while the monitor
-     * was entered.
-     */
-    PR_ASSERT(NULL != cv);
-    PR_ASSERT(0 != times);
-    if (-1 == times)
-    {
-        rv = pthread_cond_broadcast(cv);
-        PR_ASSERT(0 == rv);
-    }
-    else
-    {
-        while (times-- > 0)
-        {
-            rv = pthread_cond_signal(cv);
-            PR_ASSERT(0 == rv);
-        }
-    }
-}  /* pt_PostNotifiesFromMonitor */
-
 PR_IMPLEMENT(PRMonitor*) PR_NewMonitor(void)
 {
     PRMonitor *mon;
+    PRCondVar *cvar;
     int rv;
 
     if (!_pr_initialized) _PR_ImplicitInitialization();
 
+    cvar = PR_NEWZAP(PRCondVar);
+    if (NULL == cvar)
+    {
+        PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+        return NULL;
+    }
     mon = PR_NEWZAP(PRMonitor);
     if (mon == NULL)
     {
+        PR_Free(cvar);
         PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
         return NULL;
     }
 
-    rv = _PT_PTHREAD_MUTEX_INIT(mon->lock, _pt_mattr);
+    rv = _PT_PTHREAD_MUTEX_INIT(mon->lock.mutex, _pt_mattr); 
     PR_ASSERT(0 == rv);
     if (0 != rv)
-        goto error1;
+    {
+        PR_Free(mon);
+        PR_Free(cvar);
+        PR_SetError(PR_OPERATION_NOT_SUPPORTED_ERROR, 0);
+        return NULL;
+    }
 
     _PT_PTHREAD_INVALIDATE_THR_HANDLE(mon->owner);
 
-    rv = _PT_PTHREAD_COND_INIT(mon->entryCV, _pt_cvar_attr);
+    mon->cvar = cvar;
+    rv = _PT_PTHREAD_COND_INIT(mon->cvar->cv, _pt_cvar_attr); 
     PR_ASSERT(0 == rv);
-    if (0 != rv)
-        goto error2;
-
-    rv = _PT_PTHREAD_COND_INIT(mon->waitCV, _pt_cvar_attr);
-    PR_ASSERT(0 == rv);
+    mon->entryCount = 0;
+    mon->cvar->lock = &mon->lock;
     if (0 != rv)
-        goto error3;
-
-    mon->notifyTimes = 0;
-    mon->entryCount = 0;
+    {
+        pthread_mutex_destroy(&mon->lock.mutex);
+        PR_Free(mon);
+        PR_Free(cvar);
+        PR_SetError(PR_OPERATION_NOT_SUPPORTED_ERROR, 0);
+        return NULL;
+    }
     return mon;
-
-error3:
-    pthread_cond_destroy(&mon->entryCV);
-error2:
-    pthread_mutex_destroy(&mon->lock);
-error1:
-    PR_Free(mon);
-    PR_SetError(PR_OPERATION_NOT_SUPPORTED_ERROR, 0);
-    return NULL;
 }  /* PR_NewMonitor */
 
 PR_IMPLEMENT(PRMonitor*) PR_NewNamedMonitor(const char* name)
 {
     PRMonitor* mon = PR_NewMonitor();
     if (mon)
         mon->name = name;
     return mon;
 }
 
 PR_IMPLEMENT(void) PR_DestroyMonitor(PRMonitor *mon)
 {
     int rv;
     PR_ASSERT(mon != NULL);
-    rv = pthread_cond_destroy(&mon->waitCV); PR_ASSERT(0 == rv);
-    rv = pthread_cond_destroy(&mon->entryCV); PR_ASSERT(0 == rv);
-    rv = pthread_mutex_destroy(&mon->lock); PR_ASSERT(0 == rv);
+    PR_DestroyCondVar(mon->cvar);
+    rv = pthread_mutex_destroy(&mon->lock.mutex); PR_ASSERT(0 == rv);
 #if defined(DEBUG)
-    memset(mon, 0xaf, sizeof(PRMonitor));
+        memset(mon, 0xaf, sizeof(PRMonitor));
 #endif
     PR_Free(mon);    
 }  /* PR_DestroyMonitor */
 
+
 /* The GC uses this; it is quite arguably a bad interface.  I'm just 
  * duplicating it for now - XXXMB
  */
 PR_IMPLEMENT(PRIntn) PR_GetMonitorEntryCount(PRMonitor *mon)
 {
     pthread_t self = pthread_self();
-    PRIntn rv;
-    PRIntn count = 0;
-
-    rv = pthread_mutex_lock(&mon->lock);
-    PR_ASSERT(0 == rv);
     if (pthread_equal(mon->owner, self))
-        count = mon->entryCount;
-    rv = pthread_mutex_unlock(&mon->lock);
-    PR_ASSERT(0 == rv);
-    return count;
+        return mon->entryCount;
+    return 0;
 }
 
 PR_IMPLEMENT(void) PR_AssertCurrentThreadInMonitor(PRMonitor *mon)
 {
-#if defined(DEBUG) || defined(FORCE_PR_ASSERT)
-    PRIntn rv;
-
-    rv = pthread_mutex_lock(&mon->lock);
-    PR_ASSERT(0 == rv);
-    PR_ASSERT(mon->entryCount != 0 &&
-              pthread_equal(mon->owner, pthread_self()));
-    rv = pthread_mutex_unlock(&mon->lock);
-    PR_ASSERT(0 == rv);
-#endif
+    PR_ASSERT_CURRENT_THREAD_OWNS_LOCK(&mon->lock);
 }
 
 PR_IMPLEMENT(void) PR_EnterMonitor(PRMonitor *mon)
 {
     pthread_t self = pthread_self();
-    PRIntn rv;
 
     PR_ASSERT(mon != NULL);
-    rv = pthread_mutex_lock(&mon->lock);
-    PR_ASSERT(0 == rv);
-    if (mon->entryCount != 0)
+    /*
+     * This is safe only if mon->owner (a pthread_t) can be
+     * read in one instruction.  Perhaps mon->owner should be
+     * a "PRThread *"?
+     */
+    if (!pthread_equal(mon->owner, self))
     {
-        if (pthread_equal(mon->owner, self))
-            goto done;
-        while (mon->entryCount != 0)
-        {
-            rv = pthread_cond_wait(&mon->entryCV, &mon->lock);
-            PR_ASSERT(0 == rv);
-        }
+        PR_Lock(&mon->lock);
+        /* and now I have the lock */
+        PR_ASSERT(0 == mon->entryCount);
+        PR_ASSERT(_PT_PTHREAD_THR_HANDLE_IS_INVALID(mon->owner));
+        _PT_PTHREAD_COPY_THR_HANDLE(self, mon->owner);
     }
-    /* and now I have the monitor */
-    PR_ASSERT(0 == mon->notifyTimes);
-    PR_ASSERT(_PT_PTHREAD_THR_HANDLE_IS_INVALID(mon->owner));
-    _PT_PTHREAD_COPY_THR_HANDLE(self, mon->owner);
-
-done:
     mon->entryCount += 1;
-    rv = pthread_mutex_unlock(&mon->lock);
-    PR_ASSERT(0 == rv);
 }  /* PR_EnterMonitor */
 
 PR_IMPLEMENT(PRStatus) PR_ExitMonitor(PRMonitor *mon)
 {
     pthread_t self = pthread_self();
-    PRIntn rv;
-    PRBool notifyEntryWaiter = PR_FALSE;
-    PRIntn notifyTimes = 0;
 
     PR_ASSERT(mon != NULL);
-    rv = pthread_mutex_lock(&mon->lock);
-    PR_ASSERT(0 == rv);
-    /* the entries should be > 0 and we'd better be the owner */
-    PR_ASSERT(mon->entryCount > 0);
+    /* The lock better be that - locked */
+    PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(mon->lock.mutex));
+    /* we'd better be the owner */
     PR_ASSERT(pthread_equal(mon->owner, self));
-    if (mon->entryCount == 0 || !pthread_equal(mon->owner, self))
-    {
-        rv = pthread_mutex_unlock(&mon->lock);
-        PR_ASSERT(0 == rv);
+    if (!pthread_equal(mon->owner, self))
         return PR_FAILURE;
-    }
 
+    /* if it's locked and we have it, then the entries should be > 0 */
+    PR_ASSERT(mon->entryCount > 0);
     mon->entryCount -= 1;  /* reduce by one */
     if (mon->entryCount == 0)
     {
-        /* and if it transitioned to zero - notify an entry waiter */
-        /* make the owner unknown */
-        _PT_PTHREAD_INVALIDATE_THR_HANDLE(mon->owner);
-        notifyEntryWaiter = PR_TRUE;
-        notifyTimes = mon->notifyTimes;
-        mon->notifyTimes = 0;
-    }
-    rv = pthread_mutex_unlock(&mon->lock);
-    PR_ASSERT(0 == rv);
-    if (notifyTimes)
-        pt_PostNotifiesFromMonitor(&mon->waitCV, notifyTimes);
-    if (notifyEntryWaiter)
-    {
-        rv = pthread_cond_signal(&mon->entryCV);
-        PR_ASSERT(0 == rv);
+        /* and if it transitioned to zero - unlock */
+        _PT_PTHREAD_INVALIDATE_THR_HANDLE(mon->owner);  /* make the owner unknown */
+        PR_Unlock(&mon->lock);
     }
     return PR_SUCCESS;
 }  /* PR_ExitMonitor */
 
 PR_IMPLEMENT(PRStatus) PR_Wait(PRMonitor *mon, PRIntervalTime timeout)
 {
     PRStatus rv;
     PRInt16 saved_entries;
     pthread_t saved_owner;
 
     PR_ASSERT(mon != NULL);
-    rv = pthread_mutex_lock(&mon->lock);
-    PR_ASSERT(0 == rv);
-    /* the entries better be positive */
+    /* we'd better be locked */
+    PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(mon->lock.mutex));
+    /* and the entries better be positive */
     PR_ASSERT(mon->entryCount > 0);
-    /* and it better be owned by us */
+    /* and it better be by us */
     PR_ASSERT(pthread_equal(mon->owner, pthread_self()));
 
     /* tuck these away 'till later */
     saved_entries = mon->entryCount; 
     mon->entryCount = 0;
     _PT_PTHREAD_COPY_THR_HANDLE(mon->owner, saved_owner);
     _PT_PTHREAD_INVALIDATE_THR_HANDLE(mon->owner);
-    /*
-     * If we have pending notifies, post them now.
-     *
-     * This is not optimal. We're going to post these notifies
-     * while we're holding the lock. That means on MP systems
-     * that they are going to collide for the lock that we will
-     * hold until we actually wait.
-     */
-    if (0 != mon->notifyTimes)
-    {
-        pt_PostNotifiesFromMonitor(&mon->waitCV, mon->notifyTimes);
-        mon->notifyTimes = 0;
-    }
-    rv = pthread_cond_signal(&mon->entryCV);
-    PR_ASSERT(0 == rv);
+    
+    rv = PR_WaitCondVar(mon->cvar, timeout);
 
-    if (timeout == PR_INTERVAL_NO_TIMEOUT)
-        rv = pthread_cond_wait(&mon->waitCV, &mon->lock);
-    else
-        rv = pt_TimedWait(&mon->waitCV, &mon->lock, timeout);
-    PR_ASSERT(0 == rv);
-
-    while (mon->entryCount != 0)
-    {
-        rv = pthread_cond_wait(&mon->entryCV, &mon->lock);
-        PR_ASSERT(0 == rv);
-    }
-    PR_ASSERT(0 == mon->notifyTimes);
-    /* reinstate the interesting information */
+    /* reinstate the intresting information */
     mon->entryCount = saved_entries;
     _PT_PTHREAD_COPY_THR_HANDLE(saved_owner, mon->owner);
 
-    rv = pthread_mutex_unlock(&mon->lock);
-    PR_ASSERT(0 == rv);
     return rv;
 }  /* PR_Wait */
 
 PR_IMPLEMENT(PRStatus) PR_Notify(PRMonitor *mon)
 {
     PR_ASSERT(NULL != mon);
-    pt_PostNotifyToMonitor(mon, PR_FALSE);
+    /* we'd better be locked */
+    PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(mon->lock.mutex));
+    /* and the entries better be positive */
+    PR_ASSERT(mon->entryCount > 0);
+    /* and it better be by us */
+    PR_ASSERT(pthread_equal(mon->owner, pthread_self()));
+
+    pt_PostNotifyToCvar(mon->cvar, PR_FALSE);
+
     return PR_SUCCESS;
 }  /* PR_Notify */
 
 PR_IMPLEMENT(PRStatus) PR_NotifyAll(PRMonitor *mon)
 {
-    PR_ASSERT(NULL != mon);
-    pt_PostNotifyToMonitor(mon, PR_TRUE);
+    PR_ASSERT(mon != NULL);
+    /* we'd better be locked */
+    PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(mon->lock.mutex));
+    /* and the entries better be positive */
+    PR_ASSERT(mon->entryCount > 0);
+    /* and it better be by us */
+    PR_ASSERT(pthread_equal(mon->owner, pthread_self()));
+
+    pt_PostNotifyToCvar(mon->cvar, PR_TRUE);
+
     return PR_SUCCESS;
 }  /* PR_NotifyAll */
 
 /**************************************************************/
 /**************************************************************/
 /**************************SEMAPHORES**************************/
 /**************************************************************/
 /**************************************************************/
--- a/nsprpub/pr/src/pthreads/ptthread.c
+++ b/nsprpub/pr/src/pthreads/ptthread.c
@@ -117,48 +117,63 @@ static void _PR_InitializeStack(PRThread
     }
 }
 
 static void *_pt_root(void *arg)
 {
     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
      * set its nice value hence we do it here instead of at creation time.
      */
     tid = gettid();
     errno = 0;
     rv = getpriority(PRIO_PROCESS, 0);
 
     /* If we cannot read the main thread's nice value don't try to change the
      * new thread's nice value. */
     if (errno == 0) {
         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
 
     /*
     ** 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;
+        pthread_t self = thred->id;
         rv = pthread_detach(&self);
         PR_ASSERT(0 == rv);
     }
 #endif /* defined(_PR_DCETHREADS) */
 
     /* Set up the thread stack information */
     _PR_InitializeStack(thred->stack);
 
@@ -167,38 +182,16 @@ static void *_pt_root(void *arg)
      * This object will be deleted when the thread termintates,
      * whether in a join or detached (see _PR_InitThreads()).
      */
     rv = pthread_setspecific(pt_book.key, thred);
     PR_ASSERT(0 == rv);
 
     /* 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;
     thred->suspend = 0;
 
     thred->prev = pt_book.last;
     if (pt_book.last)
@@ -211,17 +204,17 @@ static void *_pt_root(void *arg)
 
     thred->startFunc(thred->arg);  /* make visible to the client */
 
     /* unhook the thread from the runtime */
     PR_Lock(pt_book.ml);
     /*
      * 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 accessed thred->id and thred->idSet.
+     * PR_CreateThread() has set thred->id.
      */
     if (detached)
     {
         while (!thred->okToDelete)
             PR_WaitCondVar(pt_book.cv, PR_INTERVAL_NO_TIMEOUT);
     }
 
     if (thred->state & PT_THREAD_SYSTEM)
@@ -275,17 +268,16 @@ static PRThread* pt_AttachThread(void)
     /* PR_NEWZAP must not call PR_GetCurrentThread() */
     thred = PR_NEWZAP(PRThread);
     if (NULL != thred)
     {
         int rv;
 
         thred->priority = PR_PRIORITY_NORMAL;
         thred->id = pthread_self();
-        thred->idSet = PR_TRUE;
 #ifdef _PR_NICE_PRIORITY_SCHEDULING
         thred->tid = gettid();
 #endif
         rv = pthread_setspecific(pt_book.key, thred);
         PR_ASSERT(0 == rv);
 
         thred->state = PT_THREAD_GLOBAL | PT_THREAD_FOREIGN;
         PR_Lock(pt_book.ml);
@@ -496,42 +488,34 @@ static PRThread* _PR_CreateThread(
 
             PR_Free(thred->stack);
             PR_Free(thred);  /* all that work ... poof! */
             PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, oserr);
             thred = NULL;  /* and for what? */
             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().)
          */
-        if (!thred->idSet)
-        {
-            thred->id = id;
-            thred->idSet = PR_TRUE;
-        }
-        else
-        {
-            PR_ASSERT(pthread_equal(thred->id, id));
-        }
+        thred->id = id;
 
         /*
-         * 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 the new thread is detached, tell it that PR_CreateThread()
+         * has set thred->id 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:
     rv = _PT_PTHREAD_ATTR_DESTROY(&tattr);
     PR_ASSERT(0 == rv);
 
     return thred;
 }  /* _PR_CreateThread */
@@ -951,17 +935,16 @@ void _PR_InitThreads(
     pt_book.cv = PR_NewCondVar(pt_book.ml);
     PR_ASSERT(NULL != pt_book.cv);
     thred = PR_NEWZAP(PRThread);
     PR_ASSERT(NULL != thred);
     thred->arg = NULL;
     thred->startFunc = NULL;
     thred->priority = priority;
     thred->id = pthread_self();
-    thred->idSet = PR_TRUE;
 #ifdef _PR_NICE_PRIORITY_SCHEDULING
     thred->tid = gettid();
 #endif
 
     thred->state = (PT_THREAD_DETACHED | PT_THREAD_PRIMORD);
     if (PR_SYSTEM_THREAD == type)
     {
         thred->state |= PT_THREAD_SYSTEM;
--- a/nsprpub/pr/tests/attach.c
+++ b/nsprpub/pr/tests/attach.c
@@ -255,17 +255,17 @@ int main(int argc, char **argv)
 		failed_already=1;
 		goto exit_now;
 	}
 
 
 #elif defined(WIN32)
 
     hThread = (HANDLE) _beginthreadex(NULL, 0, threadStartFunc, NULL,
-            STACK_SIZE_PARAM_IS_A_RESERVATION, &threadID);
+            0, &threadID); 
     if (hThread == 0) {
         fprintf(stderr, "thread creation failed: error code %d\n",
                 GetLastError());
 		failed_already=1;
 		goto exit_now;
     }
     rv = WaitForSingleObject(hThread, INFINITE);
     if (debug_mode)PR_ASSERT(rv != WAIT_FAILED);
--- a/nsprpub/pr/tests/foreign.c
+++ b/nsprpub/pr/tests/foreign.c
@@ -74,17 +74,19 @@ static void sproc_start(void *arg, PRSiz
     StartFn start = so->start;
     void *data = so->arg;
     PR_Free(so);
     start(data);
 }  /* sproc_start */
 #endif  /* defined(IRIX) && !defined(_PR_PTHREADS) */
 
 #if defined(WIN32)
+#if defined(WINCE)
 #include <windows.h>
+#endif
 #include <process.h>  /* for _beginthreadex() */
 
 static PRUintn __stdcall windows_start(void *arg)
 {
     StartObject *so = (StartObject*)arg;
     StartFn start = so->start;
     void *data = so->arg;
     PR_Free(so);
@@ -167,17 +169,17 @@ static PRStatus NSPRPUB_TESTS_CreateThre
             PR_ASSERT(NULL != start_object);
             start_object->start = start;
             start_object->arg = arg;
             th = (void*)_beginthreadex(
                 NULL, /* LPSECURITY_ATTRIBUTES - pointer to thread security attributes */  
                 0U, /* DWORD - initial thread stack size, in bytes */
                 windows_start, /* LPTHREAD_START_ROUTINE - pointer to thread function */
                 start_object, /* LPVOID - argument for new thread */
-                STACK_SIZE_PARAM_IS_A_RESERVATION, /*DWORD dwCreationFlags - creation flags */
+                0U, /*DWORD dwCreationFlags - creation flags */
                 &id /* LPDWORD - pointer to returned thread identifier */ );
 
             rv = (NULL == th) ? PR_FAILURE : PR_SUCCESS;
         }
 #else
         PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
         rv = PR_FAILURE;
 #endif
--- a/nsprpub/pr/tests/provider.c
+++ b/nsprpub/pr/tests/provider.c
@@ -748,17 +748,17 @@ static PRStatus NewThread(
             PR_ASSERT(NULL != start_object);
             start_object->start = start;
             start_object->arg = arg;
             th = (void*)_beginthreadex(
                 NULL, /* LPSECURITY_ATTRIBUTES - pointer to thread security attributes */  
                 0U, /* DWORD - initial thread stack size, in bytes */
                 windows_start, /* LPTHREAD_START_ROUTINE - pointer to thread function */
                 start_object, /* LPVOID - argument for new thread */
-                STACK_SIZE_PARAM_IS_A_RESERVATION, /*DWORD dwCreationFlags - creation flags */
+                0U, /*DWORD dwCreationFlags - creation flags */
                 &id /* LPDWORD - pointer to returned thread identifier */ );
 
             rv = (NULL == th) ? PR_FAILURE : PR_SUCCESS;
         }
 #else
         PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
         rv = PR_FAILURE;
 #endif
--- a/nsprpub/pr/tests/socket.c
+++ b/nsprpub/pr/tests/socket.c
@@ -342,17 +342,17 @@ PRInt32 native_thread = 0;
 		HANDLE thandle;
 		unsigned tid;
 		
 		thandle = (HANDLE) _beginthreadex(
 						NULL,
 						stackSize,
 						(unsigned (__stdcall *)(void *))start,
 						arg,
-						STACK_SIZE_PARAM_IS_A_RESERVATION,
+						0,
 						&tid);		
 		return((PRThread *) thandle);
 #endif
 	} else {
 		return(PR_CreateThread(type,start,arg,priority,scope,state,stackSize));
 	}
 #else
 	return(PR_CreateThread(type,start,arg,priority,scope,state,stackSize));
--- a/nsprpub/pr/tests/testfile.c
+++ b/nsprpub/pr/tests/testfile.c
@@ -145,17 +145,17 @@ PRInt32 native_thread = 0;
 		HANDLE thandle;
 		unsigned tid;
 		
 		thandle = (HANDLE) _beginthreadex(
 						NULL,
 						stackSize,
 						(unsigned (__stdcall *)(void *))start,
 						arg,
-						STACK_SIZE_PARAM_IS_A_RESERVATION,
+						0,
 						&tid);		
 		return((PRThread *) thandle);
 #endif
 	} else {
 		return(PR_CreateThread(type,start,arg,priority,scope,state,stackSize));
 	}
 #else
 	return(PR_CreateThread(type,start,arg,priority,scope,state,stackSize));
--- a/nsprpub/pr/tests/vercheck.c
+++ b/nsprpub/pr/tests/vercheck.c
@@ -15,50 +15,50 @@
  */
 
 #include "prinit.h"
 
 #include <stdio.h>
 #include <stdlib.h>
 
 /*
- * This release (4.10.4) is backward compatible with the
+ * This release (4.10.3) is backward compatible with the
  * 4.0.x, 4.1.x, 4.2.x, 4.3.x, 4.4.x, 4.5.x, 4.6.x, 4.7.x,
- * 4.8.x, 4.9.x, 4.10, 4.10.1, 4.10.2, and 4.10.3 releases.
+ * 4.8.x, 4.9.x, 4.10, 4.10.1 and 4.10.2 releases.
  * It, of course, is compatible with itself.
  */
 static char *compatible_version[] = {
     "4.0", "4.0.1", "4.1", "4.1.1", "4.1.2", "4.1.3",
     "4.2", "4.2.1", "4.2.2", "4.3", "4.4", "4.4.1",
     "4.5", "4.5.1",
     "4.6", "4.6.1", "4.6.2", "4.6.3", "4.6.4", "4.6.5",
     "4.6.6", "4.6.7", "4.6.8",
     "4.7", "4.7.1", "4.7.2", "4.7.3", "4.7.4", "4.7.5",
     "4.7.6",
     "4.8", "4.8.1", "4.8.2", "4.8.3", "4.8.4", "4.8.5",
     "4.8.6", "4.8.7", "4.8.8", "4.8.9",
     "4.9", "4.9.1", "4.9.2", "4.9.3", "4.9.4", "4.9.5",
     "4.9.6",
-    "4.10", "4.10.1", "4.10.2", "4.10.3",
+    "4.10", "4.10.1", "4.10.2",
     PR_VERSION
 };
 
 /*
  * This release is not backward compatible with the old
  * NSPR 2.1 and 3.x releases.
  *
  * Any release is incompatible with future releases and
  * patches.
  */
 static char *incompatible_version[] = {
     "2.1 19980529",
     "3.0", "3.0.1",
     "3.1", "3.1.1", "3.1.2", "3.1.3",
     "3.5", "3.5.1",
-    "4.10.5",
+    "4.10.4",
     "4.11", "4.11.1",
     "10.0", "11.1", "12.14.20"
 };
 
 int main(int argc, char **argv)
 {
     int idx;
     int num_compatible = sizeof(compatible_version) / sizeof(char *);