VirtualBox

Ignore:
Timestamp:
Jun 15, 2009 1:52:07 AM (15 years ago)
Author:
vboxsync
Message:

IPRT: Wrote the body for tstRTMemPool and fixed two isseus in mempool-generic.cpp: 1. messed up the linked list a little bit (as always). 2. don't assert on volatile pointers without owning the lock as someone else might change them while you're testing their validity and reading them multiple times.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/testcase/tstRTMemPool.cpp

    r20562 r20575  
    3434#include <iprt/mempool.h>
    3535
     36#include <iprt/asm.h>
    3637#include <iprt/err.h>
    3738#include <iprt/initterm.h>
    38 #include <iprt/stdarg.h>
    3939#include <iprt/string.h>
    4040#include <iprt/test.h>
    41 
     41#include <iprt/thread.h>
     42#include <iprt/rand.h>
     43
     44
     45/*******************************************************************************
     46*   Global Variables                                                           *
     47*******************************************************************************/
     48/** The test handle */
     49static RTTEST       g_hTest;
     50/** Memory pool for tst4. */
     51static RTMEMPOOL    g_hMemPool4;
     52
     53
     54/**
     55 * Basic API checks.
     56 * We'll return if any of these fails.
     57 */
     58static void tst1(RTMEMPOOL hMemPool)
     59{
     60    void *pv;
     61
     62    /* Normal alloc. */
     63    RTTESTI_CHECK_RETV(pv = RTMemPoolAlloc(hMemPool, 1));
     64    RTTESTI_CHECK_RETV(RTMemPoolRelease(hMemPool, pv) == 0);
     65
     66    RTTESTI_CHECK_RETV(pv = RTMemPoolAlloc(hMemPool, 0));
     67    RTTESTI_CHECK_RETV(RTMemPoolRelease(hMemPool, pv) == 0);
     68
     69    /* Zeroed allocation. */
     70    for (uint32_t i = 0; i < 512; i++)
     71    {
     72        RTTESTI_CHECK_RETV(pv = RTMemPoolAllocZ(hMemPool, 1024));
     73        RTTESTI_CHECK(ASMMemIsAllU32(pv, 1024, 0) == NULL);
     74        memset(pv, 'a', 1024);
     75        RTTESTI_CHECK_RETV(RTMemPoolRelease(hMemPool, pv) == 0);
     76    }
     77
     78    RTTESTI_CHECK_RETV(pv = RTMemPoolAllocZ(hMemPool, 0));
     79    RTTESTI_CHECK_RETV(RTMemPoolRelease(hMemPool, pv) == 0);
     80
     81    /* Duped allocation. */
     82    static const char szTest[] = "test string abcdef";
     83    RTTESTI_CHECK_RETV(pv = RTMemPoolDup(hMemPool, szTest, sizeof(szTest)));
     84    RTTESTI_CHECK(memcmp(pv, szTest, sizeof(szTest)) == 0);
     85    RTTESTI_CHECK_RETV(RTMemPoolRelease(hMemPool, pv) == 0);
     86
     87    for (uint32_t i = 0; i < 512; i++)
     88    {
     89        size_t const cb = 256 - sizeof(szTest);
     90        RTTESTI_CHECK_RETV(pv = RTMemPoolDupEx(hMemPool, szTest, sizeof(szTest), cb));
     91        RTTESTI_CHECK(memcmp(pv, szTest, sizeof(szTest)) == 0);
     92        RTTESTI_CHECK(ASMMemIsAll8((uint8_t *)pv + sizeof(szTest), cb, 0) == NULL);
     93        memset(pv, 'b', sizeof(szTest) + cb);
     94        RTTESTI_CHECK_RETV(RTMemPoolRelease(hMemPool, pv) == 0);
     95    }
     96
     97    /* Reallocation */
     98    RTTESTI_CHECK_RETV(pv = RTMemPoolRealloc(hMemPool, NULL, 1));
     99    RTTESTI_CHECK_RETV(pv = RTMemPoolRealloc(hMemPool, pv, 2));
     100    RTTESTI_CHECK_RETV(RTMemPoolRelease(hMemPool, pv) == 0);
     101
     102    RTTESTI_CHECK_RETV(pv = RTMemPoolAlloc(hMemPool, 42));
     103    RTTESTI_CHECK_RETV(pv = RTMemPoolRealloc(hMemPool, pv, 32));
     104    RTTESTI_CHECK_RETV(RTMemPoolRelease(hMemPool, pv) == 0);
     105
     106    RTTESTI_CHECK_RETV(pv = RTMemPoolRealloc(hMemPool, NULL, 128));
     107    RTTESTI_CHECK_RETV(pv = RTMemPoolRealloc(hMemPool, pv, 256));
     108    RTTESTI_CHECK_RETV(RTMemPoolRealloc(hMemPool, pv, 0) == NULL);
     109
     110    /* Free (a bit hard to test) */
     111    RTMemPoolFree(hMemPool, NULL);
     112    RTMemPoolFree(hMemPool, RTMemPoolAlloc(hMemPool, 42));
     113
     114    /* Memory referencing. */
     115    for (uint32_t i = 1; i <= 4096; i *= 3)
     116    {
     117        void *pv2;
     118        RTTESTI_CHECK_RETV(pv = RTMemPoolAlloc(hMemPool, i));
     119        memset(pv, 'a', i);
     120        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));
     121        RTTESTI_CHECK(RTMemPoolRetain(pv) == 2);
     122        RTTESTI_CHECK(RTMemPoolRetain(pv) == 3);
     123        RTTESTI_CHECK(RTMemPoolRetain(pv) == 4);
     124        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));
     125        RTTESTI_CHECK(RTMemPoolRelease(hMemPool, pv) == 3);
     126        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));
     127        RTTESTI_CHECK(RTMemPoolRetain(pv) == 4);
     128        RTTESTI_CHECK(RTMemPoolRetain(pv) == 5);
     129        RTTESTI_CHECK(RTMemPoolRetain(pv) == 6);
     130        RTTESTI_CHECK(RTMemPoolRelease(NIL_RTMEMPOOL, pv) == 5);
     131        RTTESTI_CHECK(RTMemPoolRelease(NIL_RTMEMPOOL, pv) == 4);
     132        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));
     133
     134        for (uint32_t cRefs = 3;; cRefs--)
     135        {
     136            RTTESTI_CHECK(RTMemPoolRelease(hMemPool, pv) == cRefs);
     137            if (cRefs == 0)
     138                break;
     139            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));
     140            for (uint32_t j = 0; j < 42; j++)
     141            {
     142                RTTESTI_CHECK_RETV(pv2 = RTMemPoolAlloc(hMemPool, i));
     143                RTTESTI_CHECK_RETV(pv2 != pv);
     144                memset(pv2, 'f', i);
     145                RTTESTI_CHECK(RTMemPoolRelease(hMemPool, pv2) == 0);
     146                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));
     147            }
     148        }
     149    }
     150}
     151
     152
     153/**
     154 * Test automatic cleanup upon destruction.
     155 */
     156static void tst3(void)
     157{
     158    RTTestISub("Destroy non-empty pool");
     159
     160    /*
     161     * Nothing freed.
     162     */
     163    RTMEMPOOL hMemPool;
     164    RTTESTI_CHECK_RC_RETV(RTMemPoolCreate(&hMemPool, "test 3a"), VINF_SUCCESS);
     165    RTTESTI_CHECK_RETV(RTMemPoolAlloc(hMemPool, 10));
     166    RTTESTI_CHECK_RETV(RTMemPoolAlloc(hMemPool, 20));
     167    RTTESTI_CHECK_RETV(RTMemPoolAlloc(hMemPool, 40));
     168    RTTESTI_CHECK_RETV(RTMemPoolAlloc(hMemPool, 80));
     169    RTTESTI_CHECK_RC_RETV(RTMemPoolDestroy(hMemPool), VINF_SUCCESS);
     170
     171    /*
     172     * Pseudo random freeing to test list maintaince.
     173     */
     174    RTRAND hRand;
     175    RTTESTI_CHECK_RC_OK_RETV(RTRandAdvCreateParkMiller(&hRand));
     176
     177    for (uint32_t i = 0; i < 10; i++)
     178    {
     179        RTTESTI_CHECK_RC_RETV(RTMemPoolCreate(&hMemPool, "test 3b"), VINF_SUCCESS);
     180
     181        void *apvHistory[256];
     182        RT_ZERO(apvHistory);
     183
     184        uint32_t cBlocks = 0;
     185        uint32_t j;
     186        for (j = 0; j < RT_ELEMENTS(apvHistory) - i * 7; j++)
     187        {
     188            RTTESTI_CHECK_RETV(apvHistory[j] = RTMemPoolAlloc(hMemPool, j));
     189            memset(apvHistory[j], 'a', j);
     190            cBlocks++;
     191
     192            if (RTRandAdvU32Ex(hRand, 0, 4) == 4)
     193            {
     194                uint32_t iFree = RTRandAdvU32Ex(hRand, 0, j);
     195                cBlocks -= apvHistory[iFree] != NULL;
     196                RTTESTI_CHECK_RETV(RTMemPoolRelease(hMemPool, apvHistory[iFree]) == 0);
     197                apvHistory[iFree] = NULL;
     198            }
     199        }
     200
     201        RTTESTI_CHECK_RC_RETV(RTMemPoolDestroy(hMemPool), VINF_SUCCESS);
     202        RTTestIPrintf(RTTESTLVL_INFO, "cBlocks=%u j=%u\n", cBlocks, j);
     203    }
     204
     205    RTRandAdvDestroy(hRand);
     206}
     207
     208
     209/** Thread function for tst4. */
     210static DECLCALLBACK(int) tst4Thread(RTTHREAD hSelf, void *pvArg)
     211{
     212//    uint32_t    iThread  = (uint32_t)(uintptr_t)pvArg;
     213    RTMEMPOOL   hMemPool = g_hMemPool4;
     214
     215    /* setup. */
     216    RTTestSetDefault(g_hTest, NULL);
     217
     218    /* wait for the kick-off */
     219    RTThreadUserWait(hSelf, RT_INDEFINITE_WAIT);
     220
     221    /* do the work. */
     222    for (uint32_t i = 0; i < 1024; i++)
     223    {
     224        void *apvHistory[256];
     225        RT_ZERO(apvHistory);
     226        uint32_t j;
     227        for (j = 0; j < RT_ELEMENTS(apvHistory) - (i % 200); j++)
     228            RTTESTI_CHECK_RET(apvHistory[j] = RTMemPoolAlloc(hMemPool, (i & 15) + (j & 63)), VERR_NO_MEMORY);
     229        for (uint32_t k = i & 7; k < j; k += 3)
     230        {
     231            RTTESTI_CHECK_RET(RTMemPoolRelease(hMemPool, apvHistory[k]) == 0, VERR_INTERNAL_ERROR);
     232            apvHistory[k] = NULL;
     233        }
     234        while (j-- > 0)
     235            RTTESTI_CHECK_RET(RTMemPoolRelease(hMemPool, apvHistory[j]) == 0, VERR_INTERNAL_ERROR);
     236    }
     237
     238    return VINF_SUCCESS;
     239}
     240
     241/** sub test */
     242static void tst4Sub(uint32_t cThreads)
     243{
     244    RTTestISubF("Serialization - %u threads", cThreads);
     245    RTMEMPOOL hMemPool;
     246    RTTESTI_CHECK_RC_RETV(RTMemPoolCreate(&hMemPool, "test 2a"), VINF_SUCCESS);
     247    g_hMemPool4 = hMemPool;
     248
     249    PRTTHREAD pahThreads = (PRTTHREAD)RTMemPoolAlloc(hMemPool, cThreads * sizeof(RTTHREAD));
     250    RTTESTI_CHECK(pahThreads);
     251    if (pahThreads)
     252    {
     253        /* start them. */
     254        for (uint32_t i = 0; i < cThreads; i++)
     255        {
     256            int rc = RTThreadCreateF(&pahThreads[i], tst4Thread, (void *)(uintptr_t)i, 0,
     257                                     RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "tst4-%u/%u", i, cThreads);
     258            RTTESTI_CHECK_RC_OK(rc);
     259            if (RT_FAILURE(rc))
     260                pahThreads[i] = NIL_RTTHREAD;
     261        }
     262        RTThreadYield();
     263
     264        /* kick them off. */
     265        for (uint32_t i = 0; i < cThreads; i++)
     266            if (pahThreads[i] != NIL_RTTHREAD)
     267                RTTESTI_CHECK_RC_OK(RTThreadUserSignal(pahThreads[i]));
     268
     269        /* wait for them. */
     270        for (uint32_t i = 0; i < cThreads; i++)
     271            if (pahThreads[i] != NIL_RTTHREAD)
     272            {
     273                int rc = RTThreadWait(pahThreads[i], 2*60*1000, NULL);
     274                RTTESTI_CHECK_RC_OK(rc);
     275            }
     276    }
     277
     278    RTTESTI_CHECK_RC(RTMemPoolDestroy(hMemPool), VINF_SUCCESS);
     279}
     280
     281
     282/**
     283 * Starts a bunch of threads beating on a pool to test serialization.
     284 */
     285static void tst4(void)
     286{
     287    /*
     288     * Test it with a few different thread counts.
     289     */
     290    tst4Sub(1);
     291    tst4Sub(2);
     292    tst4Sub(3);
     293    tst4Sub(4);
     294    tst4Sub(8);
     295    tst4Sub(16);
     296}
    42297
    43298
     
    51306    if (RT_FAILURE(rc))
    52307        return 1;
     308    g_hTest = hTest;
    53309    RTTestBanner(hTest);
    54310
     
    56312     * Smoke tests using first the default and then a custom pool.
    57313     */
    58 
    59 
     314    RTTestSub(hTest, "Smoke test on default pool");
     315    tst1(RTMEMPOOL_DEFAULT);
     316
     317    RTTestSub(hTest, "Smoke test on custom pool");
     318    RTMEMPOOL hMemPool;
     319    RTTESTI_CHECK_RC(rc = RTMemPoolCreate(&hMemPool, "test 2a"), VINF_SUCCESS);
     320    if (RT_SUCCESS(rc))
     321        RTTESTI_CHECK_RC(rc = RTMemPoolDestroy(hMemPool), VINF_SUCCESS);
     322    RTTESTI_CHECK_RC(rc = RTMemPoolDestroy(NIL_RTMEMPOOL), VINF_SUCCESS);
     323    RTTESTI_CHECK_RC(rc = RTMemPoolDestroy(RTMEMPOOL_DEFAULT), VINF_SUCCESS);
     324    RTTESTI_CHECK_RC(rc = RTMemPoolDestroy(RTMEMPOOL_DEFAULT), VINF_SUCCESS);
     325
     326    RTTESTI_CHECK_RC(rc = RTMemPoolCreate(&hMemPool, "test 2b"), VINF_SUCCESS);
     327    if (RT_SUCCESS(rc))
     328    {
     329        tst1(hMemPool);
     330        RTTESTI_CHECK_RC(rc = RTMemPoolDestroy(hMemPool), VINF_SUCCESS);
     331    }
     332
     333    /*
     334     * Further tests.
     335     */
     336    tst3();
     337    tst4();
    60338
    61339    /*
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette