VirtualBox

儲存庫 vbox 的更動 10788


忽略:
時間撮記:
2008-7-21 下午04:44:33 (16 年 以前)
作者:
vboxsync
訊息:

IPRT: Implemented the context variant of the handle table.

位置:
trunk
檔案:
修改 3 筆資料
複製 1 筆資料

圖例:

未更動
新增
刪除
  • trunk/include/iprt/handletable.h

    r10768 r10788  
    9898 * If not specfied the caller will have to take care of that. */
    9999#define RTHANDLETABLE_FLAGS_LOCKED      RT_BIT_32(1)
     100/** The mask of valid flags. */
     101#define RTHANDLETABLE_FLAGS_MASK        UINT32_C(0x00000003)
    100102/* @} */
    101103
     
    116118 *                          first handle to be returned.
    117119 * @param   cMax            The max number of handles. When exceeded the RTHandleTableAlloc
    118  *                          or RTHandleTableAllocWithCtx calls will fail.
     120 *                          or RTHandleTableAllocWithCtx calls will fail. Note that this
     121 *                          number will be rounded up to a multiple of the sub-table size,
     122 *                          or if it's too close to UINT32_MAX it will be rounded down.
    119123 * @param   pfnRetain       Optional retain callback that will be called from behind the
    120124 *                          lock (if any) during lookup.
     
    127131 * A simplified version of the RTHandleTableCreateEx API.
    128132 *
    129  * It assumes a max of 65534 handles with 1 being the base. The table
    130  * serialized (RTHANDLETABLE_FLAGS_LOCKED).
     133 * It assumes a max of about 64K handles with 1 being the base. The table
     134 * access will serialized (RTHANDLETABLE_FLAGS_LOCKED).
    131135 *
    132136 * @returns IPRT status code and *phHandleTable.
  • trunk/src/VBox/Runtime/common/misc/handletable.cpp

    r10768 r10788  
    3939#include <iprt/param.h>
    4040#include <iprt/string.h>
     41#include <iprt/asm.h>
    4142#include "internal/magics.h"
    4243
     
    5960#define RTHT_SET_FREE_IDX(pFree, idx) \
    6061    do { \
    61         (pFree)->iNext = ((uintptr_t)(idx) << 2) | 3; \
     62        (pFree)->iNext = ((uintptr_t)((uint32_t)(idx)) << 2) | 3U; \
    6263    } while (0)
    6364
     
    99100typedef struct RTHTENTRYCTX
    100101{
     102    /** The object. */
     103    void *pvObj;
    101104    /** The context. */
    102105    void *pvCtx;
    103     /** The object. */
    104     void *pvObj;
    105106} RTHTENTRYCTX;
    106107/** Pointer to a handle table entry, context variant. */
     
    126127AssertCompile(sizeof(RTHTENTRYFREE) <= sizeof(RTHTENTRY));
    127128AssertCompile(sizeof(RTHTENTRYFREE) <= sizeof(RTHTENTRYCTX));
     129AssertCompileMemberOffset(RTHTENTRYFREE, iNext, 0);
     130AssertCompileMemberOffset(RTHTENTRY,     pvObj, 0);
     131AssertCompileMemberOffset(RTHTENTRYCTX,  pvObj, 0);
    128132
    129133
     
    139143    /** The base handle value (i.e. the first handle). */
    140144    uint32_t uBase;
    141     /** The current number of handles.
    142      * This indirectly gives the size of the first level lookup table. */
     145    /** The current number of handle table entries. */
    143146    uint32_t cCur;
    144147    /** The spinlock handle (NIL if RTHANDLETABLE_FLAGS_LOCKED wasn't used). */
     
    165168
    166169
    167 
    168 /**
    169  * Looks up a simple handle.
     170/**
     171 * Looks up a simple index.
    170172 *
    171173 * @returns Pointer to the handle table entry on success, NULL on failure.
    172174 * @param   pThis           The handle table structure.
    173  * @param   h               The handle to look up.
    174  */
    175 DECLINLINE(PRTHTENTRY) rtHandleTableLookupSimple(PRTHANDLETABLEINT pThis, uint32_t h)
    176 {
    177     uint32_t i = h - pThis->uBase;
     175 * @param   i               The index to look up.
     176 */
     177DECLINLINE(PRTHTENTRY) rtHandleTableLookupSimpleIdx(PRTHANDLETABLEINT pThis, uint32_t i)
     178{
    178179    if (i < pThis->cCur)
    179180    {
     
    182183            return &paTable[i % RTHT_LEVEL2_ENTRIES];
    183184    }
    184 
    185185    return NULL;
    186186}
     
    188188
    189189/**
    190  * Looks up a context handle.
     190 * Looks up a simple handle.
    191191 *
    192192 * @returns Pointer to the handle table entry on success, NULL on failure.
     
    194194 * @param   h               The handle to look up.
    195195 */
    196 DECLINLINE(PRTHTENTRYCTX) rtHandleTableLookupWithCtx(PRTHANDLETABLEINT pThis, uint32_t h)
    197 {
    198     uint32_t i = h - pThis->uBase;
     196DECLINLINE(PRTHTENTRY) rtHandleTableLookupSimple(PRTHANDLETABLEINT pThis, uint32_t h)
     197{
     198    return rtHandleTableLookupSimpleIdx(pThis, h - pThis->uBase);
     199}
     200
     201
     202/**
     203 * Looks up a context index.
     204 *
     205 * @returns Pointer to the handle table entry on success, NULL on failure.
     206 * @param   pThis           The handle table structure.
     207 * @param   i               The index to look up.
     208 */
     209DECLINLINE(PRTHTENTRYCTX) rtHandleTableLookupWithCtxIdx(PRTHANDLETABLEINT pThis, uint32_t i)
     210{
    199211    if (i < pThis->cCur)
    200212    {
     
    203215            return &paTable[i % RTHT_LEVEL2_ENTRIES];
    204216    }
    205 
    206217    return NULL;
    207218}
    208219
    209220
     221/**
     222 * Looks up a context handle.
     223 *
     224 * @returns Pointer to the handle table entry on success, NULL on failure.
     225 * @param   pThis           The handle table structure.
     226 * @param   h               The handle to look up.
     227 */
     228DECLINLINE(PRTHTENTRYCTX) rtHandleTableLookupWithCtx(PRTHANDLETABLEINT pThis, uint32_t h)
     229{
     230    return rtHandleTableLookupWithCtxIdx(pThis, h - pThis->uBase);
     231}
     232
     233
     234/**
     235 * Locks the handle table.
     236 *
     237 * @param   pThis           The handle table structure.
     238 * @param   pTmp            The spinlock temp variable.
     239 */
    210240DECLINLINE(void) rtHandleTableLock(PRTHANDLETABLEINT pThis, PRTSPINLOCKTMP pTmp)
     241{
     242    if (pThis->hSpinlock != NIL_RTSPINLOCK)
     243    {
     244        RTSPINLOCKTMP const Tmp = RTSPINLOCKTMP_INITIALIZER;
     245        *pTmp = Tmp;
     246        RTSpinlockAcquire(pThis->hSpinlock, pTmp);
     247    }
     248}
     249
     250
     251/**
     252 * Locks the handle table.
     253 *
     254 * @param   pThis           The handle table structure.
     255 * @param   pTmp            The spinlock temp variable.
     256 */
     257DECLINLINE(void) rtHandleTableUnlock(PRTHANDLETABLEINT pThis, PRTSPINLOCKTMP pTmp)
    211258{
    212259    if (pThis->hSpinlock != NIL_RTSPINLOCK)
     
    215262
    216263
    217 DECLINLINE(void) rtHandleTableUnlock(PRTHANDLETABLEINT pThis, PRTSPINLOCKTMP pTmp)
    218 {
     264RTDECL(int) RTHandleTableCreateEx(PRTHANDLETABLE phHandleTable, uint32_t fFlags, uint32_t uBase, uint32_t cMax,
     265                                  PFNRTHANDLETABLERETAIN pfnRetain, void *pvUser)
     266{
     267    /*
     268     * Validate input.
     269     */
     270    AssertPtrReturn(phHandleTable, VERR_INVALID_POINTER);
     271    *phHandleTable = NIL_RTHANDLETABLE;
     272    AssertPtrNullReturn(pfnRetain, VERR_INVALID_POINTER);
     273    AssertReturn(!(fFlags & ~RTHANDLETABLE_FLAGS_MASK), VERR_INVALID_PARAMETER);
     274    AssertReturn(cMax > 0, VERR_INVALID_PARAMETER);
     275    AssertReturn(UINT32_MAX - cMax >= uBase, VERR_INVALID_PARAMETER);
     276
     277    /*
     278     * Adjust the cMax value so it is a multiple of the 2nd level tables.
     279     */
     280    if (cMax >= UINT32_MAX - RTHT_LEVEL2_ENTRIES)
     281        cMax = UINT32_MAX - RTHT_LEVEL2_ENTRIES + 1;
     282    cMax = ((cMax + RTHT_LEVEL2_ENTRIES - 1) / RTHT_LEVEL2_ENTRIES) * RTHT_LEVEL2_ENTRIES;
     283
     284    uint32_t const cLevel1 = cMax / RTHT_LEVEL2_ENTRIES;
     285    Assert(cLevel1 * RTHT_LEVEL2_ENTRIES == cMax);
     286
     287    /*
     288     * Allocate the structure, include the 1st level lookup table
     289     * if it's below the threshold size.
     290     */
     291    size_t cb = sizeof(RTHANDLETABLEINT);
     292    if (cLevel1 < RTHT_LEVEL1_DYN_ALLOC_THRESHOLD)
     293        cb = RT_ALIGN(cb, sizeof(void *)) + cLevel1 * sizeof(void *);
     294    PRTHANDLETABLEINT pThis = (PRTHANDLETABLEINT)RTMemAllocZ(cb);
     295    if (!pThis)
     296        return VERR_NO_MEMORY;
     297
     298    /*
     299     * Initialize it.
     300     */
     301    pThis->u32Magic = RTHANDLETABLE_MAGIC;
     302    pThis->fFlags = fFlags;
     303    pThis->uBase = uBase;
     304    pThis->cCur = 0;
     305    pThis->hSpinlock = NIL_RTSPINLOCK;
     306    if (cLevel1 < RTHT_LEVEL1_DYN_ALLOC_THRESHOLD)
     307        pThis->papvLevel1 = (void **)((uint8_t *)pThis + RT_ALIGN(sizeof(*pThis), sizeof(void *)));
     308    else
     309        pThis->papvLevel1 = NULL;
     310    pThis->pfnRetain = pfnRetain;
     311    pThis->pvRetainUser = pvUser;
     312    pThis->cMax = cMax;
     313    pThis->cCurAllocated = 0;
     314    pThis->cLevel1 = cLevel1 < RTHT_LEVEL1_DYN_ALLOC_THRESHOLD ? cLevel1 : 0;
     315    pThis->iFreeHead = NIL_RTHT_INDEX;
     316    pThis->iFreeTail = NIL_RTHT_INDEX;
     317    if (fFlags & RTHANDLETABLE_FLAGS_LOCKED)
     318    {
     319        int rc = RTSpinlockCreate(&pThis->hSpinlock);
     320        if (RT_FAILURE(rc))
     321        {
     322            RTMemFree(pThis);
     323            return rc;
     324        }
     325    }
     326
     327    *phHandleTable = pThis;
     328    return VINF_SUCCESS;
     329}
     330
     331
     332RTDECL(int) RTHandleTableCreate(PRTHANDLETABLE phHandleTable)
     333{
     334    return RTHandleTableCreateEx(phHandleTable, RTHANDLETABLE_FLAGS_LOCKED, 1, 65534, NULL, NULL);
     335}
     336
     337
     338RTDECL(int) RTHandleTableDestroy(RTHANDLETABLE hHandleTable, PFNRTHANDLETABLEDELETE pfnDelete, void *pvUser)
     339{
     340    /*
     341     * Validate input, quitely ignore the NIL handle.
     342     */
     343    if (hHandleTable == NIL_RTHANDLETABLE)
     344        return VINF_SUCCESS;
     345    PRTHANDLETABLEINT pThis = (PRTHANDLETABLEINT)hHandleTable;
     346    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     347    AssertReturn(pThis->u32Magic == RTHANDLETABLE_MAGIC, VERR_INVALID_HANDLE);
     348    AssertPtrNullReturn(pfnDelete, VERR_INVALID_POINTER);
     349
     350    /*
     351     * Mark the thing as invalid / deleted.
     352     * Then kill the lock.
     353     */
     354    RTSPINLOCKTMP Tmp;
     355    rtHandleTableLock(pThis, &Tmp);
     356    ASMAtomicWriteU32(&pThis->u32Magic, ~RTHANDLETABLE_MAGIC);
     357    rtHandleTableUnlock(pThis, &Tmp);
     358
    219359    if (pThis->hSpinlock != NIL_RTSPINLOCK)
    220         RTSpinlockAcquire(pThis->hSpinlock, pTmp);
    221 }
    222 
    223 
    224 RTDECL(int)     RTHandleTableCreateEx(PRTHANDLETABLE phHandleTable, uint32_t fFlags, uint32_t uBase, uint32_t cMax,
    225                                       PFNRTHANDLETABLERETAIN pfnRetain, void *pvUser)
    226 {
    227     return VERR_NOT_IMPLEMENTED;
    228 }
    229 
    230 
    231 RTDECL(int)     RTHandleTableCreate(PRTHANDLETABLE phHandleTable)
    232 {
    233     return RTHandleTableCreateEx(phHandleTable, RTHANDLETABLE_FLAGS_LOCKED, 1, 65534, NULL, NULL);
    234 }
    235 
    236 
    237 RTDECL(int)     RTHandleTableDestroy(RTHANDLETABLE hHandleTable, PFNRTHANDLETABLEDELETE pfnDelete, void *pvUser)
    238 {
    239     return -1;
     360    {
     361        rtHandleTableLock(pThis, &Tmp);
     362        rtHandleTableUnlock(pThis, &Tmp);
     363
     364        RTSpinlockDestroy(pThis->hSpinlock);
     365        pThis->hSpinlock = NIL_RTSPINLOCK;
     366    }
     367
     368    if (pfnDelete)
     369    {
     370        /*
     371         * Walk all the tables looking for used handles.
     372         */
     373        uint32_t cLeft = pThis->cCurAllocated;
     374        if (pThis->fFlags & RTHANDLETABLE_FLAGS_CONTEXT)
     375        {
     376            for (uint32_t i1 = 0; cLeft > 0 && i1 < pThis->cLevel1; i1++)
     377            {
     378                PRTHTENTRYCTX paTable = (PRTHTENTRYCTX)pThis->papvLevel1[i1];
     379                if (paTable)
     380                    for (uint32_t i = 0; i < RTHT_LEVEL2_ENTRIES; i++)
     381                        if (!RTHT_IS_FREE(paTable[i].pvObj))
     382                        {
     383                            pfnDelete(hHandleTable, pThis->uBase + i + i1 * RTHT_LEVEL2_ENTRIES,
     384                                      paTable[i].pvObj, paTable[i].pvCtx, pvUser);
     385                            Assert(cLeft > 0);
     386                            cLeft--;
     387                        }
     388            }
     389        }
     390        else
     391        {
     392            for (uint32_t i1 = 0; cLeft > 0 && i1 < pThis->cLevel1; i1++)
     393            {
     394                PRTHTENTRY paTable = (PRTHTENTRY)pThis->papvLevel1[i1];
     395                if (paTable)
     396                    for (uint32_t i = 0; i < RTHT_LEVEL2_ENTRIES; i++)
     397                        if (!RTHT_IS_FREE(paTable[i].pvObj))
     398                        {
     399                            pfnDelete(hHandleTable, pThis->uBase + i + i1 * RTHT_LEVEL2_ENTRIES,
     400                                      paTable[i].pvObj, NULL, pvUser);
     401                            Assert(cLeft > 0);
     402                            cLeft--;
     403                        }
     404            }
     405        }
     406        Assert(!cLeft);
     407    }
     408
     409    /*
     410     * Free the memory.
     411     */
     412    for (uint32_t i1 = 0; i1 < pThis->cLevel1; i1++)
     413        if (pThis->papvLevel1[i1])
     414        {
     415            RTMemFree(pThis->papvLevel1[i1]);
     416            pThis->papvLevel1[i1] = NULL;
     417        }
     418
     419    if (pThis->cMax / RTHT_LEVEL2_ENTRIES >= RTHT_LEVEL1_DYN_ALLOC_THRESHOLD)
     420        RTMemFree(pThis->papvLevel1);
     421
     422    RTMemFree(pThis);
     423
     424    return VINF_SUCCESS;
    240425}
    241426
     
    289474    AssertReturn(pThis->u32Magic == RTHANDLETABLE_MAGIC, VERR_INVALID_HANDLE);
    290475    AssertReturn(pThis->fFlags & RTHANDLETABLE_FLAGS_CONTEXT, VERR_INVALID_FUNCTION);
    291     AssertReturn(RTHT_IS_FREE(pvObj), VERR_INVALID_PARAMETER);
     476    AssertReturn(!RTHT_IS_FREE(pvObj), VERR_INVALID_PARAMETER);
    292477    AssertPtrReturn(ph, VERR_INVALID_POINTER);
    293478    *ph = pThis->uBase - 1;
     
    296481     * Allocation loop.
    297482     */
    298     RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
     483    RTSPINLOCKTMP Tmp;
    299484    rtHandleTableLock(pThis, &Tmp);
    300485
     
    308493        if (i != NIL_RTHT_INDEX)
    309494        {
    310             PRTHTENTRYFREE pFree = (PRTHTENTRYFREE)rtHandleTableLookupWithCtx(pThis, i + pThis->uBase);
     495            PRTHTENTRYFREE pFree = (PRTHTENTRYFREE)rtHandleTableLookupWithCtxIdx(pThis, i);
    311496            Assert(pFree);
    312497            if (i == pThis->iFreeTail)
     
    340525             */
    341526            uint32_t const iLevel1 = pThis->cCur / RTHT_LEVEL2_ENTRIES;
    342             uint32_t cLevel1 = iLevel1 + 1 >= pThis->cLevel1
     527            uint32_t cLevel1 = iLevel1 >= pThis->cLevel1
    343528                             ? pThis->cLevel1 + PAGE_SIZE / sizeof(void *)
    344529                             : 0;
    345530            if (cLevel1 > pThis->cMax / RTHT_LEVEL2_ENTRIES)
    346531                cLevel1 = pThis->cMax / RTHT_LEVEL2_ENTRIES;
     532            Assert(!cLevel1 || pThis->cMax / RTHT_LEVEL2_ENTRIES >= RTHT_LEVEL1_DYN_ALLOC_THRESHOLD);
    347533
    348534            /* leave the lock (never do fancy stuff from behind a spinlock). */
     
    375561             * raced us expanding the table.
    376562             */
    377 
     563            /* deal with the 1st level lookup expansion first */
    378564            if (cLevel1)
    379565            {
     566                Assert(papvLevel1);
    380567                if (cLevel1 > pThis->cLevel1)
    381568                {
     
    383570                    memcpy(papvLevel1, pThis->papvLevel1, sizeof(void *) * pThis->cLevel1);
    384571                    memset(&papvLevel1[pThis->cLevel1], 0, sizeof(void *) * (cLevel1 - pThis->cLevel1));
     572                    pThis->cLevel1 = cLevel1;
    385573                    void **papvTmp = pThis->papvLevel1;
    386574                    pThis->papvLevel1 = papvLevel1;
     
    389577
    390578                /* free the obsolete one (outside the lock of course) */
     579                rtHandleTableUnlock(pThis, &Tmp);
     580                RTMemFree(papvLevel1);
    391581                rtHandleTableLock(pThis, &Tmp);
    392                 RTMemFree(papvLevel1);
    393                 rtHandleTableUnlock(pThis, &Tmp);
    394582            }
    395583
     
    404592                for (uint32_t i = 0; i < RTHT_LEVEL2_ENTRIES - 1; i++)
    405593                {
    406                     RTHT_SET_FREE_IDX((PRTHTENTRYFREE)&paTable[i], i + 1);
     594                    RTHT_SET_FREE_IDX((PRTHTENTRYFREE)&paTable[i], i + 1 + pThis->cCur);
    407595                    paTable[i].pvCtx = (void *)~(uintptr_t)7;
    408596                }
     
    415603                else
    416604                {
    417                     PRTHTENTRYFREE pPrev = (PRTHTENTRYFREE)rtHandleTableLookupWithCtx(pThis, pThis->iFreeTail);
     605                    PRTHTENTRYFREE pPrev = (PRTHTENTRYFREE)rtHandleTableLookupWithCtxIdx(pThis, pThis->iFreeTail);
    418606                    Assert(pPrev);
    419607                    RTHT_SET_FREE_IDX(pPrev, pThis->cCur);
     
    426614            {
    427615                /* free the table (raced someone, and we lost). */
     616                rtHandleTableUnlock(pThis, &Tmp);
     617                RTMemFree(paTable);
    428618                rtHandleTableLock(pThis, &Tmp);
    429                 RTMemFree(paTable);
    430                 rtHandleTableUnlock(pThis, &Tmp);
    431619            }
    432620
     
    452640
    453641    /* acquire the lock */
    454     RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
     642    RTSPINLOCKTMP Tmp;
    455643    rtHandleTableLock(pThis, &Tmp);
    456644
     
    492680
    493681    /* acquire the lock */
    494     RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
     682    RTSPINLOCKTMP Tmp;
    495683    rtHandleTableLock(pThis, &Tmp);
    496684
     
    526714                else
    527715                {
    528                     PRTHTENTRYFREE pPrev = (PRTHTENTRYFREE)rtHandleTableLookupWithCtx(pThis, pThis->iFreeTail + pThis->uBase);
     716                    PRTHTENTRYFREE pPrev = (PRTHTENTRYFREE)rtHandleTableLookupWithCtxIdx(pThis, pThis->iFreeTail);
    529717                    Assert(pPrev);
    530718                    RTHT_SET_FREE_IDX(pPrev, i);
  • trunk/src/VBox/Runtime/testcase/Makefile.kmk

    r10419 r10788  
    6363        tstFileLock \
    6464        tstGetOpt \
     65        tstHandleTable \
    6566        tstHeapSimple \
    6667        tstInlineAsm \
     
    153154tstGetOpt_SOURCES = tstGetOpt.cpp
    154155
     156tstHandleTable_SOURCES = tstHandleTable.cpp
     157
    155158tstHeapSimple_SOURCES = tstHeapSimple.cpp
    156159
  • trunk/src/VBox/Runtime/testcase/tstHandleTable.cpp

    r10772 r10788  
    11/* $Id$ */
    22/** @file
    3  * IPRT Testcase - Native Loader.
     3 * IPRT Testcase - Handle Tables.
    44 */
    55
    66/*
    7  * Copyright (C) 2006-2007 Sun Microsystems, Inc.
     7 * Copyright (C) 2008 Sun Microsystems, Inc.
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2929 */
    3030
    31 
    32 #include <iprt/ldr.h>
     31/*******************************************************************************
     32*   Header Files                                                               *
     33*******************************************************************************/
     34#include <iprt/handletable.h>
    3335#include <iprt/stream.h>
    34 #include <iprt/runtime.h>
     36#include <iprt/initterm.h>
    3537#include <iprt/err.h>
    36 
    37 int main(int argc, const char * const *argv)
     38#include <iprt/getopt.h>
     39
     40
     41/*******************************************************************************
     42*   Global Variables                                                           *
     43*******************************************************************************/
     44static unsigned g_cErrors;
     45
     46static DECLCALLBACK(void) tstHandleTableTest1Delete(RTHANDLETABLE hHandleTable, uint32_t h, void *pvObj, void *pvCtx, void *pvUser)
    3847{
    39     int rcRet = 0;
    40     RTR3Init();
    41 
     48    uint32_t *pcCalls = (uint32_t *)pvUser;
     49    (*pcCalls)++;
     50}
     51
     52static DECLCALLBACK(int) tstHandleTableTest1Retain(RTHANDLETABLE hHandleTable, void *pvObj, void *pvCtx, void *pvUser)
     53{
     54    uint32_t *pcCalls = (uint32_t *)pvUser;
     55    (*pcCalls)++;
     56    return VINF_SUCCESS;
     57}
     58
     59static int tstHandleTableTest1(uint32_t fFlags, uint32_t uBase, uint32_t cMax, uint32_t cDelta, uint32_t cUnitsPerDot, bool fCallbacks)
     60{
     61    int rc;
     62    uint32_t cRetainerCalls = 0;
     63
     64    RTPrintf("tstHandleTable: TESTING RTHandleTableCreateEx(, 0");
     65    fFlags |= RTHANDLETABLE_FLAGS_CONTEXT;
     66    if (fFlags & RTHANDLETABLE_FLAGS_LOCKED)    RTPrintf(" | LOCKED");
     67    if (fFlags & RTHANDLETABLE_FLAGS_CONTEXT)   RTPrintf(" | CONTEXT");
     68    RTPrintf(", %#x, %#x,,)...\n", uBase, cMax);
     69
     70    RTHANDLETABLE hHT;
     71    rc = RTHandleTableCreateEx(&hHT, fFlags, uBase, cMax,
     72                               fCallbacks ? tstHandleTableTest1Retain : NULL,
     73                               fCallbacks ? &cRetainerCalls : NULL);
     74    if (RT_FAILURE(rc))
     75    {
     76        RTPrintf("\ntstHandleTable: FAILURE - RTHandleTableCreateEx failed, %Rrc!\n", rc);
     77        return 1;
     78    }
     79
     80    /* fill it */
     81    RTPrintf("tstHandleTable: TESTING   RTHandleTableAllocWithCtx.."); RTStrmFlush(g_pStdOut);
     82    uint32_t i = uBase;
     83    for (;; i++)
     84    {
     85        uint32_t h;
     86        rc = RTHandleTableAllocWithCtx(hHT, (void *)((uintptr_t)&i + (uintptr_t)i * 4), NULL, &h);
     87        if (RT_SUCCESS(rc))
     88        {
     89            if (h != i)
     90            {
     91                RTPrintf("\ntstHandleTable: FAILURE (%d) - h=%d, expected %d!\n", __LINE__, h, i);
     92                g_cErrors++;
     93            }
     94        }
     95        else if (rc == VERR_NO_MORE_HANDLES)
     96        {
     97            if (i < cMax)
     98            {
     99                RTPrintf("\ntstHandleTable: FAILURE (%d) - i=%d, expected > 65534!\n", __LINE__, i);
     100                g_cErrors++;
     101            }
     102            break;
     103        }
     104        else
     105        {
     106            RTPrintf("\ntstHandleTable: FAILURE (%d) - i=%d, rc=%Rrc!\n", __LINE__, i, rc);
     107            g_cErrors++;
     108        }
     109        if (!(i % cUnitsPerDot))
     110        {
     111            RTPrintf(".");
     112            RTStrmFlush(g_pStdOut);
     113        }
     114    }
     115    uint32_t const c = i;
     116    RTPrintf(" c=%#x\n", c);
     117    if (fCallbacks && cRetainerCalls != 0)
     118    {
     119        RTPrintf("tstHandleTable: FAILURE (%d) - cRetainerCalls=%#x expected 0!\n", __LINE__, i, cRetainerCalls);
     120        g_cErrors++;
     121    }
     122
     123    /* look up all the entries */
     124    RTPrintf("tstHandleTable: TESTING   RTHandleTableLookupWithCtx.."); RTStrmFlush(g_pStdOut);
     125    cRetainerCalls = 0;
     126    for (i = uBase; i < c; i++)
     127    {
     128        void *pvExpect = (void *)((uintptr_t)&i + (uintptr_t)i * 4);
     129        void *pvObj = RTHandleTableLookupWithCtx(hHT, i, NULL);
     130        if (!pvObj)
     131        {
     132            RTPrintf("\ntstHandleTable: FAILURE (%d) - i=%d, RTHandleTableLookupWithCtx failed!\n", __LINE__, i);
     133            g_cErrors++;
     134        }
     135        else if (pvObj != pvExpect)
     136        {
     137            RTPrintf("\ntstHandleTable: FAILURE (%d) - i=%d, pvObj=%p expected %p\n", __LINE__, i, pvObj, pvExpect);
     138            g_cErrors++;
     139        }
     140        if (!(i % cUnitsPerDot))
     141        {
     142            RTPrintf(".");
     143            RTStrmFlush(g_pStdOut);
     144        }
     145    }
     146    RTPrintf("\n");
     147    if (fCallbacks && cRetainerCalls != c - uBase)
     148    {
     149        RTPrintf("tstHandleTable: FAILURE (%d) - cRetainerCalls=%#x expected %#x!\n", __LINE__, cRetainerCalls, c - uBase);
     150        g_cErrors++;
     151    }
     152
     153    /* remove all the entries (in order) */
     154    RTPrintf("tstHandleTable: TESTING   RTHandleTableFreeWithCtx.."); RTStrmFlush(g_pStdOut);
     155    cRetainerCalls = 0;
     156    for (i = 1; i < c; i++)
     157    {
     158        void *pvExpect = (void *)((uintptr_t)&i + (uintptr_t)i * 4);
     159        void *pvObj = RTHandleTableFreeWithCtx(hHT, i, NULL);
     160        if (!pvObj)
     161        {
     162            RTPrintf("\ntstHandleTable: FAILURE (%d) - i=%d, RTHandleTableLookupWithCtx failed!\n", __LINE__, i);
     163            g_cErrors++;
     164        }
     165        else if (pvObj != pvExpect)
     166        {
     167            RTPrintf("\ntstHandleTable: FAILURE (%d) - i=%d, pvObj=%p expected %p\n", __LINE__, i, pvObj, pvExpect);
     168            g_cErrors++;
     169        }
     170        else if (RTHandleTableLookupWithCtx(hHT, i, NULL))
     171        {
     172            RTPrintf("\ntstHandleTable: FAILURE (%d) - i=%d, RTHandleTableLookupWithCtx succeeded after free!\n", __LINE__, i);
     173            g_cErrors++;
     174        }
     175        if (!(i % cUnitsPerDot))
     176        {
     177            RTPrintf(".");
     178            RTStrmFlush(g_pStdOut);
     179        }
     180    }
     181    RTPrintf("\n");
     182    if (fCallbacks && cRetainerCalls != c - uBase)
     183    {
     184        RTPrintf("tstHandleTable: FAILURE (%d) - cRetainerCalls=%#x expected %#x!\n", __LINE__, cRetainerCalls, c - uBase);
     185        g_cErrors++;
     186    }
     187
     188    /* do a mix of alloc, lookup and free where there is a constant of cDelta handles in the table. */
     189    RTPrintf("tstHandleTable: TESTING   Alloc,Lookup,Free mix [cDelta=%#x]..", cDelta); RTStrmFlush(g_pStdOut);
     190    for (i = 1; i < c * 2; i++)
     191    {
     192        /* alloc */
     193        uint32_t hExpect = ((i - 1) % (c - 1)) + 1;
     194        uint32_t h;
     195        rc = RTHandleTableAllocWithCtx(hHT, (void *)((uintptr_t)&i + (uintptr_t)hExpect * 4), NULL, &h);
     196        if (RT_FAILURE(rc))
     197        {
     198            RTPrintf("\ntstHandleTable: FAILURE (%d) - i=%d, RTHandleTableAllocWithCtx: rc=%Rrc!\n", __LINE__, i, rc);
     199            g_cErrors++;
     200        }
     201        else if (h != hExpect)
     202        {
     203            RTPrintf("\ntstHandleTable: FAILURE (%d) - i=%d, RTHandleTableAllocWithCtx: rc=%Rrc!\n", __LINE__, i, rc);
     204            g_cErrors++;
     205        }
     206
     207        if (i > cDelta)
     208        {
     209            /* lookup */
     210            for (uint32_t j = i - cDelta; j <= i; j++)
     211            {
     212                uint32_t hLookup = ((j - 1) % (c - 1)) + 1;
     213                void *pvExpect = (void *)((uintptr_t)&i + (uintptr_t)hLookup * 4);
     214                void *pvObj = RTHandleTableLookupWithCtx(hHT, hLookup, NULL);
     215                if (pvObj != pvExpect)
     216                {
     217                    RTPrintf("\ntstHandleTable: FAILURE (%d) - i=%d, j=%d, RTHandleTableLookupWithCtx(,%u,): pvObj=%p expected %p!\n",
     218                             __LINE__, i, j, hLookup, pvObj, pvExpect);
     219                    g_cErrors++;
     220                }
     221                else if (RTHandleTableLookupWithCtx(hHT, hLookup, &i))
     222                {
     223                    RTPrintf("\ntstHandleTable: FAILURE (%d) - i=%d, j=%d, RTHandleTableLookupWithCtx: succeeded with bad context\n",
     224                             __LINE__, i, j, pvObj, pvExpect);
     225                    g_cErrors++;
     226                }
     227            }
     228
     229            /* free */
     230            uint32_t hFree = ((i - 1 - cDelta) % (c - 1)) + 1;
     231            void *pvExpect = (void *)((uintptr_t)&i + (uintptr_t)hFree * 4);
     232            void *pvObj = RTHandleTableFreeWithCtx(hHT, hFree, NULL);
     233            if (pvObj != pvExpect)
     234            {
     235                RTPrintf("\ntstHandleTable: FAILURE (%d) - i=%d, RTHandleTableFreeWithCtx: pvObj=%p expected %p!\n",
     236                         __LINE__, i, pvObj, pvExpect);
     237                g_cErrors++;
     238            }
     239            else if (   RTHandleTableLookupWithCtx(hHT, hFree, NULL)
     240                     || RTHandleTableFreeWithCtx(hHT, hFree, NULL))
     241            {
     242                RTPrintf("\ntstHandleTable: FAILURE (%d) - i=%d, RTHandleTableLookup/FreeWithCtx: succeeded after free\n",
     243                         __LINE__, i);
     244                g_cErrors++;
     245            }
     246        }
     247        if (!(i % (cUnitsPerDot * 2)))
     248        {
     249            RTPrintf(".");
     250            RTStrmFlush(g_pStdOut);
     251        }
     252    }
     253    RTPrintf("\n");
     254
     255    /* finally, destroy the table (note that there are 128 entries in it). */
     256    cRetainerCalls = 0;
     257    uint32_t cDeleteCalls = 0;
     258    rc = RTHandleTableDestroy(hHT,
     259                              fCallbacks ? tstHandleTableTest1Delete : NULL,
     260                              fCallbacks ? &cDeleteCalls : NULL);
     261    if (RT_FAILURE(rc))
     262    {
     263        RTPrintf("tstHandleTable: FAILURE (%d) - RTHandleTableDestroy failed, %Rrc!\n", __LINE__, rc);
     264        g_cErrors++;
     265    }
     266
     267    return 0;
     268}
     269
     270int main(int argc, char **argv)
     271{
    42272    /*
    43      * If no args, display usage.
     273     * Init the runtime and parse the arguments.
    44274     */
    45     if (argc <= 1)
    46     {
    47         RTPrintf("Syntax: %s [so/dll [so/dll [..]]\n", argv[0]);
     275    RTR3Init(false, 0);
     276
     277    static RTOPTIONDEF const s_aOptions[] =
     278    {
     279        { "--base",         'b', RTGETOPT_REQ_UINT32 },
     280        { "--max",          'm', RTGETOPT_REQ_UINT32 },
     281    };
     282
     283    uint32_t uBase = 0;
     284    uint32_t cMax = 0;
     285
     286    int ch;
     287    int iArg = 1;
     288    RTOPTIONUNION Value;
     289    while ((ch = RTGetOpt(argc,argv, &s_aOptions[0], RT_ELEMENTS(s_aOptions), &iArg, &Value)))
     290        switch (ch)
     291        {
     292            case 'b':
     293                uBase = Value.u32;
     294                break;
     295
     296            case 'm':
     297                cMax = Value.u32;
     298                break;
     299
     300            case '?':
     301            case 'h':
     302                RTPrintf("syntax: tstIntNet-1 [-pSt] [-d <secs>] [-f <file>] [-r <size>] [-s <size>]\n");
     303                return 1;
     304
     305            default:
     306                if (RT_SUCCESS(ch))
     307                    RTPrintf("tstHandleTable: invalid argument (%#x): %s\n", ch, Value.psz);
     308                else
     309                    RTPrintf("tstHandleTable: invalid argument: %Rrc - \n", ch, Value.pDef->pszLong);
     310                return 1;
     311        }
     312    if (iArg < argc)
     313    {
     314        RTPrintf("tstHandleTable: invalid argument: %s\n", argv[iArg]);
    48315        return 1;
    49316    }
    50317
    51318    /*
    52      * Iterate the arguments and treat all of them as so/dll paths.
     319     * Do a simple warmup / smoke test first.
    53320     */
    54     for (int i = 1; i < argc; i++)
    55     {
    56         RTLDRMOD hLdrMod = (RTLDRMOD)0xbaadffaa;
    57         int rc = RTLdrLoad(argv[i], &hLdrMod);
    58         if (RT_SUCCESS(rc))
    59         {
    60             RTPrintf("tstLdrLoad: %d - %s\n", i, argv[i]);
    61             rc = RTLdrClose(hLdrMod);
    62             if (RT_FAILURE(rc))
    63             {
    64                 RTPrintf("tstLdrLoad: rc=%Rrc RTLdrClose()\n", rc);
    65                 rcRet++;
    66             }
    67         }
    68         else
    69         {
    70             RTPrintf("tstLdrLoad: rc=%Rrc RTLdrOpen('%s')\n", rc, argv[i]);
    71             rcRet++;
    72         }
    73     }
     321    /* these two are for the default case. */
     322    tstHandleTableTest1(0,                              1,       65534,  128,           2048, false);
     323    tstHandleTableTest1(RTHANDLETABLE_FLAGS_LOCKED,     1,       65534,   63,           2048, false);
     324    /* Test that the retain and delete functions work. */
     325    tstHandleTableTest1(RTHANDLETABLE_FLAGS_LOCKED,     1,       1024,   256,            256,  true);
     326    /* For testing 1st level expansion / reallocation. */
     327    tstHandleTableTest1(0,                              1, 1024*1024*8,   3,          150000, false);
     328
     329    /*
     330     * Threaded tests.
     331     */
     332
    74333
    75334    /*
    76335     * Summary.
    77336     */
    78     if (!rcRet)
    79         RTPrintf("tstLdrLoad: SUCCESS\n");
     337    if (!g_cErrors)
     338        RTPrintf("tstHandleTable: SUCCESS\n");
    80339    else
    81         RTPrintf("tstLdrLoad: FAILURE - %d errors\n", rcRet);
    82 
    83     return !!rcRet;
     340        RTPrintf("tstHandleTable: FAILURE - %d errors\n", g_cErrors);
     341
     342    return !!g_cErrors;
    84343}
注意: 瀏覽 TracChangeset 來幫助您使用更動檢視器

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