static inline void System_Poll( void ) { enum EPowerMode pwr_mode = pm_down; CheckStack(); sys_pwr |= core_pwr_getstate(); sys_pwr |= DispHAL_App_Poll(); if ( BeepIsRunning() ) sys_pwr |= PM_SLEEP; // decide power management model if ( sys_pwr & PM_FULL ) pwr_mode = pm_full; // full run mode - no sleeping else if ( sys_pwr & PM_SLEEP ) pwr_mode = pm_sleep; // sleep and wake up on timer/dma irq else { if ( sys_pwr & PM_HOLD_BTN ) pwr_mode = pm_hold_btn; // device with active UI, but with low cpu usage - any button should wake it up else if ( sys_pwr & PM_HOLD ) pwr_mode = pm_hold; // device is working on background only (monitoring/registering tasks), no active UI, should be woken up by the user by power button only else { core_nvfast_save_struct(); pwr_mode = pm_down; // no power requirement is needed - turn it off } core_pwr_setup_alarm(pwr_mode); // set up the next alarm point in the RTC EventBtnClear(); // clear button status } wake_up = HW_Sleep( pwr_mode ); // enter in the selected power mode sys_pwr = 0; // when exit - recreate the power scenario }
int yarg_true(int iarg) { Symbol *s = (iarg>=0)? sp - iarg : 0; int x = 0; if (s) { CheckStack(1); sp[1].ops = &intScalar; if (s->ops==&referenceSym) s = &globTab[s->index]; if (s->ops != &dataBlockSym) sp[1].value = s->value; else sp[1].value.db = Ref(s->value.db); sp++; sp->ops = s->ops; sp->ops->True(); x = (int)ygets_l(0); yarg_drop(1); } return x; }
void CLuaHandleSynced::Init(const string& syncedFile, const string& unsyncedFile, const string& modes) { if (!IsValid()) return; const string syncedCode = LoadFile(syncedFile, modes); const string unsyncedCode = LoadFile(unsyncedFile, modes); if (syncedCode.empty() && unsyncedCode.empty()) { KillLua(); return; } const bool haveSynced = syncedLuaHandle.Init(syncedCode, syncedFile); const bool haveUnsynced = unsyncedLuaHandle.Init(unsyncedCode, unsyncedFile); if (!IsValid() || (!haveSynced && !haveUnsynced)) { KillLua(); return; } CheckStack(); }
void CTabBarClass::Update(BOOL abPosted/*=FALSE*/) { #ifdef _DEBUG if (this != gpConEmu->mp_TabBar) { _ASSERTE(this == gpConEmu->mp_TabBar); } #endif MCHKHEAP /*if (!_active) { return; }*/ // Теперь - ВСЕГДА! т.к. сами управляем мультиконсолью if (mb_DisableRedraw) { _ASSERTE(FALSE && "mb_DisableRedraw?"); // Надо? return; } if (!isMainThread()) { RequestPostUpdate(); return; } gpConEmu->mp_Status->UpdateStatusBar(); mb_PostUpdateCalled = FALSE; #ifdef _DEBUG _ASSERTE(mn_InUpdate >= 0); if (mn_InUpdate > 0) { _ASSERTE(mn_InUpdate == 0); } #endif mn_InUpdate ++; MCHKHEAP int V, I, tabIdx = 0, nCurTab = -1; BOOL bShowFarWindows = gpSet->bShowFarWindows; // Выполняться должно только в основной нити, так что CriticalSection не нужна #ifdef _DEBUG if (this != gpConEmu->mp_TabBar) { _ASSERTE(this == gpConEmu->mp_TabBar); } #endif TODO("Обработка gpSet->bHideInactiveConsoleTabs для новых табов"); MCHKHEAP // Check if we need to AutoSHOW or AutoHIDE tab bar if (!IsTabsActive() && gpSet->isTabs) { int nTabs = CountActiveTabs(2); if (nTabs > 1) { Activate(); } } else if (IsTabsActive() && gpSet->isTabs==2) { int nTabs = CountActiveTabs(2); if (nTabs <= 1) { Deactivate(); } } // Validation? #ifdef _DEBUG if (this != gpConEmu->mp_TabBar) { _ASSERTE(this == gpConEmu->mp_TabBar); } #endif MCHKHEAP HANDLE hUpdate = m_Tabs.UpdateBegin(); _ASSERTE(hUpdate!=NULL); bool bStackChanged = false; /* ********************* */ /* Go */ /* ********************* */ { MMap<CVConGroup*,CVirtualConsole*> Groups; Groups.Init(MAX_CONSOLE_COUNT, true); for (V = 0; V < MAX_CONSOLE_COUNT; V++) { //if (!(pVCon = gpConEmu->GetVCon(V))) continue; CVConGuard guard; if (!CVConGroup::GetVCon(V, &guard)) continue; CVirtualConsole* pVCon = guard.VCon(); BOOL lbActive = pVCon->isActive(false); if (gpSet->bHideInactiveConsoleTabs && !lbActive) continue; if (gpSet->isOneTabPerGroup) { CVConGroup *pGr; CVConGuard VGrActive; if (CVConGroup::isGroup(pVCon, &pGr, &VGrActive)) { CVirtualConsole* pGrVCon; if (Groups.Get(pGr, &pGrVCon)) continue; // эта группа уже есть pGrVCon = VGrActive.VCon(); Groups.Set(pGr, pGrVCon); // И показывать таб нужно от "активной" консоли, а не от первой в группе if (pVCon != pGrVCon) { guard = pGrVCon; pVCon = pGrVCon; } if (!lbActive) { lbActive = pVCon->isActive(true); } // Показывать редакторы из всех групп? if (gpSet->bShowFarWindows) { MArray<CVConGuard*> Panes; int nPanes = pGr->GetGroupPanes(&Panes); // Только если в группе более одного таба - тогда нужно дополниетльная логика населения... if (nPanes > 1) { // Первым табом - показать текущую панель, либо МОДАЛЬНЫЙ редактор/вьювер // Редакторы из "far /e ..." здесь НЕ добавлять! if (!pVCon->RCon()->isFarPanelAllowed() || !UpdateAddTab(hUpdate, tabIdx, nCurTab, bStackChanged, pVCon, uat_PanelsOrModalsOnly)) { // Если есть - добавить ОДНУ панель, чтобы табы сплита не прыгали туда-сюда for (int K = 0; K < nPanes; K++) { if (Panes[K]->VCon()->RCon()->isFarPanelAllowed()) { if (UpdateAddTab(hUpdate, tabIdx, nCurTab, bStackChanged, Panes[K]->VCon(), uat_PanelsOnly) > 0) break; } } } // Потом - все оставшиеся редакторы/вьюверы (в том числе и "far /e ...") for (int K = 0; K < nPanes; K++) { UpdateAddTab(hUpdate, tabIdx, nCurTab, bStackChanged, Panes[K]->VCon(), uat_NonModals|uat_NonPanels); } // Release CVConGroup::FreePanesArray(Panes); // Already processed, next VCon continue; } } } } UpdateAddTab(hUpdate, tabIdx, nCurTab, bStackChanged, pVCon, uat_AnyTab); } Groups.Release(); } MCHKHEAP // Must be at least one tab ("ConEmu -Detached" for example) if (tabIdx == 0) { m_Tabs.UpdateAppend(hUpdate, mp_DummyTab, FALSE); // Физически (WinAPI) добавляет закладку, или меняет (при необходимости) заголовок существующей mp_Rebar->AddTabInt(gpConEmu->GetDefaultTabLabel(), tabIdx, gpConEmu->mb_IsUacAdmin, -1); nCurTab = tabIdx; tabIdx++; } m_Tabs.UpdateEnd(hUpdate, 0); // Проверим стек последних выбранных if (CheckStack()) bStackChanged = true; #ifdef PRINT_RECENT_STACK PrintRecentStack(); #endif #ifdef _DEBUG static int nPrevVisible, nPrevStacked; { wchar_t szDbg[100]; int nNewVisible = m_Tabs.GetCount(); int nNewStacked = m_TabStack.size(); _wsprintf(szDbg, SKIPLEN(countof(szDbg)) L"*** Tab list updated. Visible:%u, Stacked:%u, StackChanged:%s\n", nNewVisible, nNewStacked, bStackChanged ? L"Yes" : L"No"); DEBUGSTRCOUNT(szDbg); nPrevVisible = nNewVisible; nPrevStacked = nNewStacked; } #endif // удалить лишние закладки (визуально) int nCurCount = GetItemCount(); #ifdef _DEBUG wchar_t szDbg[128]; _wsprintf(szDbg, SKIPLEN(countof(szDbg)) L"CTabBarClass::Update. ItemCount=%i, PrevItemCount=%i\n", tabIdx, nCurCount); DEBUGSTRTABS(szDbg); #endif if (mp_Rebar->IsTabbarCreated()) { for (I = tabIdx; I < nCurCount; I++) { #ifdef _DEBUG _wsprintf(szDbg, SKIPLEN(countof(szDbg)) L" Deleting tab=%i\n", I+1); DEBUGSTRTABS(szDbg); #endif DeleteItem(tabIdx); } } MCHKHEAP if (mb_InKeySwitching) { if (mn_CurSelTab >= nCurCount) // Если выбранный таб вылез за границы mb_InKeySwitching = false; } if (!mb_InKeySwitching && nCurTab != -1) { SelectTab(nCurTab); } UpdateToolConsoles(); //if (gpSet->isTabsInCaption) //{ // SendMessage(ghWnd, WM_NCPAINT, 0, 0); //} mn_InUpdate --; if (mb_PostUpdateRequested) { mb_PostUpdateCalled = FALSE; mb_PostUpdateRequested = FALSE; RequestPostUpdate(); } MCHKHEAP return; // Just for clearness }
void LuaState::CheckStack(int space, const String& error) const { CheckStack(space, error.GetConstBuffer()); }
void EvalFN(Operand *op) { Symbol *stack= op->owner; int n= op->references; /* (sic) # of actual parameters supplied */ Function *func= op->value; Instruction *code= &func->code[1]; /* (code[0] is index to function) */ int nReq= func->nReq; /* (see CheckStack call below) */ int nPos= func->nPos; /* number of dummy positional parameters */ int nKey= func->nKey; /* number of dummy keyword parameters */ int nLoc= func->nLocal; /* number of local variables */ long hasPosList= func->hasPosList; long posList; int actual, dummy, index, nExtra; Symbol *spnow, *extraPos, *key; P_SOFTFPE_TEST; /* Be sure the stack is long enough for a worst-case invocation of this function. nReq= nPos + (hasPosList&1) + nKey + nLoc + (deepest stack required for expression evaluation) + 10 + 1 for return address for this function The nPos and nKey terms must be present because they may not be actual arguments, and because even if they are supplied they may be referenceSyms which must be copied for use during return. The extra 10 is so that builtin procedures are always guaranteed 8(+2 for luck) free stack slots without calling CheckStack. */ if (CheckStack(nReq)) stack= sp-n; /* Handle all actual parameters. This must be done in two passes to avoid accidental collisions between dummy parameters and indirect references on the stack to external variables of the same name. All of this could be avoided if function parameters were always passed by value, never by reference. But I can't bring myself to disallow the FORTRAN-like function which uses its parameters to return values. */ /* First pass copies any indirect references. The parser has guaranteed that index (dummy) will not be repeated, since there may not be 2 dummy parameters with the same name. However, nothing prevents the one or more of the actual parameters (stack) from being referenceSyms to the same name as a dummy parameter. This possibility requires copying all referenceSym actual parameters onto the stack (possibly multiple times). Also, note that a globTab entry may NEVER be a referenceSym, so if return is to affect external values of parameters, any referenceSym parameters must remain on the stack. */ posList= hasPosList>>1; hasPosList&= 1; nExtra= -nPos; spnow= stack; for (actual=0 ; actual<n ; actual++) { spnow++; if (spnow->ops) { if (spnow->ops==&referenceSym) { if (posList) { if (nExtra<0 && (posList&1)) { /* this is an output parameter */ extraPos= sp+1; /* push copy of referenceSym */ extraPos->ops= &referenceSym; extraPos->index= spnow->index; extraPos->value.offset= extraPos-spnow; /* install ref offset */ sp= extraPos; } posList>>= 1; } ReplaceRef(spnow); /* replace original reference by object */ } else if (posList) { posList>>= 1; } nExtra++; } else {
static inline void System_Poll( void ) { CheckStack(); }
pascal OSErr IndexedSearch(CSParamPtr pb, long dirID) { static LevelRecHandle searchStack = NULL; /* static handle to LevelRec stack */ static Size searchStackSize = 0; /* size of static handle */ SearchPositionRecPtr catPosition; long modDate; short index = -1 ; ExtendedTMTask timerTask; OSErr result; short realVRefNum; Str63 itemName; CInfoPBRec cPB; long tempLong; Boolean includeFiles; Boolean includeDirs; Boolean includeNames; Str63 upperName; timerTask.stopSearch = false; /* don't stop yet! */ /* If request has a timeout, install a Time Manager task. */ if ( pb->ioSearchTime != 0 ) { /* Start timer */ timerTask.theTask.tmAddr = NewTimerUPP(TimeOutTask); InsTime((QElemPtr)&(timerTask.theTask)); PrimeTime((QElemPtr)&(timerTask.theTask), pb->ioSearchTime); } /* Check the parameter block passed for things that we don't want to assume */ /* are OK later in the code. For example, make sure pointers to data structures */ /* and buffers are not NULL. And while we're in there, see if the request */ /* specified searching for files, directories, or both, and see if the search */ /* was by full or partial name. */ result = VerifyUserPB(pb, &includeFiles, &includeDirs, &includeNames); if ( result == noErr ) { pb->ioActMatchCount = 0; /* no matches yet */ if ( includeNames ) { /* The search includes seach by full or partial name. */ /* Make an upper case copy of the match string to pass to */ /* CheckForMatches. */ BlockMoveData(pb->ioSearchInfo1->hFileInfo.ioNamePtr, upperName, pb->ioSearchInfo1->hFileInfo.ioNamePtr[0] + 1); /* Use the same non-international call the File Manager uses */ UpperString(upperName, true); } /* Prevent casting to my type throughout code */ catPosition = (SearchPositionRecPtr)&pb->ioCatPosition; /* Create searchStack first time called */ if ( searchStack == NULL ) { searchStack = (LevelRecHandle)NewHandle(kAdditionalLevelRecs * sizeof(LevelRec)); } /* Make sure searchStack really exists */ if ( searchStack != NULL ) { searchStackSize = GetHandleSize((Handle)searchStack); /* See if the search is a new search or a resumed search. */ if ( catPosition->initialize == 0 ) { /* New search. */ /* Get the real vRefNum and fill in catPosition->initialize. */ result = CheckVol(pb->ioNamePtr, pb->ioVRefNum, &realVRefNum, &catPosition->initialize); if ( result == noErr ) { /* clear searchStack */ catPosition->stackDepth = 0; /* use dirID parameter passed and... */ index = -1; /* start with the passed directory itself! */ } } else { /* We're resuming a search. */ /* Get the real vRefNum and make sure catPosition->initialize is valid. */ result = CheckVol(pb->ioNamePtr, pb->ioVRefNum, &realVRefNum, &tempLong); if ( result == noErr ) { /* Make sure the resumed search is to the same volume! */ if ( catPosition->initialize == tempLong ) { /* For resume, catPosition->stackDepth > 0 */ if ( catPosition->stackDepth > 0 ) { /* Position catPosition->stackDepth to access last saved level */ --(catPosition->stackDepth); /* Get the dirID and index for the next item */ dirID = (*searchStack)[catPosition->stackDepth].dirID; index = (*searchStack)[catPosition->stackDepth].index; /* Check the dir's mod date against the saved mode date on our "stack" */ modDate = GetDirModDate(realVRefNum, dirID); if ( modDate != (*searchStack)[catPosition->stackDepth].dirModDate ) { result = catChangedErr; } } else { /* Invalid catPosition record was passed */ result = paramErr; } } else { /* The volume is not the same */ result = catChangedErr; } } } if ( result == noErr ) { /* ioNamePtr and ioVRefNum only need to be set up once. */ cPB.hFileInfo.ioNamePtr = itemName; cPB.hFileInfo.ioVRefNum = realVRefNum; /* ** Here's the loop that: ** Finds the next item on the volume. ** If noErr, calls the code to check for matches and add matches ** to the match buffer. ** Sets up dirID and index for to find the next item on the volume. ** ** The looping ends when: ** (a) an unexpected error is returned by PBGetCatInfo. All that ** is expected is noErr and fnfErr (after the last item in a ** directory is found). ** (b) the caller specified a timeout and our Time Manager task ** has fired. ** (c) the number of matches requested by the caller has been found. ** (d) the last item on the volume was found. */ do { /* get the next item */ cPB.hFileInfo.ioFDirIndex = index; cPB.hFileInfo.ioDirID = dirID; result = PBGetCatInfoSync(&cPB); if ( index != -1 ) { if ( result == noErr ) { /* We found something */ CheckForMatches(&cPB, pb, upperName, includeFiles, includeDirs); ++index; if ( (cPB.dirInfo.ioFlAttrib & kioFlAttribDirMask) != 0 ) { /* It's a directory */ result = CheckStack(catPosition->stackDepth, searchStack, &searchStackSize); if ( result == noErr ) { /* Save the current state on the searchStack */ /* when we come back, this is where we'll start */ (*searchStack)[catPosition->stackDepth].dirID = dirID; (*searchStack)[catPosition->stackDepth].index = index; (*searchStack)[catPosition->stackDepth].dirModDate = GetDirModDate(realVRefNum, dirID); /* position catPosition->stackDepth for next saved level */ ++(catPosition->stackDepth); /* The next item to get is the 1st item in the child directory */ dirID = cPB.dirInfo.ioDrDirID; index = 1; } } /* else do nothing for files */ } else { /* End of directory found (or we had some error and that */ /* means we have to drop out of this directory). */ /* Restore last thing put on stack and */ /* see if we need to continue or quit. */ if ( catPosition->stackDepth > 0 ) { /* position catPosition->stackDepth to access last saved level */ --(catPosition->stackDepth); dirID = (*searchStack)[catPosition->stackDepth].dirID; index = (*searchStack)[catPosition->stackDepth].index; /* Check the dir's mod date against the saved mode date on our "stack" */ modDate = GetDirModDate(realVRefNum, dirID); if ( modDate != (*searchStack)[catPosition->stackDepth].dirModDate ) { result = catChangedErr; } else { /* Going back to ancestor directory. */ /* Clear error so we can continue. */ result = noErr; } } else { /* We hit the bottom of the stack, so we'll let the */ /* the eofErr drop us out of the loop. */ result = eofErr; } } } else { /* Special case for index == -1; that means that we're starting */ /* a new search and so the first item to check is the directory */ /* passed to us. */ if ( result == noErr ) { /* We found something */ CheckForMatches(&cPB, pb, upperName, includeFiles, includeDirs); /* Now, set the index to 1 and then we're ready to look inside */ /* the passed directory. */ index = 1; } } } while ( (!timerTask.stopSearch) && /* timer hasn't fired */ (result == noErr) && /* no unexpected errors */ (pb->ioReqMatchCount > pb->ioActMatchCount) ); /* we haven't found our limit */ /* Did we drop out of the loop because of timeout or */ /* ioReqMatchCount was found? */ if ( result == noErr ) { result = CheckStack(catPosition->stackDepth, searchStack, &searchStackSize); if ( result == noErr ) { /* Either there was a timeout or ioReqMatchCount was reached. */ /* Save the dirID and index for the next time we're called. */ (*searchStack)[catPosition->stackDepth].dirID = dirID; (*searchStack)[catPosition->stackDepth].index = index; (*searchStack)[catPosition->stackDepth].dirModDate = GetDirModDate(realVRefNum, dirID); /* position catPosition->stackDepth for next saved level */ ++(catPosition->stackDepth); } } } } else { /* searchStack Handle could not be allocated */ result = memFullErr; } } if ( pb->ioSearchTime != 0 ) { /* Stop Time Manager task here if it was installed */ RmvTime((QElemPtr)&(timerTask.theTask)); DisposeTimerUPP(timerTask.theTask.tmAddr); } return ( result ); }
void NzLuaInstance::CheckStack(int space, const NzString& error) const { CheckStack(space, error.GetConstBuffer()); }
// ===================================================================================== // RecursiveLeafFlow // Flood fill through the leafs // If src_portal is NULL, this is the originating leaf // ===================================================================================== inline static void RecursiveLeafFlow(const int leafnum, const threaddata_t* const thread, const pstack_t* const prevstack) { pstack_t stack; leaf_t* leaf; leaf = &g_leafs[leafnum]; #ifdef USE_CHECK_STACK CheckStack(leaf, thread); #endif { const unsigned offset = leafnum >> 3; const unsigned bit = (1 << (leafnum & 7)); // mark the leaf as visible if (!(thread->leafvis[offset] & bit)) { thread->leafvis[offset] |= bit; thread->base->numcansee++; } } #ifdef USE_CHECK_STACK prevstack->next = &stack; stack.next = NULL; #endif stack.head = prevstack->head; stack.leaf = leaf; stack.portal = NULL; #ifdef RVIS_LEVEL_2 stack.clipPlaneCount = -1; stack.clipPlane = NULL; #endif // check all portals for flowing into other leafs unsigned i; portal_t** plist = leaf->portals; for (i = 0; i < leaf->numportals; i++, plist++) { portal_t* p = *plist; #if ZHLT_ZONES portal_t * head_p = stack.head->portal; if (g_Zones->check(head_p->zone, p->zone)) { continue; } #endif { const unsigned offset = p->leaf >> 3; const unsigned bit = 1 << (p->leaf & 7); if (!(stack.head->mightsee[offset] & bit)) { continue; // can't possibly see it } if (!(prevstack->mightsee[offset] & bit)) { continue; // can't possibly see it } } // if the portal can't see anything we haven't allready seen, skip it { long* test; if (p->status == stat_done) { test = (long*)p->visbits; } else { test = (long*)p->mightsee; } { const int bitlongs = g_bitlongs; { long* prevmight = (long*)prevstack->mightsee; long* might = (long*)stack.mightsee; unsigned j; for (j = 0; j < bitlongs; j++, test++, might++, prevmight++) { (*might) = (*prevmight) & (*test); } } { long* might = (long*)stack.mightsee; long* vis = (long*)thread->leafvis; unsigned j; for (j = 0; j < bitlongs; j++, might++, vis++) { if ((*might) & ~(*vis)) { break; } } if (j == g_bitlongs) { // can't see anything new continue; } } } } // get plane of portal, point normal into the neighbor leaf stack.portalplane = &p->plane; plane_t backplane; VectorSubtract(vec3_origin, p->plane.normal, backplane.normal); backplane.dist = -p->plane.dist; if (VectorCompare(prevstack->portalplane->normal, backplane.normal)) { continue; // can't go out a coplanar face } stack.portal = p; #ifdef USE_CHECK_STACK stack.next = NULL; #endif stack.freewindings[0] = 1; stack.freewindings[1] = 1; stack.freewindings[2] = 1; stack.pass = ChopWinding(p->winding, &stack, thread->pstack_head.portalplane); if (!stack.pass) { continue; } stack.source = ChopWinding(prevstack->source, &stack, &backplane); if (!stack.source) { continue; } if (!prevstack->pass) { // the second leaf can only be blocked if coplanar RecursiveLeafFlow(p->leaf, thread, &stack); continue; } stack.pass = ChopWinding(stack.pass, &stack, prevstack->portalplane); if (!stack.pass) { continue; } #ifdef RVIS_LEVEL_2 if (stack.clipPlaneCount == -1) { stack.clipPlaneCount = 0; stack.clipPlane = (plane_t*)alloca(sizeof(plane_t) * prevstack->source->numpoints * prevstack->pass->numpoints); ClipToSeperators(prevstack->source, prevstack->pass, NULL, false, &stack); ClipToSeperators(prevstack->pass, prevstack->source, NULL, true, &stack); } if (stack.clipPlaneCount > 0) { unsigned j; for (j = 0; j < stack.clipPlaneCount && stack.pass != NULL; j++) { stack.pass = ChopWinding(stack.pass, &stack, &(stack.clipPlane[j])); } if (stack.pass == NULL) continue; } #else stack.pass = ClipToSeperators(stack.source, prevstack->pass, stack.pass, false, &stack); if (!stack.pass) { continue; } stack.pass = ClipToSeperators(prevstack->pass, stack.source, stack.pass, true, &stack); if (!stack.pass) { continue; } #endif if (g_fullvis) { stack.source = ClipToSeperators(stack.pass, prevstack->pass, stack.source, false, &stack); if (!stack.source) { continue; } stack.source = ClipToSeperators(prevstack->pass, stack.pass, stack.source, true, &stack); if (!stack.source) { continue; } } // flow through it for real RecursiveLeafFlow(p->leaf, thread, &stack); } #ifdef RVIS_LEVEL_2 #if 0 if (stack.clipPlane != NULL) { free(stack.clipPlane); } #endif #endif }
uintptr_t WINAPI MemoryManager::CollectMemory(void* arg) { CollectionInfo* info = (CollectionInfo*)arg; #ifndef _GC_SERIAL EnterCriticalSection(&allocated_cs); #endif std::sort(allocated_memory.begin(), allocated_memory.end()); #ifndef _GC_SERIAL LeaveCriticalSection(&allocated_cs); #endif #ifdef _DEBUG long start = allocation_size; wcout << dec << endl << L"=========================================" << endl; wcout << L"Starting Garbage Collection; thread=" << GetCurrentThread() << endl; wcout << L"=========================================" << endl; wcout << L"## Marking memory ##" << endl; #endif #ifndef GC_SERIAL const int num_threads = 4; HANDLE thread_ids[num_threads]; thread_ids[0] = (HANDLE)_beginthreadex(NULL, 0, CheckStatic, info, 0, NULL); if(!thread_ids[0]) { wcerr << L"Unable to create garbage collection thread!" << endl; exit(-1); } thread_ids[1] = (HANDLE)_beginthreadex(NULL, 0, CheckStack, info, 0, NULL); if(!thread_ids[1]) { wcerr << L"Unable to create garbage collection thread!" << endl; exit(-1); } thread_ids[2] = (HANDLE)_beginthreadex(NULL, 0, CheckPdaRoots, NULL, 0, NULL); if(!thread_ids[2]) { wcerr << L"Unable to create garbage collection thread!" << endl; exit(-1); } thread_ids[3] = (HANDLE)_beginthreadex(NULL, 0, CheckJitRoots, NULL, 0, NULL); if(!thread_ids[3]) { wcerr << L"Unable to create garbage collection thread!" << endl; exit(-1); } // join all of the mark threads if(WaitForMultipleObjects(num_threads, thread_ids, TRUE, INFINITE) != WAIT_OBJECT_0) { wcerr << L"Unable to join garbage collection threads!" << endl; exit(-1); } for(int i=0; i < num_threads; i++) { CloseHandle(thread_ids[i]); } #else CheckStatic(NULL); CheckStack(info); CheckPdaRoots(NULL); CheckJitRoots(NULL); #endif // sweep memory #ifdef _DEBUG wcout << L"## Sweeping memory ##" << endl; #endif // sort and search #ifndef GC_SERIAL EnterCriticalSection(&allocated_cs); EnterCriticalSection(&marked_cs); #endif #ifdef _DEBUG wcout << L"-----------------------------------------" << endl; wcout << L"Marked " << marked_memory.size() << L" items." << endl; wcout << L"-----------------------------------------" << endl; #endif std::sort(marked_memory.begin(), marked_memory.end()); #ifndef GC_SERIAL #endif vector<long*> live_memory; live_memory.reserve(allocated_memory.size()); for(size_t i = 0; i < allocated_memory.size(); ++i) { long* mem = allocated_memory[i]; // check dynamic memory bool found = false; if(std::binary_search(marked_memory.begin(), marked_memory.end(), mem)) { long* tmp = mem; tmp[MARKED_FLAG] = 0L; found = true; } // live if(found) { live_memory.push_back(mem); } // will be collected else { // object or array long mem_size; if(mem[TYPE] == NIL_TYPE) { StackClass* cls = (StackClass*)mem[SIZE_OR_CLS]; #ifdef _DEBUG assert(cls); #endif if(cls) { mem_size = cls->GetInstanceMemorySize(); } else { mem_size = mem[SIZE_OR_CLS]; } } else { mem_size = mem[SIZE_OR_CLS]; } // account for deallocated memory allocation_size -= mem_size; // cache or free memory long* tmp = mem - EXTRA_BUF_SIZE; switch(mem[CACHE_SIZE]) { case 512: if(cache_pool_512.size() < POOL_SIZE + 1) { memset(tmp, 0, 512); cache_pool_512.push((char*)tmp); #ifdef _DEBUG wcout << L"# caching memory: addr=" << mem << L"(" << (long)mem << L"), size=" << mem_size << L" byte(s) #" << endl; #endif } break; case 256: if(cache_pool_256.size() < POOL_SIZE + 1) { memset(tmp, 0, 256); cache_pool_256.push((char*)tmp); #ifdef _DEBUG wcout << L"# caching memory: addr=" << mem << L"(" << (long)mem << L"), size=" << mem_size << L" byte(s) #" << endl; #endif } break; case 64: if(cache_pool_64.size() < POOL_SIZE + 1) { memset(tmp, 0, 64); cache_pool_64.push((char*)tmp); #ifdef _DEBUG wcout << L"# caching memory: addr=" << mem << L"(" << (long)mem << L"), size=" << mem_size << L" byte(s) #" << endl; #endif } break; case 32: if(cache_pool_32.size() < POOL_SIZE + 1) { memset(tmp, 0, 32); cache_pool_32.push((char*)tmp); #ifdef _DEBUG wcout << L"# caching memory: addr=" << mem << L"(" << (long)mem << L"), size=" << mem_size << L" byte(s) #" << endl; #endif } break; case 16: if(cache_pool_16.size() < POOL_SIZE + 1) { memset(tmp, 0, 16); cache_pool_16.push((char*)tmp); #ifdef _DEBUG wcout << L"# caching memory: addr=" << mem << L"(" << (long)mem << L"), size=" << mem_size << L" byte(s) #" << endl; #endif } break; default: free(tmp); tmp = NULL; #ifdef _DEBUG wcout << L"# freeing memory: addr=" << mem << L"(" << (long)mem << L"), size=" << mem_size << L" byte(s) #" << endl; #endif break; } } } marked_memory.clear(); #ifndef GC_SERIAL LeaveCriticalSection(&marked_cs); #endif // did not collect memory; ajust constraints if(live_memory.size() == allocated_memory.size()) { if(uncollected_count < UNCOLLECTED_COUNT) { uncollected_count++; } else { mem_max_size <<= 2; uncollected_count = 0; } } // collected memory; ajust constraints else if(mem_max_size != MEM_MAX) { if(collected_count < COLLECTED_COUNT) { collected_count++; } else { mem_max_size >>= 1; collected_count = 0; } } // copy live memory to allocated memory allocated_memory = live_memory; #ifndef GC_SERIAL LeaveCriticalSection(&allocated_cs); #endif #ifdef _DEBUG wcout << L"===============================================================" << endl; wcout << L"Finished Collection: collected=" << (start - allocation_size) << L" of " << start << L" byte(s) - " << showpoint << setprecision(3) << (((double)(start - allocation_size) / (double)start) * 100.0) << L"%" << endl; wcout << L"===============================================================" << endl; #endif return 0; }