/** * Basic API checks. * We'll return if any of these fails. */ static void tst1(void) { RTTestISub("Basics"); /* Create one without constructor or destructor. */ uint32_t const cObjects = PAGE_SIZE * 2 / 256; RTMEMCACHE hMemCache; RTTESTI_CHECK_RC_RETV(RTMemCacheCreate(&hMemCache, 256, cObjects, 32, NULL, NULL, NULL, 0 /*fFlags*/), VINF_SUCCESS); RTTESTI_CHECK_RETV(hMemCache != NIL_RTMEMCACHE); /* Allocate a bit and free it again. */ void *pv = NULL; RTTESTI_CHECK_RC_RETV(RTMemCacheAllocEx(hMemCache, &pv), VINF_SUCCESS); RTTESTI_CHECK_RETV(pv != NULL); RTTESTI_CHECK_RETV(RT_ALIGN_P(pv, 32) == pv); RTMemCacheFree(hMemCache, pv); RTTESTI_CHECK((pv = RTMemCacheAlloc(hMemCache)) != NULL); RTMemCacheFree(hMemCache, pv); /* Allocate everything and free it again, checking size constraints. */ for (uint32_t iLoop = 0; iLoop < 20; iLoop++) { /* Allocate everything. */ void *apv[cObjects]; for (uint32_t i = 0; i < cObjects; i++) { apv[i] = NULL; RTTESTI_CHECK_RC(RTMemCacheAllocEx(hMemCache, &apv[i]), VINF_SUCCESS); } /* Check that we've got it all. */ int rc; RTTESTI_CHECK_RC(rc = RTMemCacheAllocEx(hMemCache, &pv), VERR_MEM_CACHE_MAX_SIZE); if (RT_SUCCESS(rc)) RTMemCacheFree(hMemCache, pv); RTTESTI_CHECK((pv = RTMemCacheAlloc(hMemCache)) == NULL); RTMemCacheFree(hMemCache, pv); /* Free all the allocations. */ for (uint32_t i = 0; i < cObjects; i++) { RTMemCacheFree(hMemCache, apv[i]); RTTESTI_CHECK((pv = RTMemCacheAlloc(hMemCache)) != NULL); RTMemCacheFree(hMemCache, pv); } } /* Destroy it. */ RTTESTI_CHECK_RC(RTMemCacheDestroy(hMemCache), VINF_SUCCESS); RTTESTI_CHECK_RC(RTMemCacheDestroy(NIL_RTMEMCACHE), VINF_SUCCESS); }
/** @copydoc RTDBGMODVTDBG::pfnClose */ static DECLCALLBACK(int) rtDbgModContainer_Close(PRTDBGMODINT pMod) { PRTDBGMODCTN pThis = (PRTDBGMODCTN)pMod->pvDbgPriv; /* * Destroy the symbols and instance data. */ for (uint32_t iSeg = 0; iSeg < pThis->cSegs; iSeg++) { RTAvlrUIntPtrDestroy(&pThis->paSegs[iSeg].SymAddrTree, rtDbgModContainer_DestroyTreeNode, NULL); RTStrCacheRelease(g_hDbgModStrCache, pThis->paSegs[iSeg].pszName); pThis->paSegs[iSeg].pszName = NULL; } RTAvlrUIntPtrDestroy(&pThis->AbsAddrTree, rtDbgModContainer_DestroyTreeNode, NULL); pThis->Names = NULL; #ifdef RTDBGMODCNT_WITH_MEM_CACHE RTMemCacheDestroy(pThis->hLineNumAllocator); pThis->hLineNumAllocator = NIL_RTMEMCACHE; #else RTAvlU32Destroy(&pThis->LineOrdinalTree, rtDbgModContainer_DestroyTreeLineNode, pThis); #endif RTMemFree(pThis->paSegs); pThis->paSegs = NULL; RTMemFree(pThis); return VINF_SUCCESS; }
/** * Time constrained test with and unlimited N threads. */ static void tst3(uint32_t cThreads, uint32_t cbObject, int iMethod, uint32_t cSecs) { RTTestISubF("Benchmark - %u threads, %u bytes, %u secs, %s", cThreads, cbObject, cSecs, iMethod == 0 ? "RTMemCache" : "RTMemAlloc"); /* * Create a cache with unlimited space, a start semaphore and line up * the threads. */ RTTESTI_CHECK_RC_RETV(RTMemCacheCreate(&g_hMemCache, cbObject, 0 /*cbAlignment*/, UINT32_MAX, NULL, NULL, NULL, 0 /*fFlags*/), VINF_SUCCESS); RTSEMEVENTMULTI hEvt; RTTESTI_CHECK_RC_OK_RETV(RTSemEventMultiCreate(&hEvt)); TST3THREAD aThreads[64]; RTTESTI_CHECK_RETV(cThreads < RT_ELEMENTS(aThreads)); ASMAtomicWriteBool(&g_fTst3Stop, false); for (uint32_t i = 0; i < cThreads; i++) { aThreads[i].hThread = NIL_RTTHREAD; aThreads[i].cIterations = 0; aThreads[i].fUseCache = iMethod == 0; aThreads[i].cbObject = cbObject; aThreads[i].hEvt = hEvt; RTTESTI_CHECK_RC_OK_RETV(RTThreadCreateF(&aThreads[i].hThread, tst3Thread, &aThreads[i], 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "tst3-%u", i)); } /* * Start the race. */ RTTimeNanoTS(); /* warmup */ uint64_t uStartTS = RTTimeNanoTS(); RTTESTI_CHECK_RC_OK_RETV(RTSemEventMultiSignal(hEvt)); RTThreadSleep(cSecs * 1000); ASMAtomicWriteBool(&g_fTst3Stop, true); for (uint32_t i = 0; i < cThreads; i++) RTTESTI_CHECK_RC_OK_RETV(RTThreadWait(aThreads[i].hThread, 60*1000, NULL)); uint64_t cElapsedNS = RTTimeNanoTS() - uStartTS; /* * Sum up the counts. */ uint64_t cIterations = 0; for (uint32_t i = 0; i < cThreads; i++) cIterations += aThreads[i].cIterations; RTTestIPrintf(RTTESTLVL_ALWAYS, "%'8u iterations per second, %'llu ns on avg\n", (unsigned)((long double)cIterations * 1000000000.0 / cElapsedNS), cElapsedNS / cIterations); /* clean up */ RTTESTI_CHECK_RC(RTMemCacheDestroy(g_hMemCache), VINF_SUCCESS); RTTESTI_CHECK_RC_OK(RTSemEventMultiDestroy(hEvt)); }
VBOXDDU_DECL(void) VDDbgIoLogDestroy(VDIOLOGGER hIoLogger) { PVDIOLOGGERINT pIoLogger = hIoLogger; AssertPtrReturnVoid(pIoLogger); vddbgIoLoggerHeaderUpdate(pIoLogger); RTFileFlush(pIoLogger->hFile); RTFileClose(pIoLogger->hFile); RTMemCacheDestroy(pIoLogger->hMemCacheIoLogEntries); RTSemFastMutexDestroy(pIoLogger->hMtx); RTMemFree(pIoLogger); }
VBOXDDU_DECL(int) VSCSIDeviceDestroy(VSCSIDEVICE hVScsiDevice) { AssertPtrReturn(hVScsiDevice, VERR_INVALID_HANDLE); PVSCSIDEVICEINT pVScsiDevice = (PVSCSIDEVICEINT)hVScsiDevice; if (pVScsiDevice->cLunsAttached > 0) return VERR_VSCSI_LUN_ATTACHED_TO_DEVICE; if (pVScsiDevice->papVScsiLun) RTMemFree(pVScsiDevice->papVScsiLun); RTMemCacheDestroy(pVScsiDevice->hCacheReq); RTMemFree(pVScsiDevice); return VINF_SUCCESS;; }
/** * Creates a generic debug info container and associates it with the module. * * @returns IPRT status code. * @param pMod The module instance. * @param cbSeg The size of the initial segment. 0 if segments are to be * created manually later on. */ int rtDbgModContainerCreate(PRTDBGMODINT pMod, RTUINTPTR cbSeg) { PRTDBGMODCTN pThis = (PRTDBGMODCTN)RTMemAlloc(sizeof(*pThis)); if (!pThis) return VERR_NO_MEMORY; pThis->Names = NULL; pThis->AbsAddrTree = NULL; pThis->SymbolOrdinalTree = NULL; pThis->LineOrdinalTree = NULL; pThis->paSegs = NULL; pThis->cSegs = 0; pThis->cb = 0; pThis->iNextSymbolOrdinal = 0; pThis->iNextLineOrdinal = 0; pMod->pDbgVt = &g_rtDbgModVtDbgContainer; pMod->pvDbgPriv = pThis; #ifdef RTDBGMODCNT_WITH_MEM_CACHE int rc = RTMemCacheCreate(&pThis->hLineNumAllocator, sizeof(RTDBGMODCTNLINE), sizeof(void *), UINT32_MAX, NULL /*pfnCtor*/, NULL /*pfnDtor*/, NULL /*pvUser*/, 0 /*fFlags*/); #else int rc = VINF_SUCCESS; #endif if (RT_SUCCESS(rc)) { /* * Add the initial segment. */ if (cbSeg) rc = rtDbgModContainer_SegmentAdd(pMod, 0, cbSeg, "default", sizeof("default") - 1, 0, NULL); if (RT_SUCCESS(rc)) return rc; #ifdef RTDBGMODCNT_WITH_MEM_CACHE RTMemCacheDestroy(pThis->hLineNumAllocator); #endif } RTMemFree(pThis); pMod->pDbgVt = NULL; pMod->pvDbgPriv = NULL; return rc; }
/** * Test constructor / destructor. */ static void tst2(void) { RTTestISub("Ctor/Dtor"); /* Create one without constructor or destructor. */ bool fFail = false; uint32_t const cObjects = PAGE_SIZE * 2 / 256; RTTESTI_CHECK_RC_RETV(RTMemCacheCreate(&g_hMemCache, 256, cObjects, 32, tst2Ctor, tst2Dtor, &fFail, 0 /*fFlags*/), VINF_SUCCESS); /* A failure run first. */ fFail = true; void *pv = (void *)0x42; RTTESTI_CHECK_RC_RETV(RTMemCacheAllocEx(g_hMemCache, &pv), VERR_RESOURCE_BUSY); RTTESTI_CHECK(pv == (void *)0x42); fFail = false; /* To two rounds where we allocate all the objects and free them again. */ for (uint32_t iLoop = 0; iLoop < 2; iLoop++) { void *apv[cObjects]; for (uint32_t i = 0; i < cObjects; i++) { apv[i] = NULL; RTTESTI_CHECK_RC_RETV(RTMemCacheAllocEx(g_hMemCache, &apv[i]), VINF_SUCCESS); if (iLoop == 0) RTTESTI_CHECK(!strcmp((char *)apv[i], "ctor was called\n")); else RTTESTI_CHECK(!strcmp((char *)apv[i], "ctor was called\nused\n")); strcat((char *)apv[i], "used\n"); } RTTESTI_CHECK_RETV((pv = RTMemCacheAlloc(g_hMemCache)) == NULL); RTMemCacheFree(g_hMemCache, pv); for (uint32_t i = 0; i < cObjects; i++) RTMemCacheFree(g_hMemCache, apv[i]); } /* Cone, destroy the cache. */ RTTESTI_CHECK_RC(RTMemCacheDestroy(g_hMemCache), VINF_SUCCESS); }