Changeset 27883 in vbox
- Timestamp:
- Mar 31, 2010 12:07:15 PM (15 years ago)
- svn:sync-xref-src-repo-rev:
- 59570
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/PDMAsyncCompletion.cpp
r27738 r27883 116 116 } PDMASYNCCOMPLETIONTEMPLATE; 117 117 118 static void pdmR3AsyncCompletionPutTask(PPDMASYNCCOMPLETIONENDPOINT pEndpoint, PPDMASYNCCOMPLETIONTASK pTask , bool fLocal);118 static void pdmR3AsyncCompletionPutTask(PPDMASYNCCOMPLETIONENDPOINT pEndpoint, PPDMASYNCCOMPLETIONTASK pTask); 119 119 120 120 /** … … 580 580 } 581 581 582 pdmR3AsyncCompletionPutTask(pTask->pEndpoint, pTask , true);582 pdmR3AsyncCompletionPutTask(pTask->pEndpoint, pTask); 583 583 } 584 584 … … 620 620 PCFGMNODE pCfgNodeClass = CFGMR3GetChild(pCfgHandle, pEpClassOps->pcszName); 621 621 622 /* Query the common CFGM options */ 623 rc = CFGMR3QueryU32Def(pCfgNodeClass, "TaskCachePerEndpoint", &pEndpointClass->cEndpointCacheSize, 5); 624 AssertRCReturn(rc, rc); 625 626 rc = CFGMR3QueryU32Def(pCfgNodeClass, "TaskCachePerClass", &pEndpointClass->cEpClassCacheSize, 50); 627 AssertRCReturn(rc, rc); 628 629 /* Call the specific endpoint class initializer. */ 630 rc = pEpClassOps->pfnInitialize(pEndpointClass, pCfgNodeClass); 622 /* Create task cache */ 623 rc = RTMemCacheCreate(&pEndpointClass->hMemCacheTasks, pEpClassOps->cbTask, 624 0, UINT32_MAX, NULL, NULL, NULL, 0); 631 625 if (RT_SUCCESS(rc)) 632 626 { 633 AssertMsg(!pVM->pdm.s.papAsyncCompletionEndpointClass[pEpClassOps->enmClassType], 634 ("Endpoint class was already initialized\n")); 635 636 pVM->pdm.s.papAsyncCompletionEndpointClass[pEpClassOps->enmClassType] = pEndpointClass; 637 LogFlowFunc((": Initialized endpoint class \"%s\" rc=%Rrc\n", pEpClassOps->pcszName, rc)); 638 return VINF_SUCCESS; 627 /* Call the specific endpoint class initializer. */ 628 rc = pEpClassOps->pfnInitialize(pEndpointClass, pCfgNodeClass); 629 if (RT_SUCCESS(rc)) 630 { 631 AssertMsg(!pVM->pdm.s.papAsyncCompletionEndpointClass[pEpClassOps->enmClassType], 632 ("Endpoint class was already initialized\n")); 633 634 pVM->pdm.s.papAsyncCompletionEndpointClass[pEpClassOps->enmClassType] = pEndpointClass; 635 LogFlowFunc((": Initialized endpoint class \"%s\" rc=%Rrc\n", pEpClassOps->pcszName, rc)); 636 return VINF_SUCCESS; 637 } 638 RTMemCacheDestroy(pEndpointClass->hMemCacheTasks); 639 639 } 640 640 RTCritSectDelete(&pEndpointClass->CritSect); … … 665 665 PDMR3AsyncCompletionEpClose(pEndpointClass->pEndpointsHead); 666 666 667 /* Destroy all cached tasks. */668 for (unsigned i = 0; i < RT_ELEMENTS(pEndpointClass->apTaskCache); i++)669 {670 PPDMASYNCCOMPLETIONTASK pTask = pEndpointClass->apTaskCache[i];671 672 while (pTask)673 {674 PPDMASYNCCOMPLETIONTASK pTaskFree = pTask;675 pTask = pTask->pNext;676 MMR3HeapFree(pTaskFree);677 }678 }679 680 667 /* Call the termination callback of the class. */ 681 668 pEndpointClass->pEndpointOps->pfnTerminate(pEndpointClass); 682 669 670 RTMemCacheDestroy(pEndpointClass->hMemCacheTasks); 683 671 RTCritSectDelete(&pEndpointClass->CritSect); 684 672 … … 754 742 static PPDMASYNCCOMPLETIONTASK pdmR3AsyncCompletionGetTask(PPDMASYNCCOMPLETIONENDPOINT pEndpoint, void *pvUser) 755 743 { 744 PPDMASYNCCOMPLETIONEPCLASS pEndpointClass = pEndpoint->pEpClass; 756 745 PPDMASYNCCOMPLETIONTASK pTask = NULL; 757 746 758 /* Try the small per endpoint cache first. */ 759 uint32_t cTasksCached = ASMAtomicReadU32(&pEndpoint->cTasksCached); 760 if (cTasksCached == 0) 761 { 762 /* Try the bigger per endpoint class cache. */ 763 PPDMASYNCCOMPLETIONEPCLASS pEndpointClass = pEndpoint->pEpClass; 764 765 /* We start with the assigned slot id to distribute the load when allocating new tasks. */ 766 unsigned iSlot = pEndpoint->iSlotStart; 767 do 768 { 769 pTask = (PPDMASYNCCOMPLETIONTASK)ASMAtomicXchgPtr((void * volatile *)&pEndpointClass->apTaskCache[iSlot], NULL); 770 if (pTask) 771 break; 772 773 iSlot = (iSlot + 1) % RT_ELEMENTS(pEndpointClass->apTaskCache); 774 } while (iSlot != pEndpoint->iSlotStart); 775 776 if (!pTask) 777 { 778 /* 779 * Allocate completely new. 780 * If this fails we return NULL. 781 */ 782 int rc = MMR3HeapAllocZEx(pEndpointClass->pVM, MM_TAG_PDM_ASYNC_COMPLETION, 783 pEndpointClass->pEndpointOps->cbTask, 784 (void **)&pTask); 785 if (RT_FAILURE(rc)) 786 pTask = NULL; 787 } 788 else 789 { 790 /* Remove the first element and put the rest into the slot again. */ 791 PPDMASYNCCOMPLETIONTASK pTaskHeadNew = pTask->pNext; 792 793 /* Put back into the list adding any new tasks. */ 794 while (true) 795 { 796 bool fChanged = ASMAtomicCmpXchgPtr((void * volatile *)&pEndpointClass->apTaskCache[iSlot], pTaskHeadNew, NULL); 797 798 if (fChanged) 799 break; 800 801 PPDMASYNCCOMPLETIONTASK pTaskHead = (PPDMASYNCCOMPLETIONTASK)ASMAtomicXchgPtr((void * volatile *)&pEndpointClass->apTaskCache[iSlot], NULL); 802 803 /* The new task could be taken inbetween */ 804 if (pTaskHead) 805 { 806 /* Go to the end of the probably much shorter new list. */ 807 PPDMASYNCCOMPLETIONTASK pTaskTail = pTaskHead; 808 while (pTaskTail->pNext) 809 pTaskTail = pTaskTail->pNext; 810 811 /* Concatenate */ 812 pTaskTail->pNext = pTaskHeadNew; 813 814 pTaskHeadNew = pTaskHead; 815 } 816 /* Another round trying to change the list. */ 817 } 818 /* We got a task from the global cache so decrement the counter */ 819 ASMAtomicDecU32(&pEndpointClass->cTasksCached); 820 } 821 } 822 else 823 { 824 /* Grab a free task from the head. */ 825 AssertMsg(pEndpoint->cTasksCached > 0, ("No tasks cached but list contain more than one element\n")); 826 827 pTask = pEndpoint->pTasksFreeHead; 828 pEndpoint->pTasksFreeHead = pTask->pNext; 829 ASMAtomicDecU32(&pEndpoint->cTasksCached); 830 } 747 pTask = (PPDMASYNCCOMPLETIONTASK)RTMemCacheAlloc(pEndpointClass->hMemCacheTasks); 831 748 832 749 if (RT_LIKELY(pTask)) … … 856 773 * @param pEndpoint The endpoint the task belongs to. 857 774 * @param pTask The task to cache. 858 * @param fLocal Whether the per endpoint cache should be tried first. 859 */ 860 static void pdmR3AsyncCompletionPutTask(PPDMASYNCCOMPLETIONENDPOINT pEndpoint, PPDMASYNCCOMPLETIONTASK pTask, bool fLocal) 775 */ 776 static void pdmR3AsyncCompletionPutTask(PPDMASYNCCOMPLETIONENDPOINT pEndpoint, PPDMASYNCCOMPLETIONTASK pTask) 861 777 { 862 778 PPDMASYNCCOMPLETIONEPCLASS pEndpointClass = pEndpoint->pEpClass; … … 921 837 #endif 922 838 923 /* Check whether we can use the per endpoint cache */ 924 if ( fLocal 925 && (pEndpoint->cTasksCached < pEndpointClass->cEndpointCacheSize)) 926 { 927 /* Add it to the list. */ 928 pTask->pPrev = NULL; 929 pEndpoint->pTasksFreeTail->pNext = pTask; 930 pEndpoint->pTasksFreeTail = pTask; 931 ASMAtomicIncU32(&pEndpoint->cTasksCached); 932 } 933 else if (ASMAtomicReadU32(&pEndpoint->cTasksCached) < pEndpointClass->cEpClassCacheSize) 934 { 935 /* Use the global cache. */ 936 ASMAtomicIncU32(&pEndpointClass->cTasksCached); 937 938 PPDMASYNCCOMPLETIONTASK pNext; 939 do 940 { 941 pNext = pEndpointClass->apTaskCache[pEndpoint->iSlotStart]; 942 pTask->pNext = pNext; 943 } while (!ASMAtomicCmpXchgPtr((void * volatile *)&pEndpointClass->apTaskCache[pEndpoint->iSlotStart], (void *)pTask, (void *)pNext)); 944 } 945 else 946 { 947 /* Free it */ 948 MMR3HeapFree(pTask); 949 } 839 RTMemCacheFree(pEndpointClass->hMemCacheTasks, pTask); 950 840 } 951 841 … … 1005 895 pEndpoint->pPrev = NULL; 1006 896 pEndpoint->pEpClass = pEndpointClass; 1007 pEndpoint->pTasksFreeHead = NULL;1008 pEndpoint->pTasksFreeTail = NULL;1009 pEndpoint->cTasksCached = 0;1010 897 pEndpoint->uTaskIdNext = 0; 1011 898 pEndpoint->fTaskIdWraparound = false; 1012 899 pEndpoint->pTemplate = pTemplate; 1013 pEndpoint->iSlotStart = pEndpointClass->cEndpoints % RT_ELEMENTS(pEndpointClass->apTaskCache);1014 900 pEndpoint->pszUri = RTStrDup(pszFilename); 1015 901 pEndpoint->cUsers = 1; … … 1124 1010 && RT_SUCCESS(rc)) 1125 1011 { 1126 /* Init the cache. */ 1127 rc = MMR3HeapAllocZEx(pVM, MM_TAG_PDM_ASYNC_COMPLETION, 1128 pEndpointClass->pEndpointOps->cbTask, 1129 (void **)&pEndpoint->pTasksFreeHead); 1012 /* Call the initializer for the endpoint. */ 1013 rc = pEndpointClass->pEndpointOps->pfnEpInitialize(pEndpoint, pszFilename, fFlags); 1130 1014 if (RT_SUCCESS(rc)) 1131 1015 { 1132 pEndpoint->pTasksFreeTail = pEndpoint->pTasksFreeHead; 1133 1134 /* Call the initializer for the endpoint. */ 1135 rc = pEndpointClass->pEndpointOps->pfnEpInitialize(pEndpoint, pszFilename, fFlags); 1136 if (RT_SUCCESS(rc)) 1137 { 1138 /* Link it into the list of endpoints. */ 1139 rc = RTCritSectEnter(&pEndpointClass->CritSect); 1140 AssertMsg(RT_SUCCESS(rc), ("Failed to enter critical section rc=%Rrc\n", rc)); 1141 1142 pEndpoint->pNext = pEndpointClass->pEndpointsHead; 1143 if (pEndpointClass->pEndpointsHead) 1144 pEndpointClass->pEndpointsHead->pPrev = pEndpoint; 1145 1146 pEndpointClass->pEndpointsHead = pEndpoint; 1147 pEndpointClass->cEndpoints++; 1148 1149 rc = RTCritSectLeave(&pEndpointClass->CritSect); 1150 AssertMsg(RT_SUCCESS(rc), ("Failed to enter critical section rc=%Rrc\n", rc)); 1151 1152 /* Reference the template. */ 1153 ASMAtomicIncU32(&pTemplate->cUsed); 1154 1155 *ppEndpoint = pEndpoint; 1156 1157 LogFlowFunc((": Created endpoint for %s: rc=%Rrc\n", pszFilename, rc)); 1158 return VINF_SUCCESS; 1159 } 1160 MMR3HeapFree(pEndpoint->pTasksFreeHead); 1161 RTStrFree(pEndpoint->pszUri); 1016 /* Link it into the list of endpoints. */ 1017 rc = RTCritSectEnter(&pEndpointClass->CritSect); 1018 AssertMsg(RT_SUCCESS(rc), ("Failed to enter critical section rc=%Rrc\n", rc)); 1019 1020 pEndpoint->pNext = pEndpointClass->pEndpointsHead; 1021 if (pEndpointClass->pEndpointsHead) 1022 pEndpointClass->pEndpointsHead->pPrev = pEndpoint; 1023 1024 pEndpointClass->pEndpointsHead = pEndpoint; 1025 pEndpointClass->cEndpoints++; 1026 1027 rc = RTCritSectLeave(&pEndpointClass->CritSect); 1028 AssertMsg(RT_SUCCESS(rc), ("Failed to enter critical section rc=%Rrc\n", rc)); 1029 1030 /* Reference the template. */ 1031 ASMAtomicIncU32(&pTemplate->cUsed); 1032 1033 *ppEndpoint = pEndpoint; 1034 1035 LogFlowFunc((": Created endpoint for %s: rc=%Rrc\n", pszFilename, rc)); 1036 return VINF_SUCCESS; 1162 1037 } 1163 else 1164 rc = VERR_NO_MEMORY; 1038 RTStrFree(pEndpoint->pszUri); 1165 1039 } 1166 1040 MMR3HeapFree(pEndpoint); … … 1195 1069 PPDMASYNCCOMPLETIONEPCLASS pEndpointClass = pEndpoint->pEpClass; 1196 1070 pEndpointClass->pEndpointOps->pfnEpClose(pEndpoint); 1197 1198 /* Free cached tasks. */1199 PPDMASYNCCOMPLETIONTASK pTask = pEndpoint->pTasksFreeHead;1200 1201 while (pTask)1202 {1203 PPDMASYNCCOMPLETIONTASK pTaskFree = pTask;1204 pTask = pTask->pNext;1205 MMR3HeapFree(pTaskFree);1206 }1207 1071 1208 1072 /* Drop reference from the template. */ … … 1279 1143 } 1280 1144 else 1281 pdmR3AsyncCompletionPutTask(pEndpoint, pTask , false);1145 pdmR3AsyncCompletionPutTask(pEndpoint, pTask); 1282 1146 1283 1147 return rc; … … 1311 1175 } 1312 1176 else 1313 pdmR3AsyncCompletionPutTask(pEndpoint, pTask , false);1177 pdmR3AsyncCompletionPutTask(pEndpoint, pTask); 1314 1178 1315 1179 return rc; … … 1337 1201 } 1338 1202 else 1339 pdmR3AsyncCompletionPutTask(pEndpoint, pTask , false);1203 pdmR3AsyncCompletionPutTask(pEndpoint, pTask); 1340 1204 1341 1205 return rc; -
trunk/src/VBox/VMM/PDMAsyncCompletionInternal.h
r27738 r27883 25 25 #include <iprt/cdefs.h> 26 26 #include <iprt/critsect.h> 27 #include <iprt/memcache.h> 27 28 #include <VBox/types.h> 28 29 #include <VBox/cfgm.h> … … 198 199 /** Pointer to the callback table. */ 199 200 R3PTRTYPE(PCPDMASYNCCOMPLETIONEPCLASSOPS) pEndpointOps; 200 /** Bigger cache for free task items used by all endpoints 201 * of this class. */ 202 R3PTRTYPE(volatile PPDMASYNCCOMPLETIONTASK) apTaskCache[10]; 203 /** Number of tasks cached */ 204 volatile uint32_t cTasksCached; 201 /** Task cache. */ 202 RTMEMCACHE hMemCacheTasks; 205 203 } PDMASYNCCOMPLETIONEPCLASS; 206 204 /** Pointer to the PDM async completion endpoint class data. */ … … 219 217 /** Pointer to the class this endpoint belongs to. */ 220 218 R3PTRTYPE(PPDMASYNCCOMPLETIONEPCLASS) pEpClass; 221 /** Head of the small cache for allocated task structures for exclusive222 * use by this endpoint. */223 R3PTRTYPE(volatile PPDMASYNCCOMPLETIONTASK) pTasksFreeHead;224 /** Tail of the small cache for allocated task structures for exclusive225 * use by this endpoint. */226 R3PTRTYPE(volatile PPDMASYNCCOMPLETIONTASK) pTasksFreeTail;227 /** Number of elements in the cache. */228 volatile uint32_t cTasksCached;229 /** Start slot for the global task cache. */230 unsigned iSlotStart;231 219 /** ID of the next task to ensure consistency. */ 232 220 volatile uint32_t uTaskIdNext;
Note:
See TracChangeset
for help on using the changeset viewer.