VirtualBox

Ignore:
Timestamp:
Dec 15, 2011 4:37:48 PM (13 years ago)
Author:
vboxsync
Message:

Most of the reqpool code is there now. The testcase didn't turn up any bad bugs yet, so there must be some pretty bad stuff hiding in there. according to the rules...

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/misc/reqpool.cpp

    r39621 r39632  
    108108    /** Magic value (RTREQPOOL_MAGIC). */
    109109    uint32_t                u32Magic;
     110    /** The request pool name. */
     111    char                    szName[12];
    110112
    111113    /** @name Config
     
    618620
    619621
     622RTDECL(int) RTReqPoolCreate(uint32_t cMaxThreads, RTMSINTERVAL cMsMinIdle,
     623                            uint32_t cThreadsPushBackThreshold, uint32_t cMsMaxPushBack,
     624                            const char *pszName, PRTREQPOOL phPool)
     625{
     626    /*
     627     * Validate and massage the config.
     628     */
     629    if (cMaxThreads == UINT32_MAX)
     630        cMaxThreads = RTREQPOOL_MAX_THREADS;
     631    AssertMsgReturn(cMaxThreads > 0 && cMaxThreads <= RTREQPOOL_MAX_THREADS, ("%u\n", cMaxThreads), VERR_OUT_OF_RANGE);
     632    uint32_t const cMinThreads = cMaxThreads > 2 ? 2 : cMaxThreads - 1;
     633
     634    if (cThreadsPushBackThreshold == 0)
     635        cThreadsPushBackThreshold = cMinThreads;
     636    else if (cThreadsPushBackThreshold == UINT32_MAX)
     637        cThreadsPushBackThreshold = cMaxThreads;
     638    AssertMsgReturn(cThreadsPushBackThreshold <= cMaxThreads, ("%u/%u\n", cThreadsPushBackThreshold, cMaxThreads), VERR_OUT_OF_RANGE);
     639
     640    if (cMsMaxPushBack == UINT32_MAX)
     641        cMsMaxPushBack = RTREQPOOL_PUSH_BACK_MAX_MS;
     642    AssertMsgReturn(cMsMaxPushBack <= RTREQPOOL_PUSH_BACK_MAX_MS, ("%llu\n",  cMsMaxPushBack), VERR_OUT_OF_RANGE);
     643    uint32_t const cMsMinPushBack = cMsMaxPushBack >= 200 ? 100 : cMsMaxPushBack / 2;
     644
     645    AssertPtrReturn(pszName, VERR_INVALID_POINTER);
     646    size_t cchName = strlen(pszName);
     647    AssertReturn(cchName > 0, VERR_INVALID_PARAMETER);
     648    Assert(cchName <= 10);
     649
     650    AssertPtrReturn(phPool, VERR_INVALID_POINTER);
     651
     652    /*
     653     * Create and initialize the pool.
     654     */
     655    PRTREQPOOLINT pPool = (PRTREQPOOLINT)RTMemAlloc(sizeof(*pPool));
     656    if (!pPool)
     657        return VERR_NO_MEMORY;
     658
     659    pPool->u32Magic         = RTREQPOOL_MAGIC;
     660    RTStrCopy(pPool->szName, sizeof(pPool->szName), pszName);
     661
     662    pPool->enmThreadType        = RTTHREADTYPE_DEFAULT;
     663    pPool->cMaxThreads          = cMaxThreads;
     664    pPool->cMinThreads          = cMinThreads;
     665    pPool->cMsMinIdle           = cMsMinIdle == RT_INDEFINITE_WAIT || cMsMinIdle >= UINT32_MAX ? UINT32_MAX : cMsMinIdle;
     666    pPool->cNsMinIdle           = pPool->cMsMinIdle == UINT32_MAX ? UINT64_MAX         : cMsMinIdle * RT_NS_1MS_64;
     667    pPool->cMsIdleSleep         = pPool->cMsMinIdle == UINT32_MAX ? RT_INDEFINITE_WAIT : RT_MAX(RT_MS_1SEC, pPool->cMsMinIdle);
     668    pPool->cThreadsPushBackThreshold = cThreadsPushBackThreshold;
     669    pPool->cMsMaxPushBack       = cMsMaxPushBack;
     670    pPool->cMsMinPushBack       = cMsMinPushBack;
     671    pPool->cMaxFreeRequests     = cMaxThreads * 2;
     672    pPool->hThreadTermEvt       = NIL_RTSEMEVENTMULTI;
     673    pPool->fDestructing         = false;
     674    pPool->cMsCurPushBack       = 0;
     675    pPool->cCurThreads          = 0;
     676    pPool->cThreadsCreated      = 0;
     677    pPool->uLastThreadCreateNanoTs = 0;
     678    RTListInit(&pPool->WorkerThreads);
     679    pPool->cReqProcessed        = 0;
     680    pPool->cNsTotalReqProcessing= 0;
     681    pPool->cNsTotalReqQueued    = 0;
     682    pPool->cRefs                = 1;
     683    pPool->cIdleThreads         = 0;
     684    RTListInit(&pPool->IdleThreads);
     685    pPool->pPendingRequests     = NULL;
     686    pPool->ppPendingRequests    = &pPool->pPendingRequests;
     687    pPool->cCurPendingRequests  = 0;
     688    pPool->cCurActiveRequests   = 0;
     689    pPool->cReqSubmitted        = 0;
     690    pPool->pFreeRequests        = NULL;
     691    pPool->cCurFreeRequests     = NULL;
     692
     693    int rc = RTSemEventMultiCreate(&pPool->hThreadTermEvt);
     694    if (RT_SUCCESS(rc))
     695    {
     696        rc = RTCritSectInit(&pPool->CritSect);
     697        if (RT_SUCCESS(rc))
     698        {
     699            *phPool = pPool;
     700            return VINF_SUCCESS;
     701        }
     702
     703        RTSemEventMultiDestroy(pPool->hThreadTermEvt);
     704    }
     705    pPool->u32Magic = RTREQPOOL_MAGIC_DEAD;
     706    RTMemFree(pPool);
     707    return rc;
     708}
     709
     710
     711
    620712RTDECL(int) RTReqPoolSetCfgVar(RTREQPOOL hPool, RTREQPOOLCFGVAR enmVar, uint64_t uValue)
    621713{
     
    706798
    707799        case RTREQPOOLCFGVAR_PUSH_BACK_MIN_MS:
    708             AssertMsgBreakStmt(uValue <= RTREQPOOL_PUSH_BACK_MAX_MS,  ("%llu\n",  uValue), rc = VERR_OUT_OF_RANGE);
     800            if (uValue == UINT32_MAX || uValue == UINT64_MAX)
     801                uValue = RTREQPOOL_PUSH_BACK_MAX_MS;
     802            else
     803                AssertMsgBreakStmt(uValue <= RTREQPOOL_PUSH_BACK_MAX_MS,  ("%llu\n",  uValue), rc = VERR_OUT_OF_RANGE);
    709804            pPool->cMsMinPushBack = (uint32_t)uValue;
    710805            if (pPool->cMsMaxPushBack < pPool->cMsMinPushBack)
     
    714809
    715810        case RTREQPOOLCFGVAR_PUSH_BACK_MAX_MS:
    716             AssertMsgBreakStmt(uValue <= RTREQPOOL_PUSH_BACK_MAX_MS,  ("%llu\n",  uValue), rc = VERR_OUT_OF_RANGE);
     811            if (uValue == UINT32_MAX || uValue == UINT64_MAX)
     812                uValue = RTREQPOOL_PUSH_BACK_MAX_MS;
     813            else
     814                AssertMsgBreakStmt(uValue <= RTREQPOOL_PUSH_BACK_MAX_MS,  ("%llu\n",  uValue), rc = VERR_OUT_OF_RANGE);
    717815            pPool->cMsMaxPushBack = (uint32_t)uValue;
    718816            if (pPool->cMsMinPushBack < pPool->cMsMaxPushBack)
     
    766864
    767865
    768 RTDECL(int) RTReqPoolQueryCfgVar(RTREQPOOL hPool, RTREQPOOLCFGVAR enmVar, uint64_t *puValue)
     866RTDECL(uint64_t) RTReqPoolGetCfgVar(RTREQPOOL hPool, RTREQPOOLCFGVAR enmVar)
    769867{
    770868    PRTREQPOOLINT pPool = hPool;
    771     AssertPtrReturn(pPool, VERR_INVALID_HANDLE);
    772     AssertReturn(pPool->u32Magic == RTREQPOOL_MAGIC, VERR_INVALID_HANDLE);
    773     AssertReturn(enmVar > RTREQPOOLCFGVAR_INVALID && enmVar < RTREQPOOLCFGVAR_END, VERR_INVALID_PARAMETER);
     869    AssertPtrReturn(pPool, UINT64_MAX);
     870    AssertReturn(pPool->u32Magic == RTREQPOOL_MAGIC, UINT64_MAX);
     871    AssertReturn(enmVar > RTREQPOOLCFGVAR_INVALID && enmVar < RTREQPOOLCFGVAR_END, UINT64_MAX);
    774872
    775873    RTCritSectEnter(&pPool->CritSect);
    776874
    777     int rc = VINF_SUCCESS;
     875    uint64_t u64;
    778876    switch (enmVar)
    779877    {
    780878        case RTREQPOOLCFGVAR_THREAD_TYPE:
    781             *puValue = pPool->enmThreadType;
     879            u64 = pPool->enmThreadType;
    782880            break;
    783881
    784882        case RTREQPOOLCFGVAR_MIN_THREADS:
    785             *puValue = pPool->cMinThreads;
     883            u64 = pPool->cMinThreads;
    786884            break;
    787885
    788886        case RTREQPOOLCFGVAR_MAX_THREADS:
    789             *puValue = pPool->cMaxThreads;
     887            u64 = pPool->cMaxThreads;
    790888            break;
    791889
    792890        case RTREQPOOLCFGVAR_MS_MIN_IDLE:
    793             *puValue = pPool->cMsMinIdle;
     891            u64 = pPool->cMsMinIdle;
    794892            break;
    795893
    796894        case RTREQPOOLCFGVAR_MS_IDLE_SLEEP:
    797             *puValue = pPool->cMsIdleSleep;
     895            u64 = pPool->cMsIdleSleep;
    798896            break;
    799897
    800898        case RTREQPOOLCFGVAR_PUSH_BACK_THRESHOLD:
    801             *puValue = pPool->cThreadsPushBackThreshold;
     899            u64 = pPool->cThreadsPushBackThreshold;
    802900            break;
    803901
    804902        case RTREQPOOLCFGVAR_PUSH_BACK_MIN_MS:
    805             *puValue = pPool->cMsMinPushBack;
     903            u64 = pPool->cMsMinPushBack;
    806904            break;
    807905
    808906        case RTREQPOOLCFGVAR_PUSH_BACK_MAX_MS:
    809             *puValue = pPool->cMsMaxPushBack;
     907            u64 = pPool->cMsMaxPushBack;
    810908            break;
    811909
    812910        case RTREQPOOLCFGVAR_MAX_FREE_REQUESTS:
    813             *puValue = pPool->cMaxFreeRequests;
     911            u64 = pPool->cMaxFreeRequests;
    814912            break;
    815913
    816914        default:
    817915            AssertFailed();
    818             rc = VERR_IPE_NOT_REACHED_DEFAULT_CASE;
    819             *puValue = UINT64_MAX;
     916            u64 = UINT64_MAX;
    820917            break;
    821918    }
     
    823920    RTCritSectLeave(&pPool->CritSect);
    824921
    825     return rc;
    826 }
    827 RT_EXPORT_SYMBOL(RTReqPoolQueryCfgVar);
     922    return u64;
     923}
     924RT_EXPORT_SYMBOL(RTReqGetQueryCfgVar);
    828925
    829926
     
    9391036        }
    9401037
    941         /* Finally, free the handle. */
     1038        /* Finally, free the critical section and pool instance. */
     1039        RTCritSectLeave(&pPool->CritSect);
     1040        RTCritSectDelete(&pPool->CritSect);
    9421041        RTMemFree(pPool);
    9431042    }
     
    9921091RT_EXPORT_SYMBOL(RTReqPoolAlloc);
    9931092
     1093
     1094RTDECL(int) RTReqPoolCallEx( RTREQPOOL hPool, RTMSINTERVAL cMillies, PRTREQ *phReq, uint32_t fFlags, PFNRT pfnFunction, unsigned cArgs, ...)
     1095{
     1096    va_list va;
     1097    va_start(va, cArgs);
     1098    int rc = RTReqPoolCallExV(hPool, cMillies, phReq, fFlags, pfnFunction, cArgs, va);
     1099    va_end(va);
     1100    return rc;
     1101}
     1102RT_EXPORT_SYMBOL(RTReqPoolCallEx);
     1103
     1104
     1105RTDECL(int) RTReqPoolCallExV(RTREQPOOL hPool, RTMSINTERVAL cMillies, PRTREQ *phReq, uint32_t fFlags, PFNRT pfnFunction, unsigned cArgs, va_list va)
     1106{
     1107    /*
     1108     * Check input.
     1109     */
     1110    AssertPtrReturn(pfnFunction, VERR_INVALID_POINTER);
     1111    AssertMsgReturn(!((uint32_t)fFlags & ~(uint32_t)(RTREQFLAGS_NO_WAIT | RTREQFLAGS_RETURN_MASK)), ("%#x\n", (uint32_t)fFlags), VERR_INVALID_PARAMETER);
     1112    if (!(fFlags & RTREQFLAGS_NO_WAIT))
     1113    {
     1114        AssertPtrReturn(phReq, VERR_INVALID_POINTER);
     1115        *phReq = NIL_RTREQ;
     1116    }
     1117
     1118    PRTREQINT pReq = NULL;
     1119    AssertMsgReturn(cArgs * sizeof(uintptr_t) <= sizeof(pReq->u.Internal.aArgs), ("cArgs=%u\n", cArgs), VERR_TOO_MUCH_DATA);
     1120
     1121    /*
     1122     * Allocate and initialize the request.
     1123     */
     1124    int rc = RTReqPoolAlloc(hPool, RTREQTYPE_INTERNAL, &pReq);
     1125    if (RT_FAILURE(rc))
     1126        return rc;
     1127    pReq->fFlags           = fFlags;
     1128    pReq->u.Internal.pfn   = pfnFunction;
     1129    pReq->u.Internal.cArgs = cArgs;
     1130    for (unsigned iArg = 0; iArg < cArgs; iArg++)
     1131        pReq->u.Internal.aArgs[iArg] = va_arg(va, uintptr_t);
     1132
     1133    /*
     1134     * Submit the request.
     1135     */
     1136    rc = RTReqSubmit(pReq, cMillies);
     1137    if (   rc != VINF_SUCCESS
     1138        && rc != VERR_TIMEOUT)
     1139    {
     1140        Assert(rc != VERR_INTERRUPTED);
     1141        RTReqRelease(pReq);
     1142        pReq = NULL;
     1143    }
     1144
     1145    if (!(fFlags & RTREQFLAGS_NO_WAIT))
     1146    {
     1147        *phReq = pReq;
     1148        LogFlow(("RTReqPoolCallExV: returns %Rrc *phReq=%p\n", rc, pReq));
     1149    }
     1150    else
     1151        LogFlow(("RTReqPoolCallExV: returns %Rrc\n", rc));
     1152    return rc;
     1153}
     1154RT_EXPORT_SYMBOL(RTReqPoolCallExV);
     1155
     1156
     1157RTDECL(int) RTReqPoolCallWait(RTREQPOOL hPool, PFNRT pfnFunction, unsigned cArgs, ...)
     1158{
     1159    PRTREQINT pReq;
     1160    va_list   va;
     1161    va_start(va, cArgs);
     1162    int rc = RTReqPoolCallExV(hPool, RT_INDEFINITE_WAIT, &pReq, RTREQFLAGS_IPRT_STATUS,
     1163                              pfnFunction, cArgs, va);
     1164    va_end(va);
     1165    if (RT_SUCCESS(rc))
     1166        rc = pReq->iStatusX;
     1167    RTReqRelease(pReq);
     1168    return rc;
     1169}
     1170RT_EXPORT_SYMBOL(RTReqPoolCallWait);
     1171
     1172
     1173RTDECL(int) RTReqPoolCallNoWait(RTREQPOOL hPool, PFNRT pfnFunction, unsigned cArgs, ...)
     1174{
     1175    va_list   va;
     1176    va_start(va, cArgs);
     1177    int rc = RTReqPoolCallExV(hPool, 0, NULL, RTREQFLAGS_IPRT_STATUS | RTREQFLAGS_NO_WAIT,
     1178                              pfnFunction, cArgs, va);
     1179    va_end(va);
     1180    return rc;
     1181}
     1182RT_EXPORT_SYMBOL(RTReqPoolCallNoWait);
     1183
     1184
     1185RTDECL(int) RTReqPoolCallVoidWait(RTREQPOOL hPool, PFNRT pfnFunction, unsigned cArgs, ...)
     1186{
     1187    PRTREQINT pReq;
     1188    va_list   va;
     1189    va_start(va, cArgs);
     1190    int rc = RTReqPoolCallExV(hPool, RT_INDEFINITE_WAIT, &pReq, RTREQFLAGS_VOID,
     1191                              pfnFunction, cArgs, va);
     1192    va_end(va);
     1193    if (RT_SUCCESS(rc))
     1194        rc = pReq->iStatusX;
     1195    RTReqRelease(pReq);
     1196    return rc;
     1197}
     1198RT_EXPORT_SYMBOL(RTReqPoolCallVoidWait);
     1199
     1200
     1201RTDECL(int) RTReqPoolCallVoidNoWait(RTREQPOOL hPool, PFNRT pfnFunction, unsigned cArgs, ...)
     1202{
     1203    va_list   va;
     1204    va_start(va, cArgs);
     1205    int rc = RTReqPoolCallExV(hPool, 0, NULL, RTREQFLAGS_VOID | RTREQFLAGS_NO_WAIT,
     1206                              pfnFunction, cArgs, va);
     1207    va_end(va);
     1208    return rc;
     1209}
     1210RT_EXPORT_SYMBOL(RTReqPoolCallVoidNoWait);
     1211
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