Exemple #1
0
/**
 * Basic API checks.
 * We'll return if any of these fails.
 */
static void tst1(RTSTRCACHE hStrCache)
{
    const char *psz;

    /* Simple string entering and length. */
    RTTESTI_CHECK_RETV(psz = RTStrCacheEnter(hStrCache, "abcdefgh"));
    RTTESTI_CHECK_RETV(strcmp(psz, "abcdefgh") == 0);
    RTTESTI_CHECK_RETV(RTStrCacheLength(psz) == strlen("abcdefgh"));
    RTTESTI_CHECK_RETV(RTStrCacheRelease(hStrCache, psz) == 0);

    RTTESTI_CHECK_RETV(psz = RTStrCacheEnter(hStrCache, "abcdefghijklmnopqrstuvwxyz"));
    RTTESTI_CHECK_RETV(strcmp(psz, "abcdefghijklmnopqrstuvwxyz") == 0);
    RTTESTI_CHECK_RETV(RTStrCacheLength(psz) == strlen("abcdefghijklmnopqrstuvwxyz"));
    RTTESTI_CHECK_RETV(RTStrCacheRelease(hStrCache, psz) == 0);

    /* Unterminated strings. */
    RTTESTI_CHECK_RETV(psz = RTStrCacheEnterN(hStrCache, "0123456789", 3));
    RTTESTI_CHECK_RETV(strcmp(psz, "012") == 0);
    RTTESTI_CHECK_RETV(RTStrCacheLength(psz) == strlen("012"));
    RTTESTI_CHECK_RETV(RTStrCacheRelease(hStrCache, psz) == 0);

    RTTESTI_CHECK_RETV(psz = RTStrCacheEnterN(hStrCache, "0123456789abcdefghijklmnopqrstuvwxyz", 16));
    RTTESTI_CHECK_RETV(strcmp(psz, "0123456789abcdef") == 0);
    RTTESTI_CHECK_RETV(RTStrCacheLength(psz) == strlen("0123456789abcdef"));
    RTTESTI_CHECK_RETV(RTStrCacheRelease(hStrCache, psz) == 0);

    /* String referencing. */
    char szTest[4096+16];
    memset(szTest, 'a', sizeof(szTest));
    char szTest2[4096+16];
    memset(szTest2, 'f', sizeof(szTest));
    for (int32_t i = 4096; i > 3; i /= 3)
    {
        void *pv2;
        RTTESTI_CHECK_RETV(psz = RTStrCacheEnterN(hStrCache, szTest, i));
        RTTESTI_CHECK_MSG_RETV((pv2 = ASMMemFirstMismatchingU8(psz, i, 'a')) == NULL && !psz[i], ("i=%#x psz=%p off=%#x\n", i, psz, (uintptr_t)pv2 - (uintptr_t)psz));
        RTTESTI_CHECK(RTStrCacheRetain(psz) == 2);
        RTTESTI_CHECK(RTStrCacheRetain(psz) == 3);
        RTTESTI_CHECK(RTStrCacheRetain(psz) == 4);
        RTTESTI_CHECK_MSG_RETV((pv2 = ASMMemFirstMismatchingU8(psz, i, 'a')) == NULL && !psz[i], ("i=%#x psz=%p off=%#x\n", i, psz, (uintptr_t)pv2 - (uintptr_t)psz));
        RTTESTI_CHECK(RTStrCacheRelease(hStrCache, psz) == 3);
        RTTESTI_CHECK_MSG_RETV((pv2 = ASMMemFirstMismatchingU8(psz, i, 'a')) == NULL && !psz[i], ("i=%#x psz=%p off=%#x\n", i, psz, (uintptr_t)pv2 - (uintptr_t)psz));
        RTTESTI_CHECK(RTStrCacheRetain(psz) == 4);
        RTTESTI_CHECK(RTStrCacheRetain(psz) == 5);
        RTTESTI_CHECK(RTStrCacheRetain(psz) == 6);
        RTTESTI_CHECK(RTStrCacheRelease(hStrCache, psz) == 5);
        RTTESTI_CHECK(RTStrCacheRelease(hStrCache, psz) == 4);
        RTTESTI_CHECK_MSG_RETV((pv2 = ASMMemFirstMismatchingU8(psz, i, 'a')) == NULL && !psz[i], ("i=%#x psz=%p off=%#x\n", i, psz, (uintptr_t)pv2 - (uintptr_t)psz));

        for (uint32_t cRefs = 3;; cRefs--)
        {
            RTTESTI_CHECK(RTStrCacheRelease(hStrCache, psz) == cRefs);
            if (cRefs == 0)
                break;
            RTTESTI_CHECK_MSG_RETV((pv2 = ASMMemFirstMismatchingU8(psz, i, 'a')) == NULL && !psz[i], ("i=%#x psz=%p off=%#x cRefs=%d\n", i, psz, (uintptr_t)pv2 - (uintptr_t)psz, cRefs));
            for (uint32_t j = 0; j < 42; j++)
            {
                const char *psz2;
                RTTESTI_CHECK_RETV(psz2 = RTStrCacheEnterN(hStrCache, szTest2, i));
                RTTESTI_CHECK_RETV(psz2 != psz);
                RTTESTI_CHECK(RTStrCacheRelease(hStrCache, psz2) == 0);
                RTTESTI_CHECK_MSG_RETV((pv2 = ASMMemFirstMismatchingU8(psz, i, 'a')) == NULL && !psz[i], ("i=%#x psz=%p off=%#x cRefs=%d\n", i, psz, (uintptr_t)pv2 - (uintptr_t)psz, cRefs));
            }
        }
    }

    /* Lots of allocations. */
    memset(szTest, 'b', sizeof(szTest));
    memset(szTest2, 'e', sizeof(szTest));
    const char *pszTest1Rets[4096 + 16];
    const char *pszTest2Rets[4096 + 16];
    for (uint32_t i = 1; i < RT_ELEMENTS(pszTest1Rets); i++)
    {
        RTTESTI_CHECK(pszTest1Rets[i] = RTStrCacheEnterN(hStrCache, szTest, i));
        RTTESTI_CHECK(strlen(pszTest1Rets[i]) == i);
        RTTESTI_CHECK(pszTest2Rets[i] = RTStrCacheEnterN(hStrCache, szTest2, i));
        RTTESTI_CHECK(strlen(pszTest2Rets[i]) == i);
    }

    if (RTStrCacheIsRealImpl())
    {
        for (uint32_t i = 1; i < RT_ELEMENTS(pszTest1Rets); i++)
        {
            uint32_t cRefs;
            const char *psz1, *psz2;
            RTTESTI_CHECK((psz1 = RTStrCacheEnterN(hStrCache, szTest,  i)) == pszTest1Rets[i]);
            RTTESTI_CHECK((psz2 = RTStrCacheEnterN(hStrCache, szTest2, i)) == pszTest2Rets[i]);
            RTTESTI_CHECK_MSG((cRefs = RTStrCacheRelease(hStrCache, psz1)) == 1, ("cRefs=%#x i=%#x\n", cRefs, i));
            RTTESTI_CHECK_MSG((cRefs = RTStrCacheRelease(hStrCache, psz2)) == 1, ("cRefs=%#x i=%#x\n", cRefs, i));
        }
    }

    for (uint32_t i = 1; i < RT_ELEMENTS(pszTest1Rets); i++)
    {
        uint32_t cRefs;
        RTTESTI_CHECK(strlen(pszTest1Rets[i]) == i);
        RTTESTI_CHECK_MSG((cRefs = RTStrCacheRelease(hStrCache, pszTest1Rets[i])) == 0, ("cRefs=%#x i=%#x\n", cRefs, i));
        RTTESTI_CHECK(strlen(pszTest2Rets[i]) == i);
        RTTESTI_CHECK_MSG((cRefs = RTStrCacheRelease(hStrCache, pszTest2Rets[i])) == 0, ("cRefs=%#x i=%#x\n", cRefs, i));
    }
}
Exemple #2
0
/**
 * 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(ASMMemFirstMismatchingU32(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(ASMMemIsZero((uint8_t *)pv + sizeof(szTest), cb));
        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 = ASMMemFirstMismatchingU8(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 = ASMMemFirstMismatchingU8(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 = ASMMemFirstMismatchingU8(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 = ASMMemFirstMismatchingU8(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 = ASMMemFirstMismatchingU8(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 = ASMMemFirstMismatchingU8(pv, i, 'a')) == NULL, ("i=%#x pv=%p off=%#x cRefs=%d\n", i, pv, (uintptr_t)pv2 - (uintptr_t)pv, cRefs));
            }
        }
    }
}
Exemple #3
0
/**
 * Internal free.
 */
RTDECL(void) rtR3MemFree(const char *pszOp, RTMEMTYPE enmType, void *pv, void *pvCaller, RT_SRC_POS_DECL)
{
    NOREF(enmType); RT_SRC_POS_NOREF();

    /*
     * Simple case.
     */
    if (!pv)
        return;

    /*
     * Check watch points.
     */
    for (unsigned i = 0; i < RT_ELEMENTS(gapvRTMemFreeWatch); i++)
        if (gapvRTMemFreeWatch[i] == pv)
            RTAssertDoPanic();

#ifdef RTALLOC_EFENCE_TRACE
    /*
     * Find the block.
     */
    PRTMEMBLOCK pBlock = rtmemBlockRemove(pv);
    if (pBlock)
    {
        if (gfRTMemFreeLog)
            RTLogPrintf("RTMem %s: pv=%p pvCaller=%p cbUnaligned=%#x\n", pszOp, pv, pvCaller, pBlock->cbUnaligned);

# ifdef RTALLOC_EFENCE_NOMAN_FILLER
        /*
         * Check whether the no man's land is untouched.
         */
#  ifdef RTALLOC_EFENCE_IN_FRONT
        void *pvWrong = ASMMemFirstMismatchingU8((char *)pv + pBlock->cbUnaligned,
                                                 RT_ALIGN_Z(pBlock->cbAligned, PAGE_SIZE) - pBlock->cbUnaligned,
                                                 RTALLOC_EFENCE_NOMAN_FILLER);
#  else
        /* Alignment must match allocation alignment in rtMemAlloc(). */
        void  *pvWrong = ASMMemFirstMismatchingU8((char *)pv + pBlock->cbUnaligned,
                                                  pBlock->cbAligned - pBlock->cbUnaligned,
                                                  RTALLOC_EFENCE_NOMAN_FILLER);
        if (pvWrong)
            RTAssertDoPanic();
        pvWrong = ASMMemFirstMismatchingU8((void *)((uintptr_t)pv & ~(uintptr_t)PAGE_OFFSET_MASK),
                                           RT_ALIGN_Z(pBlock->cbAligned, PAGE_SIZE) - pBlock->cbAligned,
                                           RTALLOC_EFENCE_NOMAN_FILLER);
#  endif
        if (pvWrong)
            RTAssertDoPanic();
# endif

# ifdef RTALLOC_EFENCE_FREE_FILL
        /*
         * Fill the user part of the block.
         */
        memset(pv, RTALLOC_EFENCE_FREE_FILL, pBlock->cbUnaligned);
# endif

# if defined(RTALLOC_EFENCE_FREE_DELAYED) && RTALLOC_EFENCE_FREE_DELAYED > 0
        /*
         * We're doing delayed freeing.
         * That means we'll expand the E-fence to cover the entire block.
         */
        int rc = RTMemProtect(pv, pBlock->cbAligned, RTMEM_PROT_NONE);
        if (RT_SUCCESS(rc))
        {
            /*
             * Insert it into the free list and process pending frees.
             */
            rtmemBlockDelayInsert(pBlock);
            while ((pBlock = rtmemBlockDelayRemove()) != NULL)
            {
                pv = pBlock->Core.Key;
#  ifdef RTALLOC_EFENCE_IN_FRONT
                void  *pvBlock = (char *)pv - RTALLOC_EFENCE_SIZE;
#  else
                void  *pvBlock = (void *)((uintptr_t)pv & ~(uintptr_t)PAGE_OFFSET_MASK);
#  endif
                size_t cbBlock = RT_ALIGN_Z(pBlock->cbAligned, PAGE_SIZE) + RTALLOC_EFENCE_SIZE;
                rc = RTMemProtect(pvBlock, cbBlock, RTMEM_PROT_READ | RTMEM_PROT_WRITE);
                if (RT_SUCCESS(rc))
                    RTMemPageFree(pvBlock, RT_ALIGN_Z(pBlock->cbAligned, PAGE_SIZE) + RTALLOC_EFENCE_SIZE);
                else
                    rtmemComplain(pszOp, "RTMemProtect(%p, %#x, RTMEM_PROT_READ | RTMEM_PROT_WRITE) -> %d\n", pvBlock, cbBlock, rc);
                rtmemBlockFree(pBlock);
            }
        }
        else
            rtmemComplain(pszOp, "Failed to expand the efence of pv=%p cb=%d, rc=%d.\n", pv, pBlock, rc);

# else /* !RTALLOC_EFENCE_FREE_DELAYED */

        /*
         * Turn of the E-fence and free it.
         */
#  ifdef RTALLOC_EFENCE_IN_FRONT
        void *pvBlock = (char *)pv - RTALLOC_EFENCE_SIZE;
        void *pvEFence = pvBlock;
#  else
        void *pvBlock = (void *)((uintptr_t)pv & ~(uintptr_t)PAGE_OFFSET_MASK);
        void *pvEFence = (char *)pv + pBlock->cb;
#  endif
        int rc = RTMemProtect(pvEFence, RTALLOC_EFENCE_SIZE, RTMEM_PROT_READ | RTMEM_PROT_WRITE);
        if (RT_SUCCESS(rc))
            RTMemPageFree(pvBlock, RT_ALIGN_Z(pBlock->cbAligned, PAGE_SIZE) + RTALLOC_EFENCE_SIZE);
        else
            rtmemComplain(pszOp, "RTMemProtect(%p, %#x, RTMEM_PROT_READ | RTMEM_PROT_WRITE) -> %d\n", pvEFence, RTALLOC_EFENCE_SIZE, rc);
        rtmemBlockFree(pBlock);

# endif /* !RTALLOC_EFENCE_FREE_DELAYED */
    }
    else
        rtmemComplain(pszOp, "pv=%p not found! Incorrect free!\n", pv);

#else /* !RTALLOC_EFENCE_TRACE */

    /*
     * We have no size tracking, so we're not doing any freeing because
     * we cannot if the E-fence is after the block.
     * Let's just expand the E-fence to the first page of the user bit
     * since we know that it's around.
     */
    int rc = RTMemProtect((void *)((uintptr_t)pv & ~(uintptr_t)PAGE_OFFSET_MASK), PAGE_SIZE, RTMEM_PROT_NONE);
    if (RT_FAILURE(rc))
        rtmemComplain(pszOp, "RTMemProtect(%p, PAGE_SIZE, RTMEM_PROT_NONE) -> %d\n", (void *)((uintptr_t)pv & ~(uintptr_t)PAGE_OFFSET_MASK), rc);
#endif /* !RTALLOC_EFENCE_TRACE */
}