예제 #1
0
파일: osisleep.c 프로젝트: bagdxk/openafs
void osi_Sleep(LONG_PTR sleepVal)
{
    CRITICAL_SECTION *csp;

    /* may as well save some code by using SleepSched again */
    csp = &osi_baseAtomicCS[0];
    EnterCriticalSection(csp);
    osi_SleepSpin(sleepVal, csp);
}
예제 #2
0
void osi_SleepR(LONG_PTR sleepVal, struct osi_rwlock *lockp)
{
    long i;
    CRITICAL_SECTION *csp;
    osi_queue_t * lockRefH, *lockRefT;
    osi_lock_ref_t *lockRefp;
    DWORD tid = thrd_Current();

    if ((i = lockp->type) != 0) {
        if (i >= 0 && i < OSI_NLOCKTYPES)
            (osi_lockOps[i]->SleepRProc)(sleepVal, lockp);
        return;
    }

    /* otherwise we're the fast base type */
    csp = &osi_baseAtomicCS[lockp->atomicIndex];
    EnterCriticalSection(csp);

    if (lockOrderValidation && lockp->level != 0) {
        lockRefH = (osi_queue_t *)TlsGetValue(tls_LockRefH);
        lockRefT = (osi_queue_t *)TlsGetValue(tls_LockRefT);

        for (lockRefp = (osi_lock_ref_t *)lockRefH ; lockRefp; lockRefp = (osi_lock_ref_t *)osi_QNext(&lockRefp->q)) {
            if (lockRefp->type == OSI_LOCK_RW && lockRefp->rw == lockp) {
                osi_QRemoveHT(&lockRefH, &lockRefT, &lockRefp->q);
                lock_FreeLockRef(lockRefp);
                break;
            }
        }

        TlsSetValue(tls_LockRefH, lockRefH);
        TlsSetValue(tls_LockRefT, lockRefT);
    }

    osi_assertx(lockp->readers > 0, "osi_SleepR: not held");

    for ( i=0; i < lockp->readers; i++) {
        if ( lockp->tid[i] == tid ) {
            for ( ; i < lockp->readers - 1; i++)
                lockp->tid[i] = lockp->tid[i+1];
            lockp->tid[i] = 0;
            break;
        }
    }

    /* XXX better to get the list of things to wakeup from TSignalForMLs, and
     * then do the wakeup after SleepSpin releases the low-level mutex.
     */
    if (--(lockp->readers) == 0 && lockp->waiters) {
        osi_TSignalForMLs(&lockp->d.turn, 0, NULL);
    }

    /* now call into scheduler to sleep atomically with releasing spin lock */
    osi_SleepSpin(sleepVal, csp);
}
예제 #3
0
void osi_SleepW(LONG_PTR sleepVal, struct osi_rwlock *lockp)
{
    long i;
    CRITICAL_SECTION *csp;
    osi_queue_t * lockRefH, *lockRefT;
    osi_lock_ref_t *lockRefp;
    DWORD tid = thrd_Current();

    if ((i = lockp->type) != 0) {
        if (i >= 0 && i < OSI_NLOCKTYPES)
            (osi_lockOps[i]->SleepWProc)(sleepVal, lockp);
        return;
    }

    /* otherwise we're the fast base type */
    csp = &osi_baseAtomicCS[lockp->atomicIndex];
    EnterCriticalSection(csp);

    if (lockOrderValidation && lockp->level != 0) {
        lockRefH = (osi_queue_t *)TlsGetValue(tls_LockRefH);
        lockRefT = (osi_queue_t *)TlsGetValue(tls_LockRefT);

        for (lockRefp = (osi_lock_ref_t *)lockRefH ; lockRefp; lockRefp = (osi_lock_ref_t *)osi_QNext(&lockRefp->q)) {
            if (lockRefp->type == OSI_LOCK_RW && lockRefp->rw == lockp) {
                osi_QRemoveHT(&lockRefH, &lockRefT, &lockRefp->q);
                lock_FreeLockRef(lockRefp);
                break;
            }
        }

        TlsSetValue(tls_LockRefH, lockRefH);
        TlsSetValue(tls_LockRefT, lockRefT);
    }

    osi_assertx(lockp->flags & OSI_LOCKFLAG_EXCL, "osi_SleepW: not held");

    lockp->flags &= ~OSI_LOCKFLAG_EXCL;
    lockp->tid[0] = 0;
    if (lockp->waiters) {
        osi_TSignalForMLs(&lockp->d.turn, 0, NULL);
    }

    /* and finally release the big lock */
    osi_SleepSpin(sleepVal, csp);
}