Boolean VNonVirtualCriticalSection::Lock() { VTaskID currentTaskID = VTask::GetCurrentID(); do { VTaskID owner = (VTaskID) VInterlocked::CompareExchange((sLONG*) &fOwner, (sLONG) NULL_TASK_ID, (sLONG) currentTaskID); if (owner == NULL_TASK_ID) { assert(fUseCount == 0); fUseCount = 1; } else if (fOwner == currentTaskID) { ++fUseCount; } else { sLONG unlockCount = sUnlockCount; VSyncEvent* event = VInterlocked::ExchangePtr( &fEvent); if (event != NULL) { event->Retain(); if (VInterlocked::CompareExchangePtr((void **)&fEvent, NULL, event) != NULL) { event->Unlock(); event->Release(); VTask::YieldNow(); } else { while (VInterlocked::CompareExchange(&sUnlockCount, sUnlockCount, sUnlockCount) != sUnlockCount) VTask::YieldNow(); if (sUnlockCount == unlockCount) event->Lock( 100); else VTask::YieldNow(); } event->Release(); } else { event = new VSyncEvent; if (VInterlocked::CompareExchangePtr((void **)&fEvent, NULL, event) != NULL) { event->Unlock(); event->Release(); VTask::YieldNow(); } } } } while(fOwner != currentTaskID); return true; }
Boolean VSmallCriticalSection::Lock() { sWORD currentTaskID = (sWORD)VTask::GetCurrentID(); LongAsDoubleWord doubleWord; doubleWord.first = (sWORD)currentTaskID; doubleWord.second = 0; do { sLONG owner = VInterlocked::CompareExchange((sLONG*) &fOwner, (sLONG) 0, *((sLONG*) &doubleWord)); if (owner == 0) { assert(fUseCount == 0); fUseCount = 1; } else if (fOwner == currentTaskID) { ++fUseCount; } else { sLONG unlockCount = sUnlockCount; VSyncEvent* event = VInterlocked::ExchangePtr(&fEvent); if (event != NULL) { event->Retain(); if (VInterlocked::CompareExchangePtr((void**)&fEvent, NULL, event) != NULL) { event->Unlock(); VTask::YieldNow(); } else { if (sUnlockCount == unlockCount) event->Lock(100); else VTask::YieldNow(); } event->Release(); } else { event = new VSyncEvent; if (VInterlocked::CompareExchangePtr((void**)&fEvent, NULL, event) != NULL) { event->Release(); VTask::YieldNow(); } } } } while (fOwner != currentTaskID); return true; }
Boolean VSmallCriticalSection::Unlock() { //assert((fOwner == (sWORD)VTask::GetCurrentID()) && (fUseCount > 0) && (fUseCount < 32000L)); assert(fUseCount > 0); VSyncEvent* event = NULL; VInterlocked::Increment(&sUnlockCount); // Unlock or another successfull lock can only be called from same thead (so no contention can occur on fUseCount) if (--fUseCount == 0) { // capture currently set event event = VInterlocked::ExchangePtr(&fEvent); VTaskID owner = VInterlocked::Exchange((sLONG*) &fOwner, (sLONG) 0); //assert(owner == VTask::GetCurrentID()); if (event != NULL) { event->Unlock(); event->Release(); } } return true; }
Boolean VDBFlushMgr::NeedsBytes( VSize inNeededBytes) { Boolean isOK = false; if (VTask::GetCurrent() != fFlushTask) { sLONG lastStamp = StartFlushStamp; VTaskLock lock(&StartFlushMutex); if (lastStamp == StartFlushStamp) { { VSyncEvent* wait = NewFlushEnoughMemEvent(inNeededBytes); Flush( false); fNbWaitingClients++; wait->Lock(); fNbWaitingClients--; isOK = true; StartFlushStamp++; wait->Release(); } } else isOK = true; // si le stamp a change, cela veut dire qu'une autre tache a deja demande au flush de liberer sur disk de l'espace } return isOK; }
VError VJSContextPool::Clear() { VError err = VE_OK; bool savedEnabledState = fEnabled; // save the enabled state fEnabled = false; VSyncEvent *syncEvent = WaitForNumberOfUsedContextEqualZero(); if (syncEvent != NULL) { syncEvent->Lock(); syncEvent->Release(); } if (fPoolMutex.Lock()) { for (MapOfJSContext_iter iter = fUnusedContexts.begin() ; iter != fUnusedContexts.end() ; ++iter) { xbox_assert(iter->second->IsReusable()); VJSGlobalObject *globalObject = iter->second->GetGlobalObject(); if (globalObject != NULL) globalObject->GarbageCollect(); _ReleaseContext( iter->first); delete iter->second; --fReusableContextCount; } xbox_assert(fReusableContextCount == 0); fUnusedContexts.clear(); fPoolMutex.Unlock(); } fEnabled = savedEnabledState; // restore the enabled state return err; }
Boolean VNonVirtualCriticalSection::Unlock() { assert((fOwner == VTask::GetCurrentID()) && (fUseCount > 0) && (fUseCount < 32000L)); //assert(fUseCount > 0); VSyncEvent* event = NULL; VInterlocked::Increment(&sUnlockCount); if (--fUseCount == 0) { event = VInterlocked::ExchangePtr(&fEvent); VTaskID owner = VInterlocked::Exchange((sLONG*) &fOwner, (sLONG) NULL_TASK_ID); //assert(owner == VTask::GetCurrentID()); if (event != NULL) { event->Unlock(); event->Release(); } } return true; }
void VDBFlushMgr::Flush( Boolean inSynchronous, Boolean onlyForAllWritten) { #if debuglr == 101 if (fFlushProgress != nil && !fFlushProgress->IsManagerValid()) { sLONG xdebug = 1; // put a break here } #endif if (fFlushTask != nil) { if (inSynchronous) { #if trackClose trackDebugMsg("call flush synchronous\n"); #endif sLONG lastStamp = StartFlushStamp; VSyncEvent* wait = nil; { { VTaskLock lock(&StartFlushMutex); if (lastStamp == StartFlushStamp) { if (onlyForAllWritten) wait = NewFlushAllWrittenEvent(); else wait = NewFlushEndEvent(); #if trackClose trackDebugMsg("call flush synchronous after mutex\n"); #endif Flush( false); } } if (wait != nil) { wait->Lock(); wait->Release(); { VTaskLock lock(&StartFlushMutex); StartFlushStamp++; } } #if trackClose trackDebugMsg("end of call flush synchronous\n"); #endif } } else // pas synchrone { #if trackClose trackDebugMsg("call flush asynchronous\n"); #endif if (StartFlushMutex.TryToLock()) { #if trackClose trackDebugMsg("call flush asynchronous after mutex\n"); #endif { VTaskLock lock(&DirtyMutext); fIsAskingFlush = true; //fFlushTask->WakeUp(); } WakeUp(); StartFlushMutex.Unlock(); #if trackClose trackDebugMsg("release mutext for call flush asynchronous\n"); #endif } } } }