IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 31575


Ignore:
Timestamp:
May 26, 2011, 5:50:58 PM (15 years ago)
Author:
eugene
Message:

progress on per-memblock locking

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/eam_branches/ipp-20110505/psLib/src/sys/psMemory.c

    r31574 r31575  
    332332
    333333// if HARDLOCKS is set, revert to global locking for realloc
    334 # define HARDLOCKS 1
     334# define HARDLOCKS 0
     335
     336# if (!HARDLOCKS)
     337static int setLock1 = 0;
     338static int clearLock1 = 0;
     339
     340static int setLock2 = 0;
     341static int clearLock2 = 0;
     342
     343static int setLockNext = 0;
     344static int clearLockNext = 0;
     345
     346static int setLockPrev = 0;
     347static int clearLockPrev = 0;
     348# endif
     349
     350# define BLOCK_SLEEP 100
     351
     352static int callL1 = 0;
     353static int callL2 = 0;
     354
     355# define MEM_ASSERT(COND,MSG) { if (!(COND)) { fprintf (stderr, MSG); abort(); } }
     356
     357// pointer to the last mem block that was allocated.
     358// This is the root of the entire memory list
     359static psMemBlock *lastMemBlockAllocated = NULL;
     360
     361// set lock on lastMemBlockAllocated
     362void BLOCKLAST_LOCK () {
     363
     364# if (HARDLOCKS)
     365    MUTEX_LOCK(&memBlockListMutex);
     366# else
     367
     368    // if memBlock is not defined, we are just asking for a m
     369    if (!lastMemBlockAllocated) {
     370        MUTEX_LOCK(&memBlockListMutex);
     371        return;
     372    }
     373       
     374    while (true) {
     375        // we cannot set the lock on the marker while the lock is held
     376        while (lastMemBlockAllocated->inFlight) { usleep (BLOCK_SLEEP); }
     377
     378        // set a lock, then lock this memblock and its neighbors
     379        MUTEX_LOCK(&memBlockListMutex);
     380   
     381        // did we beat the race condition?  is the lock still clear?
     382        if (lastMemBlockAllocated->inFlight) {
     383            // nope, we need to try again
     384            MUTEX_UNLOCK(&memBlockListMutex);
     385            continue;
     386        }
     387
     388        // the marker is ours!
     389        lastMemBlockAllocated->inFlight = true;
     390        setLock1 ++;
     391        return;
     392    }
     393# endif
     394}
    335395
    336396// memBlock->inFlight is a 'soft' lock.  if true, the lock is set
     
    341401# else
    342402
    343     psAssert (memBlock || keepMutex, "trying to set a soft lock on a non-existent memBlock");
     403    MEM_ASSERT (memBlock || keepMutex, "trying to set a soft lock on a non-existent memBlock\n");
    344404
    345405    // if memBlock is not defined, we are just asking for a m
     
    351411    while (true) {
    352412        // we cannot set the lock on the marker while the lock is held
    353         while (memBlock->inFlight) { usleep (10000); }
     413        while (memBlock->inFlight) { usleep (BLOCK_SLEEP); }
    354414
    355415        // set a lock, then lock this memblock and its neighbors
     
    365425        // the marker is ours!
    366426        memBlock->inFlight = true;
     427        setLock1 ++;
    367428        if (keepMutex) return;
    368429
     
    379440# else
    380441
    381     psAssert (memBlock || haveMutex, "trying to clear a soft lock on a non-existent memBlock");
     442    MEM_ASSERT (memBlock || haveMutex, "trying to clear a soft lock on a non-existent memBlock\n");
    382443
    383444    // if memBlock is not defined, we are just asking for a regular lock
     
    387448    }
    388449
     450    MEM_ASSERT (memBlock->inFlight, "trying to clear an unlocked memBlock\n");
     451
    389452    // need to lock before clearing the marker
    390453    if (!haveMutex) {
     
    392455    }
    393456    memBlock->inFlight = false;
     457    clearLock1 ++;
    394458    MUTEX_UNLOCK(&memBlockListMutex);
    395459    return;
     
    406470# else
    407471
    408     psAssert (memBlock, "trying to set a soft lock on a non-existent memBlock");
     472    MEM_ASSERT (memBlock, "trying to set a soft lock on a non-existent memBlock\n");
    409473
    410474    while (true) {
    411475        // we cannot set the lock on the marker while the lock is held
    412476        // wait until all three markers are clear:
    413         while (memBlock->inFlight) { usleep (10000); }
    414         if (memBlock->nextBlock) {
    415             while (memBlock->nextBlock->inFlight) { usleep (10000); }
    416         }
    417         if (memBlock->previousBlock) {
    418             while (memBlock->previousBlock->inFlight) { usleep (10000); }
    419         }
     477        while (memBlock->inFlight) { usleep (BLOCK_SLEEP); }
     478        while (memBlock->nextBlock && memBlock->nextBlock->inFlight) { usleep (BLOCK_SLEEP); }
     479        while (memBlock->previousBlock && memBlock->previousBlock->inFlight) { usleep (BLOCK_SLEEP); }
    420480
    421481        // set a lock, then lock this memblock and its neighbors
     
    441501        // the markers are ours!
    442502        memBlock->inFlight = true;
     503        setLock2 ++;
    443504        if (memBlock->nextBlock) {
    444505            memBlock->nextBlock->inFlight = true;
     506            setLockNext ++;
    445507        }
    446508        if (memBlock->previousBlock) {
    447509            memBlock->previousBlock->inFlight = true;
     510            setLockPrev ++;
    448511        }
    449512        if (keepMutex) return;
     
    465528        MUTEX_LOCK(&memBlockListMutex);
    466529    }
     530    MEM_ASSERT (memBlock->inFlight, "trying to clear an unlocked memBlock\n");
    467531    memBlock->inFlight = false;
     532    clearLock2 ++;
    468533    if (memBlock->nextBlock) {
     534        MEM_ASSERT (memBlock->nextBlock->inFlight, "trying to clear an unlocked memBlock\n");
    469535        memBlock->nextBlock->inFlight = false;
     536        clearLockNext ++;
    470537    }
    471538    if (memBlock->previousBlock) {
     539        MEM_ASSERT (memBlock->previousBlock->inFlight, "trying to clear an unlocked memBlock\n");
    472540        memBlock->previousBlock->inFlight = false;
     541        clearLockPrev ++;
    473542    }
    474543    MUTEX_UNLOCK(&memBlockListMutex);
     
    476545# endif
    477546}
    478 
    479 // pointer to the last mem block that was allocated.
    480 // This is the root of the entire memory list
    481 static psMemBlock *lastMemBlockAllocated = NULL;
    482547
    483548/* Actually allocate memory
     
    549614    memBlock->refCounter = 1;                   // one user so far
    550615
     616    psMemBlock *last0 = lastMemBlockAllocated;
     617    int flight0 = (lastMemBlockAllocated) ? lastMemBlockAllocated->inFlight : 10;
     618
    551619    // need exclusive access of the memory block list now...
    552620    // this lock is very frequently called in a given program
    553621    // lastMemBlockAllocated is always true except the first allocation
    554     BLOCK_LOCK (lastMemBlockAllocated, true);
     622    BLOCKLAST_LOCK ();
     623    callL1++;
     624
     625    psMemBlock *last1 = lastMemBlockAllocated;
     626    int flight1 = (lastMemBlockAllocated) ? lastMemBlockAllocated->inFlight : 10;
     627
     628    if (false) {
     629        fprintf (stderr, "last 0 : %lld, last 1 : %lld, flight0: %d, flight1: %d\n", (long long int) last0, (long long int) last1, (int) flight0, (int) flight1);
     630    }
    555631
    556632    // increment the memory id only after we've grabbed the memBlockListMutex this value is
     
    573649
    574650    BLOCK_UNLOCK (memBlock->nextBlock, true);
     651    callL1--;
     652
     653    // if (callL1 > +7) abort();
     654    // if (callL1 < -7) abort();
    575655
    576656    // And return the user the memory that they allocated
     
    720800    // set a lock, then lock this memblock and its neighbors.  at the end of this call,
    721801    // the global mutex is released, but the memBlock and its neighbors are protected
    722     BLOCKSET_LOCK (memBlock, false);
    723     // MUTEX_LOCK(&memBlockListMutex);
     802    // BLOCKSET_LOCK (memBlock, false);
     803    MUTEX_LOCK(&memBlockListMutex);
    724804
    725805    psMemBlock *nextBlock = memBlock->nextBlock;
     
    767847
    768848    // all of the list modifications are done; set the lock and clear the per-memBlock locks
    769     // MUTEX_UNLOCK(&memBlockListMutex);
    770     BLOCKSET_UNLOCK(memBlock, false);
    771 
    772     psAssert (!memBlock->inFlight, "unreleased lock?");
    773     psAssert (!nextBlock || !nextBlock->inFlight, "unreleased lock?");
    774     psAssert (!previousBlock || !previousBlock->inFlight, "unreleased lock?");
     849    // BLOCKSET_UNLOCK(memBlock, false);
     850    MUTEX_UNLOCK(&memBlockListMutex);
     851
     852    // XXX these are not actually guaranteed : another thread may already grab them before we get here
     853    // psAssert (!memBlock->inFlight, "unreleased lock?");
     854    // psAssert (!nextBlock || !nextBlock->inFlight, "unreleased lock?");
     855    // psAssert (!previousBlock || !previousBlock->inFlight, "unreleased lock?");
    775856
    776857    return memBlock + 1;                    // usr memory
     
    9991080    // we need a MUTEX_LOCK here: otherwise, two functions can race on refCounter--;
    10001081    BLOCK_LOCK (memBlock, true);
     1082    callL2++;
    10011083    if (memBlock->refCounter > 1) {
    10021084        memBlock->refCounter--;
     
    10071089        }
    10081090        BLOCK_UNLOCK(memBlock, true);
     1091        callL2--;
    10091092        return ptr;
    10101093    }
    10111094    BLOCK_UNLOCK(memBlock, true);
     1095    callL2--;
     1096    // if (callL2 > +7) abort();
     1097    // if (callL2 < -7) abort();
    10121098
    10131099    // we can't invoke freeFunc() while we're holding memBlockListMutex as it
     
    10411127    BLOCKSET_UNLOCK (memBlock, true);
    10421128
     1129    // XXX keep this?
     1130    psAssert (memBlock->nextBlock == nextBlock, "unexpected rearrangement");
     1131    psAssert (memBlock->previousBlock == previousBlock, "unexpected rearrangement");
     1132
    10431133    // NULL out the refs so no one can get confused
    10441134    memBlock->nextBlock = NULL;
    10451135    memBlock->previousBlock = NULL;
    10461136
    1047     // XXX these are slightly dangerous : someone else may grab the lock in the meanwhile...
    1048     psAssert (!memBlock->inFlight, "unreleased lock?");
    1049     psAssert (!nextBlock || !nextBlock->inFlight, "unreleased lock?");
    1050     psAssert (!previousBlock || !previousBlock->inFlight, "unreleased lock?");
     1137    // XXX these are not actually guaranteed : another thread may already grab them before we get here
     1138    // psAssert (!memBlock->inFlight, "unreleased lock?");
     1139    // psAssert (!nextBlock || !nextBlock->inFlight, "unreleased lock?");
     1140    // psAssert (!previousBlock || !previousBlock->inFlight, "unreleased lock?");
    10511141
    10521142    // invoke free only after we've released the block list lock as free()
Note: See TracChangeset for help on using the changeset viewer.