Ejemplo n.º 1
0
PR_IMPLEMENT(PRStatus) PR_Wait(PRMonitor *mon, PRIntervalTime timeout)
{
    PRStatus rv;
    PRInt16 saved_entries;
    pthread_t saved_owner;

    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()));

    /* 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);
    
    rv = PR_WaitCondVar(mon->cvar, timeout);

    /* reinstate the intresting information */
    mon->entryCount = saved_entries;
    _PT_PTHREAD_COPY_THR_HANDLE(saved_owner, mon->owner);

    return rv;
}  /* PR_Wait */
Ejemplo n.º 2
0
PR_IMPLEMENT(PRStatus) PR_Wait(PRMonitor *mon, PRIntervalTime timeout)
{
    PRStatus rv;
    PRUint32 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 */
    PR_ASSERT(mon->entryCount > 0);
    /* and it better be owned 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);

    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 */
    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 */
Ejemplo n.º 3
0
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);
    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);
        return PR_FAILURE;
    }

    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;
        /* We will access the members of 'mon' after unlocking mon->lock.
         * Add a reference. */
        PR_ATOMIC_INCREMENT(&mon->refCount);
    }
    rv = pthread_mutex_unlock(&mon->lock);
    PR_ASSERT(0 == rv);
    if (notifyEntryWaiter)
    {
        if (notifyTimes)
            pt_PostNotifiesFromMonitor(&mon->waitCV, notifyTimes);
        rv = pthread_cond_signal(&mon->entryCV);
        PR_ASSERT(0 == rv);
        /* We are done accessing the members of 'mon'. Release the
         * reference. */
        PR_DestroyMonitor(mon);
    }
    return PR_SUCCESS;
}  /* PR_ExitMonitor */
Ejemplo n.º 4
0
PR_IMPLEMENT(PRMonitor*) PR_NewMonitor(void)
{
    PRMonitor *mon;
    int rv;

    if (!_pr_initialized) _PR_ImplicitInitialization();

    mon = PR_NEWZAP(PRMonitor);
    if (mon == NULL)
    {
        PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
        return NULL;
    }

    rv = _PT_PTHREAD_MUTEX_INIT(mon->lock, _pt_mattr);
    PR_ASSERT(0 == rv);
    if (0 != rv)
        goto error1;

    _PT_PTHREAD_INVALIDATE_THR_HANDLE(mon->owner);

    rv = _PT_PTHREAD_COND_INIT(mon->entryCV, _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->refCount = 1;
    mon->name = 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 */
Ejemplo n.º 5
0
PR_IMPLEMENT(PRStatus) PR_ExitMonitor(PRMonitor *mon)
{
    pthread_t self = pthread_self();

    PR_ASSERT(mon != NULL);
    /* 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 (!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 - unlock */
        _PT_PTHREAD_INVALIDATE_THR_HANDLE(mon->owner);  /* make the owner unknown */
        PR_Unlock(&mon->lock);
    }
    return PR_SUCCESS;
}  /* PR_ExitMonitor */
Ejemplo n.º 6
0
PR_IMPLEMENT(PRMonitor*) PR_NewMonitor(void)
{
    PRMonitor *mon;
    PRCondVar *cvar;

    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)
    {
        int rv;
        rv = _PT_PTHREAD_MUTEX_INIT(mon->lock.mutex, _pt_mattr); 
        PR_ASSERT(0 == rv);

        _PT_PTHREAD_INVALIDATE_THR_HANDLE(mon->owner);

        mon->cvar = cvar;
        rv = _PT_PTHREAD_COND_INIT(mon->cvar->cv, _pt_cvar_attr); 
        PR_ASSERT(0 == rv);
        mon->entryCount = 0;
        mon->cvar->lock = &mon->lock;
        if (0 != rv)
        {
            PR_DELETE(mon);
            PR_DELETE(cvar);
            mon = NULL;
        }
    }
    return mon;
}  /* PR_NewMonitor */