зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset ed9194eec73b (bug 958796) for multiple OSX debug failures on a CLOSED TREE
This commit is contained in:
Родитель
317979a6cd
Коммит
87f49f23e0
|
@ -1 +1 @@
|
|||
NSPR_4_10_4_BETA1
|
||||
NSPR_4_10_3_BETA3
|
||||
|
|
|
@ -10,4 +10,3 @@
|
|||
*/
|
||||
|
||||
#error "Do not include this header file."
|
||||
|
||||
|
|
|
@ -736,7 +736,7 @@ test "$host_alias" != "$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=
|
||||
|
|
|
@ -15,7 +15,7 @@ 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=
|
||||
|
|
|
@ -31,10 +31,10 @@ PR_BEGIN_EXTERN_C
|
|||
** 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
|
||||
|
||||
/*
|
||||
|
|
|
@ -1446,19 +1446,9 @@ struct PRCondVar {
|
|||
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) */
|
||||
|
@ -1565,8 +1555,6 @@ struct PRThread {
|
|||
|
||||
#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
|
||||
|
|
|
@ -182,7 +182,7 @@ _PR_MD_CREATE_THREAD(PRThread *thread,
|
|||
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;
|
||||
|
|
|
@ -106,7 +106,7 @@ _PR_MD_CREATE_THREAD(PRThread *thread,
|
|||
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;
|
||||
|
|
|
@ -169,9 +169,6 @@ PR_IMPLEMENT(void) PR_DestroyLock(PRLock *lock)
|
|||
|
||||
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);
|
||||
|
@ -192,15 +189,14 @@ PR_IMPLEMENT(void) PR_Lock(PRLock *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;
|
||||
|
@ -297,7 +293,7 @@ static void pt_PostNotifyToCvar(PRCondVar *cvar, PRBool 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 */
|
||||
|
@ -314,6 +310,10 @@ static void pt_PostNotifyToCvar(PRCondVar *cvar, PRBool broadcast)
|
|||
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)
|
||||
|
@ -427,92 +427,54 @@ PR_IMPLEMENT(PRStatus) PR_NotifyAllCondVar(PRCondVar *cvar)
|
|||
/**************************************************************/
|
||||
/**************************************************************/
|
||||
|
||||
/*
|
||||
* 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();
|
||||
|
||||
mon = PR_NEWZAP(PRMonitor);
|
||||
if (mon == NULL)
|
||||
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);
|
||||
if (0 != rv)
|
||||
goto error3;
|
||||
|
||||
mon->notifyTimes = 0;
|
||||
mon->entryCount = 0;
|
||||
mon->cvar->lock = &mon->lock;
|
||||
if (0 != rv)
|
||||
{
|
||||
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)
|
||||
|
@ -527,114 +489,72 @@ 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 */
|
||||
|
@ -646,11 +566,11 @@ PR_IMPLEMENT(PRStatus) PR_Wait(PRMonitor *mon, PRIntervalTime timeout)
|
|||
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 */
|
||||
|
@ -658,54 +578,43 @@ PR_IMPLEMENT(PRStatus) PR_Wait(PRMonitor *mon, PRIntervalTime timeout)
|
|||
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 */
|
||||
|
||||
|
|
|
@ -122,11 +122,21 @@ 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
|
||||
|
@ -142,6 +152,11 @@ static void *_pt_root(void *arg)
|
|||
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
|
||||
|
||||
/*
|
||||
|
@ -153,7 +168,7 @@ static void *_pt_root(void *arg)
|
|||
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);
|
||||
}
|
||||
|
@ -172,28 +187,6 @@ static void *_pt_root(void *arg)
|
|||
|
||||
/* 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)
|
||||
|
@ -216,7 +209,7 @@ static void *_pt_root(void *arg)
|
|||
/*
|
||||
* 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)
|
||||
{
|
||||
|
@ -280,7 +273,6 @@ static PRThread* pt_AttachThread(void)
|
|||
|
||||
thred->priority = PR_PRIORITY_NORMAL;
|
||||
thred->id = pthread_self();
|
||||
thred->idSet = PR_TRUE;
|
||||
#ifdef _PR_NICE_PRIORITY_SCHEDULING
|
||||
thred->tid = gettid();
|
||||
#endif
|
||||
|
@ -501,32 +493,24 @@ static PRThread* _PR_CreateThread(
|
|||
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:
|
||||
|
@ -956,7 +940,6 @@ void _PR_InitThreads(
|
|||
thred->startFunc = NULL;
|
||||
thred->priority = priority;
|
||||
thred->id = pthread_self();
|
||||
thred->idSet = PR_TRUE;
|
||||
#ifdef _PR_NICE_PRIORITY_SCHEDULING
|
||||
thred->tid = gettid();
|
||||
#endif
|
||||
|
|
|
@ -260,7 +260,7 @@ int main(int argc, char **argv)
|
|||
#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());
|
||||
|
|
|
@ -79,7 +79,9 @@ static void sproc_start(void *arg, PRSize size)
|
|||
#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)
|
||||
|
@ -172,7 +174,7 @@ static PRStatus NSPRPUB_TESTS_CreateThread(StartFn start, void *arg)
|
|||
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;
|
||||
|
|
|
@ -753,7 +753,7 @@ static PRStatus NewThread(
|
|||
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;
|
||||
|
|
|
@ -347,7 +347,7 @@ PRInt32 native_thread = 0;
|
|||
stackSize,
|
||||
(unsigned (__stdcall *)(void *))start,
|
||||
arg,
|
||||
STACK_SIZE_PARAM_IS_A_RESERVATION,
|
||||
0,
|
||||
&tid);
|
||||
return((PRThread *) thandle);
|
||||
#endif
|
||||
|
|
|
@ -150,7 +150,7 @@ PRInt32 native_thread = 0;
|
|||
stackSize,
|
||||
(unsigned (__stdcall *)(void *))start,
|
||||
arg,
|
||||
STACK_SIZE_PARAM_IS_A_RESERVATION,
|
||||
0,
|
||||
&tid);
|
||||
return((PRThread *) thandle);
|
||||
#endif
|
||||
|
|
|
@ -20,9 +20,9 @@
|
|||
#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[] = {
|
||||
|
@ -37,7 +37,7 @@ static char *compatible_version[] = {
|
|||
"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
|
||||
};
|
||||
|
||||
|
@ -53,7 +53,7 @@ static char *incompatible_version[] = {
|
|||
"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"
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче