Changeset 39632 in vbox for trunk/src/VBox/Runtime/common/misc/reqpool.cpp
- Timestamp:
- Dec 15, 2011 4:37:48 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/misc/reqpool.cpp
r39621 r39632 108 108 /** Magic value (RTREQPOOL_MAGIC). */ 109 109 uint32_t u32Magic; 110 /** The request pool name. */ 111 char szName[12]; 110 112 111 113 /** @name Config … … 618 620 619 621 622 RTDECL(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 620 712 RTDECL(int) RTReqPoolSetCfgVar(RTREQPOOL hPool, RTREQPOOLCFGVAR enmVar, uint64_t uValue) 621 713 { … … 706 798 707 799 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); 709 804 pPool->cMsMinPushBack = (uint32_t)uValue; 710 805 if (pPool->cMsMaxPushBack < pPool->cMsMinPushBack) … … 714 809 715 810 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); 717 815 pPool->cMsMaxPushBack = (uint32_t)uValue; 718 816 if (pPool->cMsMinPushBack < pPool->cMsMaxPushBack) … … 766 864 767 865 768 RTDECL( int) RTReqPoolQueryCfgVar(RTREQPOOL hPool, RTREQPOOLCFGVAR enmVar, uint64_t *puValue)866 RTDECL(uint64_t) RTReqPoolGetCfgVar(RTREQPOOL hPool, RTREQPOOLCFGVAR enmVar) 769 867 { 770 868 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); 774 872 775 873 RTCritSectEnter(&pPool->CritSect); 776 874 777 int rc = VINF_SUCCESS;875 uint64_t u64; 778 876 switch (enmVar) 779 877 { 780 878 case RTREQPOOLCFGVAR_THREAD_TYPE: 781 *puValue= pPool->enmThreadType;879 u64 = pPool->enmThreadType; 782 880 break; 783 881 784 882 case RTREQPOOLCFGVAR_MIN_THREADS: 785 *puValue= pPool->cMinThreads;883 u64 = pPool->cMinThreads; 786 884 break; 787 885 788 886 case RTREQPOOLCFGVAR_MAX_THREADS: 789 *puValue= pPool->cMaxThreads;887 u64 = pPool->cMaxThreads; 790 888 break; 791 889 792 890 case RTREQPOOLCFGVAR_MS_MIN_IDLE: 793 *puValue= pPool->cMsMinIdle;891 u64 = pPool->cMsMinIdle; 794 892 break; 795 893 796 894 case RTREQPOOLCFGVAR_MS_IDLE_SLEEP: 797 *puValue= pPool->cMsIdleSleep;895 u64 = pPool->cMsIdleSleep; 798 896 break; 799 897 800 898 case RTREQPOOLCFGVAR_PUSH_BACK_THRESHOLD: 801 *puValue= pPool->cThreadsPushBackThreshold;899 u64 = pPool->cThreadsPushBackThreshold; 802 900 break; 803 901 804 902 case RTREQPOOLCFGVAR_PUSH_BACK_MIN_MS: 805 *puValue= pPool->cMsMinPushBack;903 u64 = pPool->cMsMinPushBack; 806 904 break; 807 905 808 906 case RTREQPOOLCFGVAR_PUSH_BACK_MAX_MS: 809 *puValue= pPool->cMsMaxPushBack;907 u64 = pPool->cMsMaxPushBack; 810 908 break; 811 909 812 910 case RTREQPOOLCFGVAR_MAX_FREE_REQUESTS: 813 *puValue= pPool->cMaxFreeRequests;911 u64 = pPool->cMaxFreeRequests; 814 912 break; 815 913 816 914 default: 817 915 AssertFailed(); 818 rc = VERR_IPE_NOT_REACHED_DEFAULT_CASE; 819 *puValue = UINT64_MAX; 916 u64 = UINT64_MAX; 820 917 break; 821 918 } … … 823 920 RTCritSectLeave(&pPool->CritSect); 824 921 825 return rc;826 } 827 RT_EXPORT_SYMBOL(RTReq PoolQueryCfgVar);922 return u64; 923 } 924 RT_EXPORT_SYMBOL(RTReqGetQueryCfgVar); 828 925 829 926 … … 939 1036 } 940 1037 941 /* Finally, free the handle. */ 1038 /* Finally, free the critical section and pool instance. */ 1039 RTCritSectLeave(&pPool->CritSect); 1040 RTCritSectDelete(&pPool->CritSect); 942 1041 RTMemFree(pPool); 943 1042 } … … 992 1091 RT_EXPORT_SYMBOL(RTReqPoolAlloc); 993 1092 1093 1094 RTDECL(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 } 1102 RT_EXPORT_SYMBOL(RTReqPoolCallEx); 1103 1104 1105 RTDECL(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 } 1154 RT_EXPORT_SYMBOL(RTReqPoolCallExV); 1155 1156 1157 RTDECL(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 } 1170 RT_EXPORT_SYMBOL(RTReqPoolCallWait); 1171 1172 1173 RTDECL(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 } 1182 RT_EXPORT_SYMBOL(RTReqPoolCallNoWait); 1183 1184 1185 RTDECL(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 } 1198 RT_EXPORT_SYMBOL(RTReqPoolCallVoidWait); 1199 1200 1201 RTDECL(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 } 1210 RT_EXPORT_SYMBOL(RTReqPoolCallVoidNoWait); 1211
Note:
See TracChangeset
for help on using the changeset viewer.