/** * Internal consistency check. */ static void mmHyperHeapCheck(PMMHYPERHEAP pHeap) { PMMHYPERCHUNKFREE pPrev = NULL; PMMHYPERCHUNKFREE pCur = (PMMHYPERCHUNKFREE)pHeap->CTX_SUFF(pbHeap); for (;;) { if (MMHYPERCHUNK_ISUSED(&pCur->core)) ASSERT_CHUNK_USED(pHeap, &pCur->core); else ASSERT_CHUNK_FREE(pHeap, pCur); if (pPrev) AssertMsg((int32_t)pPrev->core.offNext == -MMHYPERCHUNK_GET_OFFPREV(&pCur->core), ("pPrev->core.offNext=%d offPrev=%d\n", pPrev->core.offNext, MMHYPERCHUNK_GET_OFFPREV(&pCur->core))); # ifdef MMHYPER_HEAP_STRICT_FENCE uint32_t off = (uint8_t *)pCur - pHeap->CTX_SUFF(pbHeap); if ( MMHYPERCHUNK_ISUSED(&pCur->core) && off < pHeap->offPageAligned) { uint32_t cbCur = pCur->core.offNext ? pCur->core.offNext : pHeap->cbHeap - off; uint32_t *pu32End = ((uint32_t *)((uint8_t *)pCur + cbCur)); uint32_t cbFence = pu32End[-1]; if (RT_UNLIKELY( cbFence >= cbCur - sizeof(*pCur) || cbFence < MMHYPER_HEAP_STRICT_FENCE_SIZE)) { mmHyperHeapDumpOne(pHeap, pCur); Assert(cbFence < cbCur - sizeof(*pCur)); Assert(cbFence >= MMHYPER_HEAP_STRICT_FENCE_SIZE); } uint32_t *pu32Bad = ASMMemIsAllU32((uint8_t *)pu32End - cbFence, cbFence - sizeof(uint32_t), MMHYPER_HEAP_STRICT_FENCE_U32); if (RT_UNLIKELY(pu32Bad)) { mmHyperHeapDumpOne(pHeap, pCur); Assert(!pu32Bad); } } # endif /* next */ if (!pCur->core.offNext) break; pPrev = pCur; pCur = (PMMHYPERCHUNKFREE)((char *)pCur + pCur->core.offNext); } }
int main(int argc, char **argv) { RTR3InitExe(argc, &argv, 0); /* * Parse arguments. */ static const RTGETOPTDEF s_aOptions[] = { { "--iterations", 'i', RTGETOPT_REQ_UINT32 }, { "--num-pages", 'n', RTGETOPT_REQ_UINT32 }, { "--page-at-a-time", 'c', RTGETOPT_REQ_UINT32 }, { "--page-file", 'f', RTGETOPT_REQ_STRING }, { "--offset", 'o', RTGETOPT_REQ_UINT64 }, }; const char *pszPageFile = NULL; uint64_t offPageFile = 0; uint32_t cIterations = 1; uint32_t cPagesAtATime = 1; RTGETOPTUNION Val; RTGETOPTSTATE State; int rc = RTGetOptInit(&State, argc, argv, &s_aOptions[0], RT_ELEMENTS(s_aOptions), 1, 0); AssertRCReturn(rc, 1); while ((rc = RTGetOpt(&State, &Val))) { switch (rc) { case 'n': g_cPages = Val.u32; if (g_cPages * PAGE_SIZE * 4 / (PAGE_SIZE * 4) != g_cPages) return Error("The specified page count is too high: %#x (%#llx bytes)\n", g_cPages, (uint64_t)g_cPages * PAGE_SHIFT); if (g_cPages < 1) return Error("The specified page count is too low: %#x\n", g_cPages); break; case 'i': cIterations = Val.u32; if (cIterations < 1) return Error("The number of iterations must be 1 or higher\n"); break; case 'c': cPagesAtATime = Val.u32; if (cPagesAtATime < 1 || cPagesAtATime > 10240) return Error("The specified pages-at-a-time count is out of range: %#x\n", cPagesAtATime); break; case 'f': pszPageFile = Val.psz; break; case 'o': offPageFile = Val.u64; break; case 'O': offPageFile = Val.u64 * PAGE_SIZE; break; case 'h': RTPrintf("syntax: tstCompressionBenchmark [options]\n" "\n" "Options:\n" " -h, --help\n" " Show this help page\n" " -i, --iterations <num>\n" " The number of iterations.\n" " -n, --num-pages <pages>\n" " The number of pages.\n" " -c, --pages-at-a-time <pages>\n" " Number of pages at a time.\n" " -f, --page-file <filename>\n" " File or device to read the page from. The default\n" " is to generate some garbage.\n" " -o, --offset <file-offset>\n" " Offset into the page file to start reading at.\n"); return 0; case 'V': RTPrintf("%sr%s\n", RTBldCfgVersion(), RTBldCfgRevisionStr()); return 0; default: return RTGetOptPrintError(rc, &Val); } } g_cbPages = g_cPages * PAGE_SIZE; uint64_t cbTotal = (uint64_t)g_cPages * PAGE_SIZE * cIterations; uint64_t cbTotalKB = cbTotal / _1K; if (cbTotal / cIterations != g_cbPages) return Error("cPages * cIterations -> overflow\n"); /* * Gather the test memory. */ if (pszPageFile) { size_t cbFile; rc = RTFileReadAllEx(pszPageFile, offPageFile, g_cbPages, RTFILE_RDALL_O_DENY_NONE, (void **)&g_pabSrc, &cbFile); if (RT_FAILURE(rc)) return Error("Error reading %zu bytes from %s at %llu: %Rrc\n", g_cbPages, pszPageFile, offPageFile, rc); if (cbFile != g_cbPages) return Error("Error reading %zu bytes from %s at %llu: got %zu bytes\n", g_cbPages, pszPageFile, offPageFile, cbFile); } else { g_pabSrc = (uint8_t *)RTMemAlloc(g_cbPages); if (g_pabSrc) { /* Just fill it with something - warn about the low quality of the something. */ RTPrintf("tstCompressionBenchmark: WARNING! No input file was specified so the source\n" "buffer will be filled with generated data of questionable quality.\n"); #ifdef RT_OS_LINUX RTPrintf("To get real RAM on linux: sudo dd if=/dev/mem ... \n"); #endif uint8_t *pb = g_pabSrc; uint8_t *pbEnd = &g_pabSrc[g_cbPages]; for (; pb != pbEnd; pb += 16) { char szTmp[17]; RTStrPrintf(szTmp, sizeof(szTmp), "aaaa%08Xzzzz", (uint32_t)(uintptr_t)pb); memcpy(pb, szTmp, 16); } } } g_pabDecompr = (uint8_t *)RTMemAlloc(g_cbPages); g_cbComprAlloc = RT_MAX(g_cbPages * 2, 256 * PAGE_SIZE); g_pabCompr = (uint8_t *)RTMemAlloc(g_cbComprAlloc); if (!g_pabSrc || !g_pabDecompr || !g_pabCompr) return Error("failed to allocate memory buffers (g_cPages=%#x)\n", g_cPages); /* * Double loop compressing and uncompressing the data, where the outer does * the specified number of iterations while the inner applies the different * compression algorithms. */ struct { /** The time spent decompressing. */ uint64_t cNanoDecompr; /** The time spent compressing. */ uint64_t cNanoCompr; /** The size of the compressed data. */ uint64_t cbCompr; /** First error. */ int rc; /** The compression style: block or stream. */ bool fBlock; /** Compression type. */ RTZIPTYPE enmType; /** Compression level. */ RTZIPLEVEL enmLevel; /** Method name. */ const char *pszName; } aTests[] = { { 0, 0, 0, VINF_SUCCESS, false, RTZIPTYPE_STORE, RTZIPLEVEL_DEFAULT, "RTZip/Store" }, { 0, 0, 0, VINF_SUCCESS, false, RTZIPTYPE_LZF, RTZIPLEVEL_DEFAULT, "RTZip/LZF" }, /* { 0, 0, 0, VINF_SUCCESS, false, RTZIPTYPE_ZLIB, RTZIPLEVEL_DEFAULT, "RTZip/zlib" }, - slow plus it randomly hits VERR_GENERAL_FAILURE atm. */ { 0, 0, 0, VINF_SUCCESS, true, RTZIPTYPE_STORE, RTZIPLEVEL_DEFAULT, "RTZipBlock/Store" }, { 0, 0, 0, VINF_SUCCESS, true, RTZIPTYPE_LZF, RTZIPLEVEL_DEFAULT, "RTZipBlock/LZF" }, { 0, 0, 0, VINF_SUCCESS, true, RTZIPTYPE_LZJB, RTZIPLEVEL_DEFAULT, "RTZipBlock/LZJB" }, { 0, 0, 0, VINF_SUCCESS, true, RTZIPTYPE_LZO, RTZIPLEVEL_DEFAULT, "RTZipBlock/LZO" }, }; RTPrintf("tstCompressionBenchmark: TESTING.."); for (uint32_t i = 0; i < cIterations; i++) { for (uint32_t j = 0; j < RT_ELEMENTS(aTests); j++) { if (RT_FAILURE(aTests[j].rc)) continue; memset(g_pabCompr, 0xaa, g_cbComprAlloc); memset(g_pabDecompr, 0xcc, g_cbPages); g_cbCompr = 0; g_offComprIn = 0; RTPrintf("."); RTStrmFlush(g_pStdOut); /* * Compress it. */ uint64_t NanoTS = RTTimeNanoTS(); if (aTests[j].fBlock) { size_t cbLeft = g_cbComprAlloc; uint8_t const *pbSrcPage = g_pabSrc; uint8_t *pbDstPage = g_pabCompr; for (size_t iPage = 0; iPage < g_cPages; iPage += cPagesAtATime) { AssertBreakStmt(cbLeft > PAGE_SIZE * 4, aTests[j].rc = rc = VERR_BUFFER_OVERFLOW); uint32_t *pcb = (uint32_t *)pbDstPage; pbDstPage += sizeof(uint32_t); cbLeft -= sizeof(uint32_t); size_t cbSrc = RT_MIN(g_cPages - iPage, cPagesAtATime) * PAGE_SIZE; size_t cbDst; rc = RTZipBlockCompress(aTests[j].enmType, aTests[j].enmLevel, 0 /*fFlags*/, pbSrcPage, cbSrc, pbDstPage, cbLeft, &cbDst); if (RT_FAILURE(rc)) { Error("RTZipBlockCompress failed for '%s' (#%u): %Rrc\n", aTests[j].pszName, j, rc); aTests[j].rc = rc; break; } *pcb = (uint32_t)cbDst; cbLeft -= cbDst; pbDstPage += cbDst; pbSrcPage += cbSrc; } if (RT_FAILURE(rc)) continue; g_cbCompr = pbDstPage - g_pabCompr; } else { PRTZIPCOMP pZipComp; rc = RTZipCompCreate(&pZipComp, NULL, ComprOutCallback, aTests[j].enmType, aTests[j].enmLevel); if (RT_FAILURE(rc)) { Error("Failed to create the compressor for '%s' (#%u): %Rrc\n", aTests[j].pszName, j, rc); aTests[j].rc = rc; continue; } uint8_t const *pbSrcPage = g_pabSrc; for (size_t iPage = 0; iPage < g_cPages; iPage += cPagesAtATime) { size_t cb = RT_MIN(g_cPages - iPage, cPagesAtATime) * PAGE_SIZE; rc = RTZipCompress(pZipComp, pbSrcPage, cb); if (RT_FAILURE(rc)) { Error("RTZipCompress failed for '%s' (#%u): %Rrc\n", aTests[j].pszName, j, rc); aTests[j].rc = rc; break; } pbSrcPage += cb; } if (RT_FAILURE(rc)) continue; rc = RTZipCompFinish(pZipComp); if (RT_FAILURE(rc)) { Error("RTZipCompFinish failed for '%s' (#%u): %Rrc\n", aTests[j].pszName, j, rc); aTests[j].rc = rc; break; } RTZipCompDestroy(pZipComp); } NanoTS = RTTimeNanoTS() - NanoTS; aTests[j].cbCompr += g_cbCompr; aTests[j].cNanoCompr += NanoTS; /* * Decompress it. */ NanoTS = RTTimeNanoTS(); if (aTests[j].fBlock) { uint8_t const *pbSrcPage = g_pabCompr; size_t cbLeft = g_cbCompr; uint8_t *pbDstPage = g_pabDecompr; for (size_t iPage = 0; iPage < g_cPages; iPage += cPagesAtATime) { size_t cbDst = RT_MIN(g_cPages - iPage, cPagesAtATime) * PAGE_SIZE; size_t cbSrc = *(uint32_t *)pbSrcPage; pbSrcPage += sizeof(uint32_t); cbLeft -= sizeof(uint32_t); rc = RTZipBlockDecompress(aTests[j].enmType, 0 /*fFlags*/, pbSrcPage, cbSrc, &cbSrc, pbDstPage, cbDst, &cbDst); if (RT_FAILURE(rc)) { Error("RTZipBlockDecompress failed for '%s' (#%u): %Rrc\n", aTests[j].pszName, j, rc); aTests[j].rc = rc; break; } pbDstPage += cbDst; cbLeft -= cbSrc; pbSrcPage += cbSrc; } if (RT_FAILURE(rc)) continue; } else { PRTZIPDECOMP pZipDecomp; rc = RTZipDecompCreate(&pZipDecomp, NULL, DecomprInCallback); if (RT_FAILURE(rc)) { Error("Failed to create the decompressor for '%s' (#%u): %Rrc\n", aTests[j].pszName, j, rc); aTests[j].rc = rc; continue; } uint8_t *pbDstPage = g_pabDecompr; for (size_t iPage = 0; iPage < g_cPages; iPage += cPagesAtATime) { size_t cb = RT_MIN(g_cPages - iPage, cPagesAtATime) * PAGE_SIZE; rc = RTZipDecompress(pZipDecomp, pbDstPage, cb, NULL); if (RT_FAILURE(rc)) { Error("RTZipDecompress failed for '%s' (#%u): %Rrc\n", aTests[j].pszName, j, rc); aTests[j].rc = rc; break; } pbDstPage += cb; } RTZipDecompDestroy(pZipDecomp); if (RT_FAILURE(rc)) continue; } NanoTS = RTTimeNanoTS() - NanoTS; aTests[j].cNanoDecompr += NanoTS; if (memcmp(g_pabDecompr, g_pabSrc, g_cbPages)) { Error("The compressed data doesn't match the source for '%s' (%#u)\n", aTests[j].pszName, j); aTests[j].rc = VERR_BAD_EXE_FORMAT; continue; } } } if (RT_SUCCESS(rc)) RTPrintf("\n"); /* * Report the results. */ rc = 0; RTPrintf("tstCompressionBenchmark: BEGIN RESULTS\n"); RTPrintf("%-20s Compression Decompression\n", ""); RTPrintf("%-20s In Out Ratio Size In Out\n", "Method"); RTPrintf("%.20s-----------------------------------------------------------------------------------------\n", "---------------------------------------------"); for (uint32_t j = 0; j < RT_ELEMENTS(aTests); j++) { if (RT_SUCCESS(aTests[j].rc)) { unsigned uComprSpeedIn = (unsigned)(cbTotalKB / (long double)aTests[j].cNanoCompr * 1000000000.0); unsigned uComprSpeedOut = (unsigned)(aTests[j].cbCompr / (long double)aTests[j].cNanoCompr * 1000000000.0 / 1024); unsigned uRatio = (unsigned)(aTests[j].cbCompr / cIterations * 100 / g_cbPages); unsigned uDecomprSpeedIn = (unsigned)(aTests[j].cbCompr / (long double)aTests[j].cNanoDecompr * 1000000000.0 / 1024); unsigned uDecomprSpeedOut = (unsigned)(cbTotalKB / (long double)aTests[j].cNanoDecompr * 1000000000.0); RTPrintf("%-20s %'9u KB/s %'9u KB/s %3u%% %'11llu bytes %'9u KB/s %'9u KB/s", aTests[j].pszName, uComprSpeedIn, uComprSpeedOut, uRatio, aTests[j].cbCompr / cIterations, uDecomprSpeedIn, uDecomprSpeedOut); #if 0 RTPrintf(" [%'14llu / %'14llu ns]\n", aTests[j].cNanoCompr / cIterations, aTests[j].cNanoDecompr / cIterations); #else RTPrintf("\n"); #endif } else { RTPrintf("%-20s: %Rrc\n", aTests[j].pszName, aTests[j].rc); rc = 1; } } if (pszPageFile) RTPrintf("Input: %'10zu pages from '%s' starting at offset %'lld (%#llx)\n" " %'11zu bytes\n", g_cPages, pszPageFile, offPageFile, offPageFile, g_cbPages); else RTPrintf("Input: %'10zu pages of generated rubbish %'11zu bytes\n", g_cPages, g_cbPages); /* * Count zero pages in the data set. */ size_t cZeroPages = 0; for (size_t iPage = 0; iPage < g_cPages; iPage++) { if (!ASMMemIsAllU32(&g_pabSrc[iPage * PAGE_SIZE], PAGE_SIZE, 0)) cZeroPages++; } RTPrintf(" %'10zu zero pages (%u %%)\n", cZeroPages, cZeroPages * 100 / g_cPages); /* * A little extension to the test, benchmark relevant CRCs. */ RTPrintf("\n" "tstCompressionBenchmark: Hash/CRC - All In One\n"); tstBenchmarkCRCsAllInOne(g_pabSrc, g_cbPages); RTPrintf("\n" "tstCompressionBenchmark: Hash/CRC - Page by Page\n"); tstBenchmarkCRCsPageByPage(g_pabSrc, g_cbPages); RTPrintf("\n" "tstCompressionBenchmark: Hash/CRC - Zero Page Digest\n"); static uint8_t s_abZeroPg[PAGE_SIZE]; RT_ZERO(s_abZeroPg); tstBenchmarkCRCsAllInOne(s_abZeroPg, PAGE_SIZE); RTPrintf("\n" "tstCompressionBenchmark: Hash/CRC - Zero Half Page Digest\n"); tstBenchmarkCRCsAllInOne(s_abZeroPg, PAGE_SIZE / 2); RTPrintf("tstCompressionBenchmark: END RESULTS\n"); return rc; }
/** * Parses and validates a TAR header. * * @returns IPRT status code. * @param pThis The TAR reader stat. * @param pTar The TAR header that has been read. */ static int rtZipTarReaderParseHeader(PRTZIPTARREADER pThis, PCRTZIPTARHDR pHdr) { switch (pThis->enmState) { /* * The first record for a file/directory/whatever. */ case RTZIPTARREADERSTATE_FIRST: pThis->Hdr.Common.typeflag = 0x7f; pThis->enmPrevType = pThis->enmType; pThis->enmType = RTZIPTARTYPE_INVALID; pThis->offGnuLongCur = 0; pThis->cbGnuLongExpect = 0; pThis->szName[0] = '\0'; pThis->szTarget[0] = '\0'; return rtZipTarReaderParseNextHeader(pThis, pHdr, true /*fFirst*/); /* * There should only be so many zero headers at the end of the file as * it is a function of the block size used when writing. Don't go on * reading them forever in case someone points us to /dev/zero. */ case RTZIPTARREADERSTATE_ZERO: if (ASMMemIsAllU32(pHdr, sizeof(*pHdr), 0) != NULL) return VERR_TAR_ZERO_HEADER; pThis->cZeroHdrs++; if (pThis->cZeroHdrs <= _64K / 512 + 2) return VINF_SUCCESS; return VERR_TAR_ZERO_HEADER; case RTZIPTARREADERSTATE_GNU_LONGNAME: case RTZIPTARREADERSTATE_GNU_LONGLINK: { size_t cbIncoming = RTStrNLen((const char *)pHdr->ab, sizeof(*pHdr)); if (cbIncoming < sizeof(*pHdr)) cbIncoming += 1; if (cbIncoming + pThis->offGnuLongCur > pThis->cbGnuLongExpect) return VERR_TAR_MALFORMED_GNU_LONGXXXX; if ( cbIncoming < sizeof(*pHdr) && cbIncoming + pThis->offGnuLongCur != pThis->cbGnuLongExpect) return VERR_TAR_MALFORMED_GNU_LONGXXXX; char *pszDst = pThis->enmState == RTZIPTARREADERSTATE_GNU_LONGNAME ? pThis->szName : pThis->szTarget; pszDst += pThis->offGnuLongCur; memcpy(pszDst, pHdr->ab, cbIncoming); pThis->offGnuLongCur += (uint32_t)cbIncoming; if (pThis->offGnuLongCur == pThis->cbGnuLongExpect) pThis->enmState = RTZIPTARREADERSTATE_GNU_NEXT; return VINF_SUCCESS; } case RTZIPTARREADERSTATE_GNU_NEXT: pThis->enmState = RTZIPTARREADERSTATE_FIRST; return rtZipTarReaderParseNextHeader(pThis, pHdr, false /*fFirst*/); default: return VERR_INTERNAL_ERROR_5; } }
/** * Basic API checks. * We'll return if any of these fails. */ static void tst1(RTMEMPOOL hMemPool) { void *pv; /* Normal alloc. */ RTTESTI_CHECK_RETV(pv = RTMemPoolAlloc(hMemPool, 1)); RTTESTI_CHECK_RETV(RTMemPoolRelease(hMemPool, pv) == 0); RTTESTI_CHECK_RETV(pv = RTMemPoolAlloc(hMemPool, 0)); RTTESTI_CHECK_RETV(RTMemPoolRelease(hMemPool, pv) == 0); /* Zeroed allocation. */ for (uint32_t i = 0; i < 512; i++) { RTTESTI_CHECK_RETV(pv = RTMemPoolAllocZ(hMemPool, 1024)); RTTESTI_CHECK(ASMMemIsAllU32(pv, 1024, 0) == NULL); memset(pv, 'a', 1024); RTTESTI_CHECK_RETV(RTMemPoolRefCount(pv) == 1); RTTESTI_CHECK_RETV(RTMemPoolRelease(hMemPool, pv) == 0); } RTTESTI_CHECK_RETV(pv = RTMemPoolAllocZ(hMemPool, 0)); RTTESTI_CHECK_RETV(RTMemPoolRelease(hMemPool, pv) == 0); /* Duped allocation. */ static const char szTest[] = "test string abcdef"; RTTESTI_CHECK_RETV(pv = RTMemPoolDup(hMemPool, szTest, sizeof(szTest))); RTTESTI_CHECK(memcmp(pv, szTest, sizeof(szTest)) == 0); RTTESTI_CHECK_RETV(RTMemPoolRelease(hMemPool, pv) == 0); for (uint32_t i = 0; i < 512; i++) { size_t const cb = 256 - sizeof(szTest); RTTESTI_CHECK_RETV(pv = RTMemPoolDupEx(hMemPool, szTest, sizeof(szTest), cb)); RTTESTI_CHECK(memcmp(pv, szTest, sizeof(szTest)) == 0); RTTESTI_CHECK(ASMMemIsAll8((uint8_t *)pv + sizeof(szTest), cb, 0) == NULL); memset(pv, 'b', sizeof(szTest) + cb); RTTESTI_CHECK_RETV(RTMemPoolRefCount(pv) == 1); RTTESTI_CHECK_RETV(RTMemPoolRelease(hMemPool, pv) == 0); } /* Reallocation */ RTTESTI_CHECK_RETV(pv = RTMemPoolRealloc(hMemPool, NULL, 1)); RTTESTI_CHECK_RETV(pv = RTMemPoolRealloc(hMemPool, pv, 2)); RTTESTI_CHECK_RETV(RTMemPoolRelease(hMemPool, pv) == 0); RTTESTI_CHECK_RETV(pv = RTMemPoolAlloc(hMemPool, 42)); RTTESTI_CHECK_RETV(pv = RTMemPoolRealloc(hMemPool, pv, 32)); RTTESTI_CHECK_RETV(RTMemPoolRelease(hMemPool, pv) == 0); RTTESTI_CHECK_RETV(pv = RTMemPoolRealloc(hMemPool, NULL, 128)); RTTESTI_CHECK_RETV(pv = RTMemPoolRealloc(hMemPool, pv, 256)); RTTESTI_CHECK_RETV(RTMemPoolRealloc(hMemPool, pv, 0) == NULL); /* Free (a bit hard to test) */ RTMemPoolFree(hMemPool, NULL); RTMemPoolFree(hMemPool, RTMemPoolAlloc(hMemPool, 42)); /* Memory referencing. */ for (uint32_t i = 1; i <= 4096; i *= 3) { void *pv2; RTTESTI_CHECK_RETV(pv = RTMemPoolAlloc(hMemPool, i)); RTTESTI_CHECK(RTMemPoolRefCount(pv) == 1); memset(pv, 'a', i); RTTESTI_CHECK_MSG_RETV((pv2 = ASMMemIsAll8(pv, i, 'a')) == NULL, ("i=%#x pv=%p off=%#x\n", i, pv, (uintptr_t)pv2 - (uintptr_t)pv)); RTTESTI_CHECK(RTMemPoolRetain(pv) == 2); RTTESTI_CHECK(RTMemPoolRefCount(pv) == 2); RTTESTI_CHECK(RTMemPoolRetain(pv) == 3); RTTESTI_CHECK(RTMemPoolRefCount(pv) == 3); RTTESTI_CHECK(RTMemPoolRetain(pv) == 4); RTTESTI_CHECK(RTMemPoolRefCount(pv) == 4); RTTESTI_CHECK_MSG_RETV((pv2 = ASMMemIsAll8(pv, i, 'a')) == NULL, ("i=%#x pv=%p off=%#x\n", i, pv, (uintptr_t)pv2 - (uintptr_t)pv)); RTTESTI_CHECK(RTMemPoolRelease(hMemPool, pv) == 3); RTTESTI_CHECK(RTMemPoolRefCount(pv) == 3); RTTESTI_CHECK_MSG_RETV((pv2 = ASMMemIsAll8(pv, i, 'a')) == NULL, ("i=%#x pv=%p off=%#x\n", i, pv, (uintptr_t)pv2 - (uintptr_t)pv)); RTTESTI_CHECK(RTMemPoolRetain(pv) == 4); RTTESTI_CHECK(RTMemPoolRefCount(pv) == 4); RTTESTI_CHECK(RTMemPoolRetain(pv) == 5); RTTESTI_CHECK(RTMemPoolRefCount(pv) == 5); RTTESTI_CHECK(RTMemPoolRetain(pv) == 6); RTTESTI_CHECK(RTMemPoolRefCount(pv) == 6); RTTESTI_CHECK(RTMemPoolRelease(NIL_RTMEMPOOL, pv) == 5); RTTESTI_CHECK(RTMemPoolRelease(NIL_RTMEMPOOL, pv) == 4); RTTESTI_CHECK_MSG_RETV((pv2 = ASMMemIsAll8(pv, i, 'a')) == NULL, ("i=%#x pv=%p off=%#x\n", i, pv, (uintptr_t)pv2 - (uintptr_t)pv)); for (uint32_t cRefs = 3;; cRefs--) { RTTESTI_CHECK(RTMemPoolRelease(hMemPool, pv) == cRefs); if (cRefs == 0) break; RTTESTI_CHECK(RTMemPoolRefCount(pv) == cRefs); RTTESTI_CHECK_MSG_RETV((pv2 = ASMMemIsAll8(pv, i, 'a')) == NULL, ("i=%#x pv=%p off=%#x cRefs=%d\n", i, pv, (uintptr_t)pv2 - (uintptr_t)pv, cRefs)); for (uint32_t j = 0; j < 42; j++) { RTTESTI_CHECK_RETV(pv2 = RTMemPoolAlloc(hMemPool, i)); RTTESTI_CHECK_RETV(pv2 != pv); memset(pv2, 'f', i); RTTESTI_CHECK(RTMemPoolRelease(hMemPool, pv2) == 0); RTTESTI_CHECK_MSG_RETV((pv2 = ASMMemIsAll8(pv, i, 'a')) == NULL, ("i=%#x pv=%p off=%#x cRefs=%d\n", i, pv, (uintptr_t)pv2 - (uintptr_t)pv, cRefs)); } } } }