static void test2(RTTEST hTest) { struct TestMap2 *p2 = (struct TestMap2 *)RTTestGuardedAllocTail(hTest, sizeof(TestMap2)); p2->idNil = NIL_TEST2_ID; p2->idLast = TEST2_ID_LAST; /* Some simple tests first. */ RT_ZERO(p2->bmChunkId); RTTEST_CHECK(hTest, ASMBitFirstSet(&p2->bmChunkId[0], TEST2_ID_LAST + 1) == -1); for (uint32_t iBit = 0; iBit <= TEST2_ID_LAST; iBit++) RTTEST_CHECK(hTest, !ASMBitTest(&p2->bmChunkId[0], iBit)); memset(&p2->bmChunkId[0], 0xff, sizeof(p2->bmChunkId)); RTTEST_CHECK(hTest, ASMBitFirstClear(&p2->bmChunkId[0], TEST2_ID_LAST + 1) == -1); for (uint32_t iBit = 0; iBit <= TEST2_ID_LAST; iBit++) RTTEST_CHECK(hTest, ASMBitTest(&p2->bmChunkId[0], iBit)); /* The real test. */ p2->idChunkPrev = 0; RT_ZERO(p2->bmChunkId); ASMBitSet(p2->bmChunkId, NIL_TEST2_ID); uint32_t cLeft = TEST2_ID_LAST; while (cLeft-- > 0) test2AllocId(p2); RTTEST_CHECK(hTest, ASMBitFirstClear(&p2->bmChunkId[0], TEST2_ID_LAST + 1) == -1); }
static PCR_DISPLAY crServerDisplayGet(uint32_t idScreen) { if (idScreen >= CR_MAX_GUEST_MONITORS) { crWarning("invalid idScreen %d", idScreen); return NULL; } if (ASMBitTest(cr_server.DisplaysInitMap, idScreen)) return &cr_server.aDispplays[idScreen]; /* the display (screen id == 0) can be initialized while doing crServerCheckInitDisplayBlitter, * so re-check the bit map */ if (ASMBitTest(cr_server.DisplaysInitMap, idScreen)) return &cr_server.aDispplays[idScreen]; int rc = CrDpInit(&cr_server.aDispplays[idScreen]); if (RT_SUCCESS(rc)) { CrDpResize(&cr_server.aDispplays[idScreen], cr_server.screen[idScreen].w, cr_server.screen[idScreen].h, cr_server.screen[idScreen].w, cr_server.screen[idScreen].h); ASMBitSet(cr_server.DisplaysInitMap, idScreen); return &cr_server.aDispplays[idScreen]; } else { crWarning("CrDpInit failed for screen %d", idScreen); } return NULL; }
/** * Checks if a page range is free in the specified block. * * @returns @c true if the range is free, @c false if not. * @param pBlock The block. * @param iFirst The first page to check. * @param cPages The number of pages to check. */ DECLINLINE(bool) rtHeapPageIsPageRangeFree(PRTHEAPPAGEBLOCK pBlock, uint32_t iFirst, uint32_t cPages) { uint32_t i = iFirst + cPages; while (i-- > iFirst) { if (ASMBitTest(&pBlock->bmAlloc[0], i)) return false; Assert(!ASMBitTest(&pBlock->bmFirst[0], i)); } return true; }
/** * Flush pending queues. * This is a forced action callback. * * @param pVM Pointer to the VM. * @thread Emulation thread only. */ VMMR3_INT_DECL(void) PDMR3QueueFlushAll(PVM pVM) { VM_ASSERT_EMT(pVM); LogFlow(("PDMR3QueuesFlush:\n")); /* * Only let one EMT flushing queues at any one time to preserve the order * and to avoid wasting time. The FF is always cleared here, because it's * only used to get someones attention. Queue inserts occurring during the * flush are caught using the pending bit. * * Note! We must check the force action and pending flags after clearing * the active bit! */ VM_FF_CLEAR(pVM, VM_FF_PDM_QUEUES); while (!ASMAtomicBitTestAndSet(&pVM->pdm.s.fQueueFlushing, PDM_QUEUE_FLUSH_FLAG_ACTIVE_BIT)) { ASMAtomicBitClear(&pVM->pdm.s.fQueueFlushing, PDM_QUEUE_FLUSH_FLAG_PENDING_BIT); for (PPDMQUEUE pCur = pVM->pUVM->pdm.s.pQueuesForced; pCur; pCur = pCur->pNext) if ( pCur->pPendingR3 || pCur->pPendingR0 || pCur->pPendingRC) pdmR3QueueFlush(pCur); ASMAtomicBitClear(&pVM->pdm.s.fQueueFlushing, PDM_QUEUE_FLUSH_FLAG_ACTIVE_BIT); /* We're done if there were no inserts while we were busy. */ if ( !ASMBitTest(&pVM->pdm.s.fQueueFlushing, PDM_QUEUE_FLUSH_FLAG_PENDING_BIT) && !VM_FF_ISPENDING(pVM, VM_FF_PDM_QUEUES)) break; VM_FF_CLEAR(pVM, VM_FF_PDM_QUEUES); } }
RTDECL(bool) ASMBitTestAndClear(volatile void *pvBitmap, int32_t iBit) { if (!ASMBitTest(pvBitmap, iBit)) return false; ASMBitClear(pvBitmap, iBit); return true; }
RTDECL(bool) ASMBitTestAndSet(volatile void *pvBitmap, int32_t iBit) { if (ASMBitTest(pvBitmap, iBit)) return true; ASMBitSet(pvBitmap, iBit); return false; }
/** * Checks if the specified generic event is enabled or not. * * @returns true / false. * @param pVM The cross context VM structure. * @param enmEvent The generic event being raised. * @param uEventArg The argument of that event. */ DECLINLINE(bool) dbgfEventIsGenericWithArgEnabled(PVM pVM, DBGFEVENTTYPE enmEvent, uint64_t uEventArg) { if (DBGF_IS_EVENT_ENABLED(pVM, enmEvent)) { switch (enmEvent) { case DBGFEVENT_INTERRUPT_HARDWARE: AssertReturn(uEventArg < 256, false); return ASMBitTest(pVM->dbgf.s.bmHardIntBreakpoints, (uint32_t)uEventArg); case DBGFEVENT_INTERRUPT_SOFTWARE: AssertReturn(uEventArg < 256, false); return ASMBitTest(pVM->dbgf.s.bmSoftIntBreakpoints, (uint32_t)uEventArg); default: return true; } } return false; }
PVBOXWDDM_VIDEOMODES_INFO VBoxWddmUpdateVideoModesInfoByMask(PVBOXMP_DEVEXT pExt, uint8_t *pScreenIdMask) { for (int i = 0; i < VBoxCommonFromDeviceExt(pExt)->cDisplays; ++i) { if (ASMBitTest(pScreenIdMask, i)) VBoxWddmInvalidateVideoModesInfo(pExt, i); } /* ensure we have all the rest populated */ VBoxWddmGetAllVideoModesInfos(pExt); return g_aVBoxVideoModeInfos; }
/** * Destroys the per thread data. * * @param pThread The thread to destroy. */ static void rtThreadDestroy(PRTTHREADINT pThread) { RTSEMEVENTMULTI hEvt1, hEvt2; /* * Remove it from the tree and mark it as dead. * * Threads that has seen rtThreadTerminate and should already have been * removed from the tree. There is probably no thread that should * require removing here. However, be careful making sure that cRefs * isn't 0 if we do or we'll blow up because the strict locking code * will be calling us back. */ if (ASMBitTest(&pThread->fIntFlags, RTTHREADINT_FLAG_IN_TREE_BIT)) { ASMAtomicIncU32(&pThread->cRefs); rtThreadRemove(pThread); ASMAtomicDecU32(&pThread->cRefs); } /* * Invalidate the thread structure. */ #ifdef IN_RING3 rtLockValidatorSerializeDestructEnter(); rtLockValidatorDeletePerThread(&pThread->LockValidator); #endif #ifdef RT_WITH_ICONV_CACHE rtStrIconvCacheDestroy(pThread); #endif ASMAtomicXchgU32(&pThread->u32Magic, RTTHREADINT_MAGIC_DEAD); ASMAtomicWritePtr(&pThread->Core.Key, (void *)NIL_RTTHREAD); pThread->enmType = RTTHREADTYPE_INVALID; hEvt1 = pThread->EventUser; pThread->EventUser = NIL_RTSEMEVENTMULTI; hEvt2 = pThread->EventTerminated; pThread->EventTerminated = NIL_RTSEMEVENTMULTI; #ifdef IN_RING3 rtLockValidatorSerializeDestructLeave(); #endif /* * Destroy semaphore resources and free the bugger. */ RTSemEventMultiDestroy(hEvt1); if (hEvt2 != NIL_RTSEMEVENTMULTI) RTSemEventMultiDestroy(hEvt2); rtThreadNativeDestroy(pThread); RTMemFree(pThread); }
RTR3DECL(int) RTTlsSet(RTTLS iTls, void *pvValue) { if (RT_UNLIKELY( iTls < 0 || iTls >= RTTHREAD_TLS_ENTRIES || !ASMBitTest(&g_au32AllocatedBitmap[0], iTls))) return VERR_INVALID_PARAMETER; PRTTHREADINT pThread = rtThreadGet(RTThreadSelf()); AssertReturn(pThread, VERR_NOT_SUPPORTED); pThread->apvTlsEntries[iTls] = pvValue; rtThreadRelease(pThread); return VINF_SUCCESS; }
RTR3DECL(int) RTTlsFree(RTTLS iTls) { if (iTls == NIL_RTTLS) return VINF_SUCCESS; if ( iTls < 0 || iTls >= RTTHREAD_TLS_ENTRIES || !ASMBitTest(&g_au32AllocatedBitmap[0], iTls)) return VERR_INVALID_PARAMETER; ASMAtomicWriteNullPtr(&g_apfnDestructors[iTls]); rtThreadClearTlsEntry(iTls); ASMAtomicBitClear(&g_au32AllocatedBitmap[0], iTls); return VINF_SUCCESS; }
/** * Check if this page was previously scanned by CSAM * * @returns true -> scanned, false -> not scanned * @param pVM Pointer to the VM. * @param pPage GC page address */ VMM_INT_DECL(bool) CSAMIsPageScanned(PVM pVM, RTRCPTR pPage) { int pgdir, bit; uintptr_t page; page = (uintptr_t)pPage; pgdir = page >> X86_PAGE_4M_SHIFT; bit = (page & X86_PAGE_4M_OFFSET_MASK) >> X86_PAGE_4K_SHIFT; Assert(pgdir < CSAM_PGDIRBMP_CHUNKS); Assert(bit < PAGE_SIZE); return pVM->csam.s.CTXSUFF(pPDBitmap)[pgdir] && ASMBitTest((void *)pVM->csam.s.CTXSUFF(pPDBitmap)[pgdir], bit); }
/** * \#PF Virtual Handler callback for Guest write access to the Guest's own current IDT. * * @returns VBox status code (appropriate for trap handling and GC return). * @param pVM Pointer to the VM. * @param uErrorCode CPU Error code. * @param pRegFrame Trap register frame. * @param pvFault The fault address (cr2). * @param pvRange The base address of the handled virtual range. * @param offRange The offset of the access into this range. * (If it's a EIP range this is the EIP, if not it's pvFault.) */ VMMRCDECL(int) trpmRCGuestIDTWriteHandler(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, RTGCPTR pvRange, uintptr_t offRange) { PVMCPU pVCpu = VMMGetCpu0(pVM); uint16_t cbIDT; RTGCPTR GCPtrIDT = (RTGCPTR)CPUMGetGuestIDTR(pVCpu, &cbIDT); #ifdef VBOX_STRICT RTGCPTR GCPtrIDTEnd = (RTGCPTR)((RTGCUINTPTR)GCPtrIDT + cbIDT + 1); #endif uint32_t iGate = ((RTGCUINTPTR)pvFault - (RTGCUINTPTR)GCPtrIDT)/sizeof(VBOXIDTE); AssertMsg(offRange < (uint32_t)cbIDT+1, ("pvFault=%RGv GCPtrIDT=%RGv-%RGv pvRange=%RGv\n", pvFault, GCPtrIDT, GCPtrIDTEnd, pvRange)); Assert((RTGCPTR)(RTRCUINTPTR)pvRange == GCPtrIDT); NOREF(uErrorCode); #if 0 /* Note! this causes problems in Windows XP as instructions following the update can be dangerous (str eax has been seen) */ /* Note! not going back to ring 3 could make the code scanner miss them. */ /* Check if we can handle the write here. */ if ( iGate != 3 /* Gate 3 is handled differently; could do it here as well, but let ring 3 handle this case for now. */ && !ASMBitTest(&pVM->trpm.s.au32IdtPatched[0], iGate)) /* Passthru gates need special attention too. */ { uint32_t cb; int rc = EMInterpretInstructionEx(pVM, pVCpu, pRegFrame, pvFault, &cb); if (RT_SUCCESS(rc) && cb) { uint32_t iGate1 = (offRange + cb - 1)/sizeof(VBOXIDTE); Log(("trpmRCGuestIDTWriteHandler: write to gate %x (%x) offset %x cb=%d\n", iGate, iGate1, offRange, cb)); trpmClearGuestTrapHandler(pVM, iGate); if (iGate != iGate1) trpmClearGuestTrapHandler(pVM, iGate1); STAM_COUNTER_INC(&pVM->trpm.s.StatRCWriteGuestIDTHandled); return VINF_SUCCESS; } } #else NOREF(iGate); #endif Log(("trpmRCGuestIDTWriteHandler: eip=%RGv write to gate %x offset %x\n", pRegFrame->eip, iGate, offRange)); /** @todo Check which IDT entry and keep the update cost low in TRPMR3SyncIDT() and CSAMCheckGates(). */ VMCPU_FF_SET(pVCpu, VMCPU_FF_TRPM_SYNC_IDT); STAM_COUNTER_INC(&pVM->trpm.s.StatRCWriteGuestIDTFault); return VINF_EM_RAW_EMULATE_INSTR_IDT_FAULT; }
/** * Checks if the argument needs quoting or not. * * @returns true if it needs, false if it don't. * @param pszArg The argument. * @param fFlags Quoting style. * @param pcch Where to store the argument length when quoting * is not required. (optimization) */ DECLINLINE(bool) rtGetOpArgvRequiresQuoting(const char *pszArg, uint32_t fFlags, size_t *pcch) { char const *psz = pszArg; unsigned char ch; while ((ch = (unsigned char)*psz)) { if ( ch < 128 && ASMBitTest(&g_abmQuoteChars[fFlags & RTGETOPTARGV_CNV_QUOTE_MASK], ch)) return true; psz++; } *pcch = psz - pszArg; return false; }
/** * Frees a page from the page pool. * * @param pPool Pointer to the page pool. * @param pv Pointer to the page to free. * I.e. pointer returned by mmR3PagePoolAlloc(). * @thread The Emulation Thread. */ DECLINLINE(void) mmR3PagePoolFree(PMMPAGEPOOL pPool, void *pv) { VM_ASSERT_EMT(pPool->pVM); STAM_COUNTER_INC(&pPool->cFreeCalls); /* * Lookup the virtual address. */ PMMPPLOOKUPHCPTR pLookup = (PMMPPLOOKUPHCPTR)RTAvlPVGetBestFit(&pPool->pLookupVirt, pv, false); if ( !pLookup || (uint8_t *)pv >= (uint8_t *)pLookup->pSubPool->pvPages + (pLookup->pSubPool->cPages << PAGE_SHIFT) ) { STAM_COUNTER_INC(&pPool->cErrors); AssertMsgFailed(("invalid pointer %p\n", pv)); return; } /* * Free the page. */ PMMPAGESUBPOOL pSubPool = pLookup->pSubPool; /* clear bitmap bit */ const unsigned iPage = ((uint8_t *)pv - (uint8_t *)pSubPool->pvPages) >> PAGE_SHIFT; #ifdef USE_INLINE_ASM_BIT_OPS Assert(ASMBitTest(pSubPool->auBitmap, iPage)); ASMBitClear(pSubPool->auBitmap, iPage); #else unsigned iBit = iPage % (sizeof(pSubPool->auBitmap[0]) * 8); unsigned iIndex = iPage / (sizeof(pSubPool->auBitmap[0]) * 8); pSubPool->auBitmap[iIndex] &= ~(1 << iBit); #endif /* update stats. */ pSubPool->cPagesFree++; #ifdef VBOX_WITH_STATISTICS pPool->cFreePages++; #endif if (pSubPool->cPagesFree == 1) { pSubPool->pNextFree = pPool->pHeadFree; pPool->pHeadFree = pSubPool; } }
int main() { /* * Init the runtime and stuff. */ RTTEST hTest; int rc = RTTestInitAndCreate("tstRTBitOperations", &hTest); if (rc) return rc; RTTestBanner(hTest); int i; int j; int k; /* * Tests */ struct TestMap { uint32_t au32[4]; }; #if 0 struct TestMap sTest; struct TestMap *p = &sTest; #else struct TestMap *p = (struct TestMap *)RTTestGuardedAllocTail(hTest, sizeof(*p)); #endif #define DUMP() RTTestPrintf(hTest, RTTESTLVL_INFO, "au32={%08x,%08x,%08x,%08x}", p->au32[0], p->au32[1], p->au32[2], p->au32[3]) #define CHECK(expr) do { if (!(expr)) { RTTestFailed(hTest, "line %d: %s", __LINE__, #expr); DUMP(); } CHECK_GUARD(s); } while (0) #define CHECK_BIT(expr, b1) do { if (!(expr)) { RTTestFailed(hTest, "line %d, b1=%d: %s", __LINE__, b1, #expr); } CHECK_GUARD(s); } while (0) #define CHECK_BIT2(expr, b1, b2) do { if (!(expr)) { RTTestFailed(hTest, "line %d, b1=%d b2=%d: %s", __LINE__, b1, b2, #expr); } CHECK_GUARD(s); } while (0) #define CHECK_BIT3(expr, b1, b2, b3) do { if (!(expr)) { RTTestFailed(hTest, "line %d, b1=%d b2=%d b3=%d: %s", __LINE__, b1, b2, b3, #expr); } CHECK_GUARD(s); } while (0) #define GUARD_MAP(p) do { } while (0) #define CHECK_GUARD(p) do { } while (0) #define MAP_CLEAR(p) do { RT_ZERO(*(p)); GUARD_MAP(p); } while (0) #define MAP_SET(p) do { memset(p, 0xff, sizeof(*(p))); GUARD_MAP(p); } while (0) /* self check. */ MAP_CLEAR(p); CHECK_GUARD(p); /* bit set */ MAP_CLEAR(p); ASMBitSet(&p->au32[0], 0); ASMBitSet(&p->au32[0], 31); ASMBitSet(&p->au32[0], 65); CHECK(p->au32[0] == 0x80000001U); CHECK(p->au32[2] == 0x00000002U); CHECK(ASMBitTestAndSet(&p->au32[0], 0) && p->au32[0] == 0x80000001U); CHECK(!ASMBitTestAndSet(&p->au32[0], 16) && p->au32[0] == 0x80010001U); CHECK(ASMBitTestAndSet(&p->au32[0], 16) && p->au32[0] == 0x80010001U); CHECK(!ASMBitTestAndSet(&p->au32[0], 80) && p->au32[2] == 0x00010002U); MAP_CLEAR(p); ASMAtomicBitSet(&p->au32[0], 0); ASMAtomicBitSet(&p->au32[0], 30); ASMAtomicBitSet(&p->au32[0], 64); CHECK(p->au32[0] == 0x40000001U); CHECK(p->au32[2] == 0x00000001U); CHECK(ASMAtomicBitTestAndSet(&p->au32[0], 0) && p->au32[0] == 0x40000001U); CHECK(!ASMAtomicBitTestAndSet(&p->au32[0], 16) && p->au32[0] == 0x40010001U); CHECK(ASMAtomicBitTestAndSet(&p->au32[0], 16) && p->au32[0] == 0x40010001U); CHECK(!ASMAtomicBitTestAndSet(&p->au32[0], 80) && p->au32[2] == 0x00010001U); /* bit clear */ MAP_SET(p); ASMBitClear(&p->au32[0], 0); ASMBitClear(&p->au32[0], 31); ASMBitClear(&p->au32[0], 65); CHECK(p->au32[0] == ~0x80000001U); CHECK(p->au32[2] == ~0x00000002U); CHECK(!ASMBitTestAndClear(&p->au32[0], 0) && p->au32[0] == ~0x80000001U); CHECK(ASMBitTestAndClear(&p->au32[0], 16) && p->au32[0] == ~0x80010001U); CHECK(!ASMBitTestAndClear(&p->au32[0], 16) && p->au32[0] == ~0x80010001U); CHECK(ASMBitTestAndClear(&p->au32[0], 80) && p->au32[2] == ~0x00010002U); MAP_SET(p); ASMAtomicBitClear(&p->au32[0], 0); ASMAtomicBitClear(&p->au32[0], 30); ASMAtomicBitClear(&p->au32[0], 64); CHECK(p->au32[0] == ~0x40000001U); CHECK(p->au32[2] == ~0x00000001U); CHECK(!ASMAtomicBitTestAndClear(&p->au32[0], 0) && p->au32[0] == ~0x40000001U); CHECK(ASMAtomicBitTestAndClear(&p->au32[0], 16) && p->au32[0] == ~0x40010001U); CHECK(!ASMAtomicBitTestAndClear(&p->au32[0], 16) && p->au32[0] == ~0x40010001U); CHECK(ASMAtomicBitTestAndClear(&p->au32[0], 80) && p->au32[2] == ~0x00010001U); /* toggle */ MAP_SET(p); ASMBitToggle(&p->au32[0], 0); ASMBitToggle(&p->au32[0], 31); ASMBitToggle(&p->au32[0], 65); ASMBitToggle(&p->au32[0], 47); ASMBitToggle(&p->au32[0], 47); CHECK(p->au32[0] == ~0x80000001U); CHECK(p->au32[2] == ~0x00000002U); CHECK(!ASMBitTestAndToggle(&p->au32[0], 0) && p->au32[0] == ~0x80000000U); CHECK(ASMBitTestAndToggle(&p->au32[0], 0) && p->au32[0] == ~0x80000001U); CHECK(ASMBitTestAndToggle(&p->au32[0], 16) && p->au32[0] == ~0x80010001U); CHECK(!ASMBitTestAndToggle(&p->au32[0], 16) && p->au32[0] == ~0x80000001U); CHECK(ASMBitTestAndToggle(&p->au32[0], 80) && p->au32[2] == ~0x00010002U); MAP_SET(p); ASMAtomicBitToggle(&p->au32[0], 0); ASMAtomicBitToggle(&p->au32[0], 30); ASMAtomicBitToggle(&p->au32[0], 64); ASMAtomicBitToggle(&p->au32[0], 47); ASMAtomicBitToggle(&p->au32[0], 47); CHECK(p->au32[0] == ~0x40000001U); CHECK(p->au32[2] == ~0x00000001U); CHECK(!ASMAtomicBitTestAndToggle(&p->au32[0], 0) && p->au32[0] == ~0x40000000U); CHECK(ASMAtomicBitTestAndToggle(&p->au32[0], 0) && p->au32[0] == ~0x40000001U); CHECK(ASMAtomicBitTestAndToggle(&p->au32[0], 16) && p->au32[0] == ~0x40010001U); CHECK(!ASMAtomicBitTestAndToggle(&p->au32[0], 16) && p->au32[0] == ~0x40000001U); CHECK(ASMAtomicBitTestAndToggle(&p->au32[0], 80) && p->au32[2] == ~0x00010001U); /* test bit. */ for (i = 0; i < 128; i++) { MAP_SET(p); CHECK_BIT(ASMBitTest(&p->au32[0], i), i); ASMBitToggle(&p->au32[0], i); CHECK_BIT(!ASMBitTest(&p->au32[0], i), i); CHECK_BIT(!ASMBitTestAndToggle(&p->au32[0], i), i); CHECK_BIT(ASMBitTest(&p->au32[0], i), i); CHECK_BIT(ASMBitTestAndToggle(&p->au32[0], i), i); CHECK_BIT(!ASMBitTest(&p->au32[0], i), i); MAP_SET(p); CHECK_BIT(ASMBitTest(&p->au32[0], i), i); ASMAtomicBitToggle(&p->au32[0], i); CHECK_BIT(!ASMBitTest(&p->au32[0], i), i); CHECK_BIT(!ASMAtomicBitTestAndToggle(&p->au32[0], i), i); CHECK_BIT(ASMBitTest(&p->au32[0], i), i); CHECK_BIT(ASMAtomicBitTestAndToggle(&p->au32[0], i), i); CHECK_BIT(!ASMBitTest(&p->au32[0], i), i); } /* bit searching */ MAP_SET(p); CHECK(ASMBitFirstClear(&p->au32[0], sizeof(p->au32) * 8) == -1); CHECK(ASMBitFirstSet(&p->au32[0], sizeof(p->au32) * 8) == 0); ASMBitClear(&p->au32[0], 1); CHECK(ASMBitFirstClear(&p->au32[0], sizeof(p->au32) * 8) == 1); CHECK(ASMBitFirstSet(&p->au32[0], sizeof(p->au32) * 8) == 0); MAP_SET(p); ASMBitClear(&p->au32[0], 95); CHECK(ASMBitFirstClear(&p->au32[0], sizeof(p->au32) * 8) == 95); CHECK(ASMBitFirstSet(&p->au32[0], sizeof(p->au32) * 8) == 0); MAP_SET(p); ASMBitClear(&p->au32[0], 127); CHECK(ASMBitFirstClear(&p->au32[0], sizeof(p->au32) * 8) == 127); CHECK(ASMBitFirstSet(&p->au32[0], sizeof(p->au32) * 8) == 0); CHECK(ASMBitNextSet(&p->au32[0], sizeof(p->au32) * 8, 0) == 1); CHECK(ASMBitNextSet(&p->au32[0], sizeof(p->au32) * 8, 1) == 2); CHECK(ASMBitNextSet(&p->au32[0], sizeof(p->au32) * 8, 2) == 3); MAP_SET(p); CHECK(ASMBitNextClear(&p->au32[0], sizeof(p->au32) * 8, 0) == -1); ASMBitClear(&p->au32[0], 32); CHECK(ASMBitNextClear(&p->au32[0], sizeof(p->au32) * 8, 32) == -1); ASMBitClear(&p->au32[0], 88); CHECK(ASMBitNextClear(&p->au32[0], sizeof(p->au32) * 8, 57) == 88); MAP_SET(p); ASMBitClear(&p->au32[0], 31); ASMBitClear(&p->au32[0], 57); ASMBitClear(&p->au32[0], 88); ASMBitClear(&p->au32[0], 101); ASMBitClear(&p->au32[0], 126); ASMBitClear(&p->au32[0], 127); CHECK(ASMBitFirstClear(&p->au32[0], sizeof(p->au32) * 8) == 31); CHECK(ASMBitNextClear(&p->au32[0], sizeof(p->au32) * 8, 31) == 57); CHECK(ASMBitNextClear(&p->au32[0], sizeof(p->au32) * 8, 57) == 88); CHECK(ASMBitNextClear(&p->au32[0], sizeof(p->au32) * 8, 88) == 101); CHECK(ASMBitNextClear(&p->au32[0], sizeof(p->au32) * 8, 101) == 126); CHECK(ASMBitNextClear(&p->au32[0], sizeof(p->au32) * 8, 126) == 127); CHECK(ASMBitNextClear(&p->au32[0], sizeof(p->au32) * 8, 127) == -1); CHECK(ASMBitNextSet(&p->au32[0], sizeof(p->au32) * 8, 29) == 30); CHECK(ASMBitNextSet(&p->au32[0], sizeof(p->au32) * 8, 30) == 32); MAP_CLEAR(p); for (i = 1; i < 128; i++) CHECK_BIT(ASMBitNextClear(&p->au32[0], sizeof(p->au32) * 8, i - 1) == i, i); for (i = 0; i < 128; i++) { MAP_SET(p); ASMBitClear(&p->au32[0], i); CHECK_BIT(ASMBitFirstClear(&p->au32[0], sizeof(p->au32) * 8) == i, i); for (j = 0; j < i; j++) CHECK_BIT(ASMBitNextClear(&p->au32[0], sizeof(p->au32) * 8, j) == i, i); for (j = i; j < 128; j++) CHECK_BIT(ASMBitNextClear(&p->au32[0], sizeof(p->au32) * 8, j) == -1, i); } /* clear range. */ MAP_SET(p); ASMBitClearRange(&p->au32, 0, 128); CHECK(!p->au32[0] && !p->au32[1] && !p->au32[2] && !p->au32[3]); for (i = 0; i < 128; i++) { for (j = i + 1; j <= 128; j++) { MAP_SET(p); ASMBitClearRange(&p->au32, i, j); for (k = 0; k < i; k++) CHECK_BIT3(ASMBitTest(&p->au32[0], k), i, j, k); for (k = i; k < j; k++) CHECK_BIT3(!ASMBitTest(&p->au32[0], k), i, j, k); for (k = j; k < 128; k++) CHECK_BIT3(ASMBitTest(&p->au32[0], k), i, j, k); } } /* set range. */ MAP_CLEAR(p); ASMBitSetRange(&p->au32[0], 0, 5); ASMBitSetRange(&p->au32[0], 6, 44); ASMBitSetRange(&p->au32[0], 64, 65); CHECK(p->au32[0] == UINT32_C(0xFFFFFFDF)); CHECK(p->au32[1] == UINT32_C(0x00000FFF)); CHECK(p->au32[2] == UINT32_C(0x00000001)); MAP_CLEAR(p); ASMBitSetRange(&p->au32[0], 0, 1); ASMBitSetRange(&p->au32[0], 62, 63); ASMBitSetRange(&p->au32[0], 63, 64); ASMBitSetRange(&p->au32[0], 127, 128); CHECK(p->au32[0] == UINT32_C(0x00000001) && p->au32[1] == UINT32_C(0xC0000000)); CHECK(p->au32[2] == UINT32_C(0x00000000) && p->au32[3] == UINT32_C(0x80000000)); MAP_CLEAR(p); ASMBitSetRange(&p->au32, 0, 128); CHECK(!~p->au32[0] && !~p->au32[1] && !~p->au32[2] && !~p->au32[3]); for (i = 0; i < 128; i++) { for (j = i + 1; j <= 128; j++) { MAP_CLEAR(p); ASMBitSetRange(&p->au32, i, j); for (k = 0; k < i; k++) CHECK_BIT3(!ASMBitTest(&p->au32[0], k), i, j, k); for (k = i; k < j; k++) CHECK_BIT3(ASMBitTest(&p->au32[0], k), i, j, k); for (k = j; k < 128; k++) CHECK_BIT3(!ASMBitTest(&p->au32[0], k), i, j, k); } } /* searching for set bits. */ MAP_CLEAR(p); CHECK(ASMBitFirstSet(&p->au32[0], sizeof(p->au32) * 8) == -1); ASMBitSet(&p->au32[0], 65); CHECK(ASMBitFirstSet(&p->au32[0], sizeof(p->au32) * 8) == 65); CHECK(ASMBitNextSet(&p->au32[0], sizeof(p->au32) * 8, 65) == -1); for (i = 0; i < 65; i++) CHECK(ASMBitNextSet(&p->au32[0], sizeof(p->au32) * 8, i) == 65); for (i = 65; i < 128; i++) CHECK(ASMBitNextSet(&p->au32[0], sizeof(p->au32) * 8, i) == -1); ASMBitSet(&p->au32[0], 17); CHECK(ASMBitFirstSet(&p->au32[0], sizeof(p->au32) * 8) == 17); CHECK(ASMBitNextSet(&p->au32[0], sizeof(p->au32) * 8, 17) == 65); for (i = 0; i < 16; i++) CHECK(ASMBitNextSet(&p->au32[0], sizeof(p->au32) * 8, i) == 17); for (i = 17; i < 65; i++) CHECK(ASMBitNextSet(&p->au32[0], sizeof(p->au32) * 8, i) == 65); MAP_SET(p); for (i = 1; i < 128; i++) CHECK_BIT(ASMBitNextSet(&p->au32[0], sizeof(p->au32) * 8, i - 1) == i, i); for (i = 0; i < 128; i++) { MAP_CLEAR(p); ASMBitSet(&p->au32[0], i); CHECK_BIT(ASMBitFirstSet(&p->au32[0], sizeof(p->au32) * 8) == i, i); for (j = 0; j < i; j++) CHECK_BIT(ASMBitNextSet(&p->au32[0], sizeof(p->au32) * 8, j) == i, i); for (j = i; j < 128; j++) CHECK_BIT(ASMBitNextSet(&p->au32[0], sizeof(p->au32) * 8, j) == -1, i); } CHECK(ASMBitLastSetU32(0) == 0); CHECK(ASMBitLastSetU32(1) == 1); CHECK(ASMBitLastSetU32(0x80000000) == 32); CHECK(ASMBitLastSetU32(0xffffffff) == 32); CHECK(ASMBitLastSetU32(RT_BIT(23) | RT_BIT(11)) == 24); for (i = 0; i < 32; i++) CHECK(ASMBitLastSetU32(1 << i) == (unsigned)i + 1); CHECK(ASMBitFirstSetU32(0) == 0); CHECK(ASMBitFirstSetU32(1) == 1); CHECK(ASMBitFirstSetU32(0x80000000) == 32); CHECK(ASMBitFirstSetU32(0xffffffff) == 1); CHECK(ASMBitFirstSetU32(RT_BIT(23) | RT_BIT(11)) == 12); for (i = 0; i < 32; i++) CHECK(ASMBitFirstSetU32(1 << i) == (unsigned)i + 1); /* * Special tests. */ test2(hTest); /* * Summary */ return RTTestSummaryAndDestroy(hTest); }
/** * Allocates a page from the page pool. * * @returns Pointer to allocated page(s). * @returns NULL on failure. * @param pPool Pointer to the page pool. * @thread The Emulation Thread. */ DECLINLINE(void *) mmR3PagePoolAlloc(PMMPAGEPOOL pPool) { VM_ASSERT_EMT(pPool->pVM); STAM_COUNTER_INC(&pPool->cAllocCalls); /* * Walk free list. */ if (pPool->pHeadFree) { PMMPAGESUBPOOL pSub = pPool->pHeadFree; /* decrement free count and unlink if no more free entries. */ if (!--pSub->cPagesFree) pPool->pHeadFree = pSub->pNextFree; #ifdef VBOX_WITH_STATISTICS pPool->cFreePages--; #endif /* find free spot in bitmap. */ #ifdef USE_INLINE_ASM_BIT_OPS const int iPage = ASMBitFirstClear(pSub->auBitmap, pSub->cPages); if (iPage >= 0) { Assert(!ASMBitTest(pSub->auBitmap, iPage)); ASMBitSet(pSub->auBitmap, iPage); return (uint8_t *)pSub->pvPages + PAGE_SIZE * iPage; } #else unsigned *pu = &pSub->auBitmap[0]; unsigned *puEnd = &pSub->auBitmap[pSub->cPages / (sizeof(pSub->auBitmap) * 8)]; while (pu < puEnd) { unsigned u; if ((u = *pu) != ~0U) { unsigned iBit = 0; unsigned uMask = 1; while (iBit < sizeof(pSub->auBitmap[0]) * 8) { if (!(u & uMask)) { *pu |= uMask; return (uint8_t *)pSub->pvPages + PAGE_SIZE * (iBit + ((uint8_t *)pu - (uint8_t *)&pSub->auBitmap[0]) * 8); } iBit++; uMask <<= 1; } STAM_COUNTER_INC(&pPool->cErrors); AssertMsgFailed(("how odd, expected to find a free bit in %#x, but didn't\n", u)); } /* next */ pu++; } #endif STAM_COUNTER_INC(&pPool->cErrors); #ifdef VBOX_WITH_STATISTICS pPool->cFreePages++; #endif AssertMsgFailed(("how strange, expected to find a free bit in %p, but didn't (%d pages supposed to be free!)\n", pSub, pSub->cPagesFree + 1)); } /* * Allocate new subpool. */ unsigned cPages = !pPool->fLow ? 128 : 32; PMMPAGESUBPOOL pSub; int rc = MMHyperAlloc(pPool->pVM, RT_OFFSETOF(MMPAGESUBPOOL, auBitmap[cPages / (sizeof(pSub->auBitmap[0]) * 8)]) + (sizeof(SUPPAGE) + sizeof(MMPPLOOKUPHCPHYS)) * cPages + sizeof(MMPPLOOKUPHCPTR), 0, MM_TAG_MM_PAGE, (void **)&pSub); if (RT_FAILURE(rc)) return NULL; PSUPPAGE paPhysPages = (PSUPPAGE)&pSub->auBitmap[cPages / (sizeof(pSub->auBitmap[0]) * 8)]; Assert((uintptr_t)paPhysPages >= (uintptr_t)&pSub->auBitmap[1]); if (!pPool->fLow) { rc = SUPR3PageAllocEx(cPages, 0 /* fFlags */, &pSub->pvPages, NULL, paPhysPages); if (RT_FAILURE(rc)) rc = VMSetError(pPool->pVM, rc, RT_SRC_POS, N_("Failed to lock host %zd bytes of memory (out of memory)"), (size_t)cPages << PAGE_SHIFT); } else rc = SUPR3LowAlloc(cPages, &pSub->pvPages, NULL, paPhysPages); if (RT_SUCCESS(rc)) { /* * Setup the sub structure and allocate the requested page. */ pSub->cPages = cPages; pSub->cPagesFree= cPages - 1; pSub->paPhysPages = paPhysPages; memset(pSub->auBitmap, 0, cPages / 8); /* allocate first page. */ pSub->auBitmap[0] |= 1; /* link into free chain. */ pSub->pNextFree = pPool->pHeadFree; pPool->pHeadFree= pSub; /* link into main chain. */ pSub->pNext = pPool->pHead; pPool->pHead = pSub; /* update pool statistics. */ pPool->cSubPools++; pPool->cPages += cPages; #ifdef VBOX_WITH_STATISTICS pPool->cFreePages += cPages - 1; #endif /* * Initialize the physical pages with backpointer to subpool. */ unsigned i = cPages; while (i-- > 0) { AssertMsg(paPhysPages[i].Phys && !(paPhysPages[i].Phys & PAGE_OFFSET_MASK), ("i=%d Phys=%d\n", i, paPhysPages[i].Phys)); paPhysPages[i].uReserved = (RTHCUINTPTR)pSub; } /* * Initialize the physical lookup record with backpointers to the physical pages. */ PMMPPLOOKUPHCPHYS paLookupPhys = (PMMPPLOOKUPHCPHYS)&paPhysPages[cPages]; i = cPages; while (i-- > 0) { paLookupPhys[i].pPhysPage = &paPhysPages[i]; paLookupPhys[i].Core.Key = paPhysPages[i].Phys; RTAvlHCPhysInsert(&pPool->pLookupPhys, &paLookupPhys[i].Core); } /* * And the one record for virtual memory lookup. */ PMMPPLOOKUPHCPTR pLookupVirt = (PMMPPLOOKUPHCPTR)&paLookupPhys[cPages]; pLookupVirt->pSubPool = pSub; pLookupVirt->Core.Key = pSub->pvPages; RTAvlPVInsert(&pPool->pLookupVirt, &pLookupVirt->Core); /* return allocated page (first). */ return pSub->pvPages; } MMHyperFree(pPool->pVM, pSub); STAM_COUNTER_INC(&pPool->cErrors); if (pPool->fLow) VMSetError(pPool->pVM, rc, RT_SRC_POS, N_("Failed to expand page pool for memory below 4GB. Current size: %d pages"), pPool->cPages); AssertMsgFailed(("Failed to expand pool%s. rc=%Rrc poolsize=%d\n", pPool->fLow ? " (<4GB)" : "", rc, pPool->cPages)); return NULL; }
/** * Worker for the --list and --extract commands. * * @returns The appropriate exit code. * @param pOpts The Unzip options. * @param pfnCallback The command specific callback. */ static RTEXITCODE rtZipUnzipDoWithMembers(PRTZIPUNZIPCMDOPS pOpts, PFNDOWITHMEMBER pfnCallback, uint32_t *pcFiles, PRTFOFF pcBytes) { /* * Allocate a bitmap to go with the file list. This will be used to * indicate which files we've processed and which not. */ uint32_t *pbmFound = NULL; if (pOpts->cFiles) { pbmFound = (uint32_t *)RTMemAllocZ(((pOpts->cFiles + 31) / 32) * sizeof(uint32_t)); if (!pbmFound) return RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to allocate the found-file-bitmap"); } uint32_t cFiles = 0; RTFOFF cBytesSum = 0; /* * Open the input archive. */ RTVFSFSSTREAM hVfsFssIn; RTEXITCODE rcExit = rtZipUnzipCmdOpenInputArchive(pOpts, &hVfsFssIn); if (rcExit == RTEXITCODE_SUCCESS) { /* * Process the stream. */ for (;;) { /* * Retrieve the next object. */ char *pszName; RTVFSOBJ hVfsObj; int rc = RTVfsFsStrmNext(hVfsFssIn, &pszName, NULL, &hVfsObj); if (RT_FAILURE(rc)) { if (rc != VERR_EOF) rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "RTVfsFsStrmNext returned %Rrc", rc); break; } /* * Should we process this object? */ uint32_t iFile = UINT32_MAX; if ( !pOpts->cFiles || rtZipUnzipCmdIsNameInArray(pszName, pOpts->papszFiles, &iFile)) { if (pbmFound) ASMBitSet(pbmFound, iFile); RTFOFF cBytes = 0; rcExit = pfnCallback(pOpts, hVfsObj, pszName, rcExit, &cBytes); cBytesSum += cBytes; cFiles++; } /* * Release the current object and string. */ RTVfsObjRelease(hVfsObj); RTStrFree(pszName); } /* * Complain about any files we didn't find. */ for (uint32_t iFile = 0; iFile <pOpts->cFiles; iFile++) if (!ASMBitTest(pbmFound, iFile)) { RTMsgError("%s: Was not found in the archive", pOpts->papszFiles[iFile]); rcExit = RTEXITCODE_FAILURE; } RTVfsFsStrmRelease(hVfsFssIn); } RTMemFree(pbmFound); *pcFiles = cFiles; *pcBytes = cBytesSum; return RTEXITCODE_SUCCESS; }
RTDECL(bool) ASMBitTestAndToggle(volatile void *pvBitmap, int32_t iBit) { bool fRet = ASMBitTest(pvBitmap, iBit); ASMBitToggle(pvBitmap, iBit); return fRet; }
PCR_DISPLAY crServerDisplayGetInitialized(uint32_t idScreen) { if (ASMBitTest(cr_server.DisplaysInitMap, idScreen)) return &cr_server.aDispplays[idScreen]; return NULL; }
/** * Allocates one or more pages off the heap. * * @returns IPRT status code. * @param pHeap The page heap. * @param pv Pointer to what RTHeapPageAlloc returned. * @param cPages The number of pages that was allocated. */ int RTHeapPageFree(PRTHEAPPAGE pHeap, void *pv, size_t cPages) { /* * Validate input. */ if (!pv) return VINF_SUCCESS; AssertPtrReturn(pHeap, VERR_INVALID_HANDLE); AssertReturn(pHeap->u32Magic == RTHEAPPAGE_MAGIC, VERR_INVALID_HANDLE); /* * Grab the lock and look up the page. */ int rc = RTCritSectEnter(&pHeap->CritSect); if (RT_SUCCESS(rc)) { PRTHEAPPAGEBLOCK pBlock = (PRTHEAPPAGEBLOCK)RTAvlrPVRangeGet(&pHeap->BlockTree, pv); if (pBlock) { /* * Validate the specified address range. */ uint32_t const iPage = (uint32_t)(((uintptr_t)pv - (uintptr_t)pBlock->Core.Key) >> PAGE_SHIFT); /* Check the range is within the block. */ bool fOk = iPage + cPages <= RTMEMPAGEPOSIX_BLOCK_PAGE_COUNT; /* Check that it's the start of an allocation. */ fOk = fOk && ASMBitTest(&pBlock->bmFirst[0], iPage); /* Check that the range ends at an allocation boundrary. */ fOk = fOk && ( iPage + cPages == RTMEMPAGEPOSIX_BLOCK_PAGE_COUNT || ASMBitTest(&pBlock->bmFirst[0], iPage + cPages) || !ASMBitTest(&pBlock->bmAlloc[0], iPage + cPages)); /* Check the other pages. */ uint32_t const iLastPage = iPage + cPages - 1; for (uint32_t i = iPage + 1; i < iLastPage && fOk; i++) fOk = ASMBitTest(&pBlock->bmAlloc[0], i) && !ASMBitTest(&pBlock->bmFirst[0], i); if (fOk) { /* * Free the memory. */ ASMBitClearRange(&pBlock->bmAlloc[0], iPage, iPage + cPages); ASMBitClear(&pBlock->bmFirst[0], iPage); pBlock->cFreePages += cPages; pHeap->cFreePages += cPages; pHeap->cFreeCalls++; if (!pHeap->pHint1 || pHeap->pHint1->cFreePages < pBlock->cFreePages) pHeap->pHint1 = pBlock; /* * Shrink the heap. Not very efficient because of the AVL tree. */ if ( pHeap->cFreePages >= RTMEMPAGEPOSIX_BLOCK_PAGE_COUNT * 3 && pHeap->cFreePages >= pHeap->cHeapPages / 2 /* 50% free */ && pHeap->cFreeCalls - pHeap->uLastMinimizeCall > RTMEMPAGEPOSIX_BLOCK_PAGE_COUNT ) { uint32_t cFreePageTarget = pHeap->cHeapPages / 4; /* 25% free */ while (pHeap->cFreePages > cFreePageTarget) { pHeap->uLastMinimizeCall = pHeap->cFreeCalls; pBlock = NULL; RTAvlrPVDoWithAll(&pHeap->BlockTree, false /*fFromLeft*/, rtHeapPageFindUnusedBlockCallback, &pBlock); if (!pBlock) break; void *pv2 = RTAvlrPVRemove(&pHeap->BlockTree, pBlock->Core.Key); Assert(pv2); NOREF(pv2); pHeap->cHeapPages -= RTMEMPAGEPOSIX_BLOCK_PAGE_COUNT; pHeap->cFreePages -= RTMEMPAGEPOSIX_BLOCK_PAGE_COUNT; pHeap->pHint1 = NULL; pHeap->pHint2 = NULL; RTCritSectLeave(&pHeap->CritSect); munmap(pBlock->Core.Key, RTMEMPAGEPOSIX_BLOCK_SIZE); pBlock->Core.Key = pBlock->Core.KeyLast = NULL; pBlock->cFreePages = 0; rtMemBaseFree(pBlock); RTCritSectEnter(&pHeap->CritSect); } } } else rc = VERR_INVALID_POINTER; } else rc = VERR_INVALID_POINTER; RTCritSectLeave(&pHeap->CritSect); }