void SharedContents::Cleanup() { Assert(refCount == 0); buffer = nullptr; bufferLength = 0; #if DBG { AutoCriticalSection autoCS(&csAgent); if (allowedAgents != nullptr) { HeapDelete(allowedAgents); allowedAgents = nullptr; } } #endif if (indexToWaiterList != nullptr) { // TODO: the map should be empty here? // or we need to wake all the waiters from current context? indexToWaiterList->Map([](uint index, WaiterList *waiters) { if (waiters != nullptr) { waiters->Cleanup(); HeapDelete(waiters); waiters = nullptr; } }); HeapDelete(indexToWaiterList); indexToWaiterList = nullptr; } }
void XProcNumberPageSegmentManager::GetFreeSegment(XProcNumberPageSegment * seg) { AutoCriticalSection autoCS(&cs); if (segmentsList == nullptr) { new (seg) XProcNumberPageSegmentImpl(); return; } auto temp = segmentsList; auto prev = &segmentsList; while (temp) { if (temp->allocEndAddress != temp->pageAddress + (int)(XProcNumberPageSegmentImpl::PageCount*AutoSystemInfo::PageSize)) // not full { *prev = (XProcNumberPageSegmentImpl*)temp->nextSegment; // remove from the list memcpy(seg, temp, sizeof(XProcNumberPageSegment)); midl_user_free(temp); return; } prev = (XProcNumberPageSegmentImpl**)&temp->nextSegment; temp = (XProcNumberPageSegmentImpl*)temp->nextSegment; } }
WaiterList *SharedArrayBuffer::GetWaiterList(uint index) { if (sharedContents != nullptr) { // REVIEW: only lock creating the map and pass the lock to the map? // use one lock per instance? AutoCriticalSection autoCS(&csSharedArrayBuffer); if (sharedContents->indexToWaiterList == nullptr) { sharedContents->indexToWaiterList = HeapNew(IndexToWaitersMap, &HeapAllocator::Instance); } WaiterList * waiters = nullptr; if (!sharedContents->indexToWaiterList->TryGetValue(index, &waiters)) { waiters = HeapNew(WaiterList); sharedContents->indexToWaiterList->Add(index, waiters); } return waiters; } Assert(false); return nullptr; }
Var AtomicsObject::EntryWake(RecyclableObject* function, CallInfo callInfo, ...) { ATOMICS_FUNCTION_ENTRY_CHECKS(2, "Atomics.wake"); uint32 accessIndex = 0; TypedArrayBase *typedArrayBase = ValidateAndGetTypedArray(args[1], args[2], &accessIndex, scriptContext, true /*onlyInt32*/); int32 count = INT_MAX; if (args.Info.Count > 3 && !JavascriptOperators::IsUndefinedObject(args[3])) { double d = JavascriptConversion::ToInteger(args[3], scriptContext); if (!(NumberUtilities::IsNan(d) || JavascriptNumber::IsPosInf(d))) { int32 c = JavascriptConversion::ToInt32(d); count = max(0, c); } } Assert(typedArrayBase->GetBytesPerElement() == 4); uint32 bufferIndex = (accessIndex * 4) + typedArrayBase->GetByteOffset(); Assert(bufferIndex < typedArrayBase->GetArrayBuffer()->GetByteLength()); SharedArrayBuffer *sharedArrayBuffer = typedArrayBase->GetArrayBuffer()->GetAsSharedArrayBuffer(); WaiterList *waiterList = sharedArrayBuffer->GetWaiterList(bufferIndex); uint32 removed = 0; { AutoCriticalSection autoCS(waiterList->GetCriticalSectionForAccess()); removed = waiterList->RemoveAndWakeWaiters(count); } return JavascriptNumber::ToVar(removed, scriptContext); }
bool ServerContextManager::IsScriptContextAlive(ServerScriptContext* scriptContext) { AutoCriticalSection autoCS(&cs); if (scriptContexts.LookupWithKey(scriptContext)) { return !scriptContext->IsClosed(); } return false; }
bool ServerContextManager::IsThreadContextAlive(ServerThreadContext* threadContext) { AutoCriticalSection autoCS(&cs); if (threadContexts.LookupWithKey(threadContext)) { return !threadContext->IsClosed(); } return false; }
CStreamReadRequest* CStreamProcessor::PopFinishedRequest() { CAutoCriticalSection autoCS(m_FinishedRequestsCS); if (m_FinishedRequests.size() > 0) { CStreamReadRequest* pResult = m_FinishedRequests.front(); m_FinishedRequests.pop_front(); return pResult; } return 0; }
Var AtomicsObject::EntryWait(RecyclableObject* function, CallInfo callInfo, ...) { ATOMICS_FUNCTION_ENTRY_CHECKS(3, "Atomics.wait"); uint32 accessIndex = 0; TypedArrayBase *typedArrayBase = ValidateAndGetTypedArray(args[1], args[2], &accessIndex, scriptContext, true /*onlyInt32*/); int32 value = JavascriptConversion::ToInt32(args[3], scriptContext); uint32 timeout = INFINITE; if (args.Info.Count > 4 && !JavascriptOperators::IsUndefinedObject(args[4])) { double t =JavascriptConversion::ToNumber(args[4], scriptContext); if (!(NumberUtilities::IsNan(t) || JavascriptNumber::IsPosInf(t))) { int32 t1 = JavascriptConversion::ToInt32(t); timeout = (uint32)max(0, t1); } } if (!AgentOfBuffer::AgentCanSuspend(scriptContext)) { JavascriptError::ThrowTypeError(scriptContext, JSERR_CannotSuspendBuffer); } Assert(typedArrayBase->GetBytesPerElement() == 4); uint32 bufferIndex = (accessIndex * 4) + typedArrayBase->GetByteOffset(); Assert(bufferIndex < typedArrayBase->GetArrayBuffer()->GetByteLength()); SharedArrayBuffer *sharedArrayBuffer = typedArrayBase->GetArrayBuffer()->GetAsSharedArrayBuffer(); WaiterList *waiterList = sharedArrayBuffer->GetWaiterList(bufferIndex); bool awoken = false; { AutoCriticalSection autoCS(waiterList->GetCriticalSectionForAccess()); int32 w = JavascriptConversion::ToInt32(typedArrayBase->DirectGetItem(accessIndex), scriptContext); if (value != w) { return scriptContext->GetLibrary()->CreateStringFromCppLiteral(_u("not-equal")); } DWORD_PTR agent = (DWORD_PTR)scriptContext; Assert(sharedArrayBuffer->GetSharedContents()->IsValidAgent(agent)); awoken = waiterList->AddAndSuspendWaiter(agent, timeout); waiterList->RemoveWaiter(agent); } return awoken ? scriptContext->GetLibrary()->CreateStringFromCppLiteral(_u("ok")) : scriptContext->GetLibrary()->CreateStringFromCppLiteral(_u("timed-out")); }
void ServerContextManager::UnRegisterThreadContext(ServerThreadContext* threadContext) { AutoCriticalSection autoCS(&cs); threadContexts.Remove(threadContext); auto iter = scriptContexts.GetIteratorWithRemovalSupport(); while (iter.IsValid()) { ServerScriptContext* scriptContext = iter.Current().Key(); if (scriptContext->GetThreadContext() == threadContext) { scriptContext->Close(); iter.RemoveCurrent(); } iter.MoveNext(); } }
bool CStreamProcessor::RemoveOpenRequest(CStreamReadRequest* pRequest) { CAutoCriticalSection autoCS(m_OpenRequestsCS); if (m_OpenRequests.size() > 0) { TStreamReadRequestPtrList::iterator itFindRes = stl_find(m_OpenRequests.begin(), m_OpenRequests.end(), pRequest); if (itFindRes == m_OpenRequests.end()) return false; m_OpenRequests.erase(itFindRes); return true; } return 0; }
void XProcNumberPageSegmentManager::Integrate() { AutoCriticalSection autoCS(&cs); auto temp = this->segmentsList; auto prev = &this->segmentsList; while (temp) { if (temp->pageSegment == 0) { auto leafPageAllocator = recycler->GetRecyclerLeafPageAllocator(); DListBase<PageSegment> segmentList; temp->pageSegment = (intptr_t)leafPageAllocator->AllocPageSegment(segmentList, leafPageAllocator, (void*)temp->pageAddress, XProcNumberPageSegmentImpl::PageCount, temp->committedEnd / AutoSystemInfo::PageSize); leafPageAllocator->IntegrateSegments(segmentList, 1, XProcNumberPageSegmentImpl::PageCount); this->integratedSegmentCount++; } unsigned int minIntegrateSize = XProcNumberPageSegmentImpl::BlockSize; for (; temp->pageAddress + temp->blockIntegratedSize + minIntegrateSize < (unsigned int)temp->allocEndAddress; temp->blockIntegratedSize += minIntegrateSize) { TRACK_ALLOC_INFO(recycler, Js::JavascriptNumber, Recycler, 0, (size_t)-1); if (!recycler->IntegrateBlock<LeafBit>((char*)temp->pageAddress + temp->blockIntegratedSize, (PageSegment*)temp->pageSegment, XProcNumberPageSegmentImpl::GetSizeCat(), sizeof(Js::JavascriptNumber))) { Js::Throw::OutOfMemory(); } } *prev = (XProcNumberPageSegmentImpl*)temp->nextSegment; midl_user_free(temp); temp = *prev; } }
void ServerContextManager::UnRegisterScriptContext(ServerScriptContext* scriptContext) { AutoCriticalSection autoCS(&cs); scriptContexts.Remove(scriptContext); }
void ServerContextManager::RegisterThreadContext(ServerThreadContext* threadContext) { AutoCriticalSection autoCS(&cs); threadContexts.Add(threadContext); }
bool SharedContents::IsValidAgent(DWORD_PTR agent) { AutoCriticalSection autoCS(&csAgent); return allowedAgents != nullptr && allowedAgents->Contains(agent); }
void CStreamProcessor::PushFinishedRequest(CStreamReadRequest* pRequest) { CAutoCriticalSection autoCS(m_FinishedRequestsCS); m_FinishedRequests.push_back(pRequest); }