Changeset 93609 in vbox
- Timestamp:
- Feb 5, 2022 7:03:08 PM (3 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 24 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/types.h
r93444 r93609 446 446 /** Pointer to a const PDM read/write critical section. */ 447 447 typedef union PDMCRITSECTRW const *PCPDMCRITSECTRW; 448 449 /** PDM queue handle. */ 450 typedef uint64_t PDMQUEUEHANDLE; 451 /** Pointer to a PDM queue handle. */ 452 typedef PDMQUEUEHANDLE *PPDMQUEUEHANDLE; 453 /** NIL PDM queue handle. */ 454 #define NIL_PDMQUEUEHANDLE ((PDMQUEUEHANDLE)UINT64_MAX) 448 455 449 456 /** R3 pointer to a timer. */ -
trunk/include/VBox/vmm/gvm.h
r93594 r93609 247 247 struct PDMR0PERVM s; 248 248 #endif 249 uint8_t padding[ 2176];249 uint8_t padding[3008]; 250 250 } pdmr0; 251 251 … … 300 300 /** Padding so aCpus starts on a page boundrary. */ 301 301 #ifdef VBOX_WITH_NEM_R0 302 uint8_t abPadding2[16384 - 64 - 4352 - 1024 - 256 - 256 - 64 - 2176- 640 - 512 - 64 - 1024 - 128 - 704 - sizeof(PGVMCPU) * VMM_MAX_CPU_COUNT];302 uint8_t abPadding2[16384 - 64 - 4352 - 1024 - 256 - 256 - 64 - 3008 - 640 - 512 - 64 - 1024 - 128 - 704 - sizeof(PGVMCPU) * VMM_MAX_CPU_COUNT]; 303 303 #else 304 uint8_t abPadding2[16384 - 64 - 4352 - 1024 - 256 - 64 - 2176- 640 - 512 - 64 - 1024 - 128 - 704 - sizeof(PGVMCPU) * VMM_MAX_CPU_COUNT];304 uint8_t abPadding2[16384 - 64 - 4352 - 1024 - 256 - 64 - 3008 - 640 - 512 - 64 - 1024 - 128 - 704 - sizeof(PGVMCPU) * VMM_MAX_CPU_COUNT]; 305 305 #endif 306 306 -
trunk/include/VBox/vmm/gvm.mac
r93593 r93609 83 83 .rawpci resb 64 84 84 alignb 64 85 .pdmr0 resb 217685 .pdmr0 resb 3008 86 86 alignb 64 87 87 .pgmr0 resb 640 -
trunk/include/VBox/vmm/pdmapi.h
r93115 r93609 343 343 VMMR0_INT_DECL(int) PDMR0DeviceCompatSetCritSectReqHandler(PGVM pGVM, PPDMDEVICECOMPATSETCRITSECTREQ pReq); 344 344 345 346 /** 347 * Request buffer for PDMR0QueueCreateReqHandler / VMMR0_DO_PDM_QUEUE_CREATE. 348 * @see PDMR0QueueCreateReqHandler. 349 */ 350 typedef struct PDMQUEUECREATEREQ 351 { 352 /** The header. */ 353 SUPVMMR0REQHDR Hdr; 354 355 /** Number of queue items. */ 356 uint32_t cItems; 357 /** Queue item size. */ 358 uint32_t cbItem; 359 /** Owner type (PDMQUEUETYPE). */ 360 uint32_t enmType; 361 /** The ring-3 owner pointer. */ 362 RTR3PTR pvOwner; 363 /** The ring-3 callback function address. */ 364 RTR3PTR pfnCallback; 365 /** The queue name. */ 366 char szName[40]; 367 368 /** Output: The queue handle. */ 369 PDMQUEUEHANDLE hQueue; 370 } PDMQUEUECREATEREQ; 371 /** Pointer to a PDMR0QueueCreateReqHandler / VMMR0_DO_PDM_QUEUE_CREATE request buffer. */ 372 typedef PDMQUEUECREATEREQ *PPDMQUEUECREATEREQ; 373 374 VMMR0_INT_DECL(int) PDMR0QueueCreateReqHandler(PGVM pGVM, PPDMQUEUECREATEREQ pReq); 375 345 376 /** @} */ 346 377 -
trunk/include/VBox/vmm/pdmdev.h
r93115 r93609 4000 4000 4001 4001 DECLR3CALLBACKMEMBER(PPDMQUEUEITEMCORE, pfnQueueAlloc,(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue)); 4002 DECLR3CALLBACKMEMBER( void, pfnQueueInsert,(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue, PPDMQUEUEITEMCORE pItem));4002 DECLR3CALLBACKMEMBER(int, pfnQueueInsert,(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue, PPDMQUEUEITEMCORE pItem)); 4003 4003 DECLR3CALLBACKMEMBER(bool, pfnQueueFlushIfNecessary,(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue)); 4004 4004 /** @} */ … … 5767 5767 * @{ */ 5768 5768 DECLR0CALLBACKMEMBER(PPDMQUEUEITEMCORE, pfnQueueAlloc,(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue)); 5769 DECLR0CALLBACKMEMBER( void, pfnQueueInsert,(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue, PPDMQUEUEITEMCORE pItem));5769 DECLR0CALLBACKMEMBER(int, pfnQueueInsert,(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue, PPDMQUEUEITEMCORE pItem)); 5770 5770 DECLR0CALLBACKMEMBER(bool, pfnQueueFlushIfNecessary,(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue)); 5771 5771 /** @} */ … … 8424 8424 * @copydoc PDMDEVHLPR3::pfnQueueInsert 8425 8425 */ 8426 DECLINLINE( void) PDMDevHlpQueueInsert(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue, PPDMQUEUEITEMCORE pItem)8427 { 8428 pDevIns->CTX_SUFF(pHlp)->pfnQueueInsert(pDevIns, hQueue, pItem);8426 DECLINLINE(int) PDMDevHlpQueueInsert(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue, PPDMQUEUEITEMCORE pItem) 8427 { 8428 return pDevIns->CTX_SUFF(pHlp)->pfnQueueInsert(pDevIns, hQueue, pItem); 8429 8429 } 8430 8430 -
trunk/include/VBox/vmm/pdmdrv.h
r93115 r93609 841 841 842 842 DECLR3CALLBACKMEMBER(PPDMQUEUEITEMCORE, pfnQueueAlloc,(PPDMDRVINS pDrvIns, PDMQUEUEHANDLE hQueue)); 843 DECLR3CALLBACKMEMBER( void, pfnQueueInsert,(PPDMDRVINS pDrvIns, PDMQUEUEHANDLE hQueue, PPDMQUEUEITEMCORE pItem));843 DECLR3CALLBACKMEMBER(int, pfnQueueInsert,(PPDMDRVINS pDrvIns, PDMQUEUEHANDLE hQueue, PPDMQUEUEITEMCORE pItem)); 844 844 DECLR3CALLBACKMEMBER(bool, pfnQueueFlushIfNecessary,(PPDMDRVINS pDrvIns, PDMQUEUEHANDLE hQueue)); 845 845 /** @} */ … … 1705 1705 * @copydoc PDMDRVHLPR3::pfnQueueInsert 1706 1706 */ 1707 DECLINLINE( void) PDMDrvHlpQueueInsert(PPDMDRVINS pDrvIns, PDMQUEUEHANDLE hQueue, PPDMQUEUEITEMCORE pItem)1708 { 1709 pDrvIns->CTX_SUFF(pHlp)->pfnQueueInsert(pDrvIns, hQueue, pItem);1707 DECLINLINE(int) PDMDrvHlpQueueInsert(PPDMDRVINS pDrvIns, PDMQUEUEHANDLE hQueue, PPDMQUEUEITEMCORE pItem) 1708 { 1709 return pDrvIns->CTX_SUFF(pHlp)->pfnQueueInsert(pDrvIns, hQueue, pItem); 1710 1710 } 1711 1711 -
trunk/include/VBox/vmm/pdmqueue.h
r93115 r93609 39 39 */ 40 40 41 /** PDM queue handle. */42 typedef uint64_t PDMQUEUEHANDLE;43 /** NIL PDM queue handle. */44 #define NIL_PDMQUEUEHANDLE UINT64_MAX45 46 41 /** Pointer to a PDM queue. */ 47 42 typedef struct PDMQUEUE *PPDMQUEUE; 48 43 49 44 /** Pointer to a PDM queue item core. */ 50 typedef structPDMQUEUEITEMCORE *PPDMQUEUEITEMCORE;45 typedef union PDMQUEUEITEMCORE *PPDMQUEUEITEMCORE; 51 46 52 47 /** 53 48 * PDM queue item core. 54 49 */ 55 typedef structPDMQUEUEITEMCORE50 typedef union PDMQUEUEITEMCORE 56 51 { 57 /** Pointer to the next item in the pending list - R3 Pointer. */ 58 R3PTRTYPE(PPDMQUEUEITEMCORE) pNextR3; 59 /** Pointer to the next item in the pending list - R0 Pointer. */ 60 R0PTRTYPE(PPDMQUEUEITEMCORE) pNextR0; 52 /** The next queue item on the pending list (UINT32_MAX for NIL). */ 53 uint32_t volatile iNext; 54 /** The next item about to be flushed. */ 55 R3PTRTYPE(PPDMQUEUEITEMCORE) pNext; 56 /** Make sure the core is 64-bit wide. */ 57 uint64_t u64View; 61 58 } PDMQUEUEITEMCORE; 62 59 … … 134 131 135 132 #ifdef VBOX_IN_VMM 136 VMMR3_INT_DECL(int) PDMR3QueueCreateDevice(PVM pVM, PPDMDEVINS pDevIns, size_t cbItem, uint32_t cItems, uint32_t cMilliesInterval, 137 PFNPDMQUEUEDEV pfnCallback, bool fRZEnabled, const char *pszName, PPDMQUEUE *ppQueue); 138 VMMR3_INT_DECL(int) PDMR3QueueCreateDriver(PVM pVM, PPDMDRVINS pDrvIns, size_t cbItem, uint32_t cItems, uint32_t cMilliesInterval, 139 PFNPDMQUEUEDRV pfnCallback, const char *pszName, PPDMQUEUE *ppQueue); 140 VMMR3_INT_DECL(int) PDMR3QueueCreateInternal(PVM pVM, size_t cbItem, uint32_t cItems, uint32_t cMilliesInterval, 141 PFNPDMQUEUEINT pfnCallback, bool fGCEnabled, const char *pszName, PPDMQUEUE *ppQueue); 142 VMMR3_INT_DECL(int) PDMR3QueueCreateExternal(PVM pVM, size_t cbItem, uint32_t cItems, uint32_t cMilliesInterval, 143 PFNPDMQUEUEEXT pfnCallback, void *pvUser, const char *pszName, PPDMQUEUE *ppQueue); 144 VMMR3_INT_DECL(int) PDMR3QueueDestroy(PPDMQUEUE pQueue); 133 VMMR3_INT_DECL(int) PDMR3QueueCreateDevice(PVM pVM, PPDMDEVINS pDevIns, size_t cbItem, uint32_t cItems, 134 uint32_t cMilliesInterval, PFNPDMQUEUEDEV pfnCallback, 135 bool fRZEnabled, const char *pszName, PDMQUEUEHANDLE *phQueue); 136 VMMR3_INT_DECL(int) PDMR3QueueCreateDriver(PVM pVM, PPDMDRVINS pDrvIns, size_t cbItem, uint32_t cItems, 137 uint32_t cMilliesInterval, PFNPDMQUEUEDRV pfnCallback, 138 const char *pszName, PDMQUEUEHANDLE *phQueue); 139 VMMR3_INT_DECL(int) PDMR3QueueCreateInternal(PVM pVM, size_t cbItem, uint32_t cItems, 140 uint32_t cMilliesInterval, PFNPDMQUEUEINT pfnCallback, 141 bool fRZEnabled, const char *pszName, PDMQUEUEHANDLE *phQueue); 142 VMMR3DECL(int) PDMR3QueueCreateExternal(PVM pVM, size_t cbItem, uint32_t cItems, uint32_t cMilliesInterval, 143 PFNPDMQUEUEEXT pfnCallback, void *pvUser, const char *pszName, PDMQUEUEHANDLE *phQueue); 144 VMMR3DECL(int) PDMR3QueueDestroy(PVM pVM, PDMQUEUEHANDLE hQueue, void *pvOwner); 145 145 VMMR3_INT_DECL(int) PDMR3QueueDestroyDevice(PVM pVM, PPDMDEVINS pDevIns); 146 146 VMMR3_INT_DECL(int) PDMR3QueueDestroyDriver(PVM pVM, PPDMDRVINS pDrvIns); 147 VMMR3 _INT_DECL(void)PDMR3QueueFlushAll(PVM pVM);147 VMMR3DECL(void) PDMR3QueueFlushAll(PVM pVM); 148 148 #endif /* VBOX_IN_VMM */ 149 149 150 VMMDECL(PPDMQUEUEITEMCORE) PDMQueueAlloc(PPDMQUEUE pQueue); 151 VMMDECL(void) PDMQueueInsert(PPDMQUEUE pQueue, PPDMQUEUEITEMCORE pItem); 152 VMMDECL(void) PDMQueueInsertEx(PPDMQUEUE pQueue, PPDMQUEUEITEMCORE pItem, uint64_t NanoMaxDelay); 153 VMMDECL(R0PTRTYPE(PPDMQUEUE)) PDMQueueR0Ptr(PPDMQUEUE pQueue); 154 VMMDECL(bool) PDMQueueFlushIfNecessary(PPDMQUEUE pQueue); 150 VMMDECL(PPDMQUEUEITEMCORE) PDMQueueAlloc(PVMCC pVM, PDMQUEUEHANDLE hQueue, void *pvOwner); 151 VMMDECL(int) PDMQueueInsert(PVMCC pVM, PDMQUEUEHANDLE hQueue, void *pvOwner, PPDMQUEUEITEMCORE pInsert); 152 VMMDECL(int) PDMQueueFlushIfNecessary(PVMCC pVM, PDMQUEUEHANDLE hQueue, void *pvOwner); 155 153 156 154 /** @} */ -
trunk/include/VBox/vmm/vm.h
r93593 r93609 1323 1323 struct PDM s; 1324 1324 #endif 1325 uint8_t padding[8 320]; /* multiple of 64 */1325 uint8_t padding[8448]; /* multiple of 64 */ 1326 1326 } pdm; 1327 1327 … … 1458 1458 1459 1459 /** Padding for aligning the structure size on a page boundrary. */ 1460 uint8_t abAlignment2[6 616- sizeof(PVMCPUR3) * VMM_MAX_CPU_COUNT];1460 uint8_t abAlignment2[6488 - sizeof(PVMCPUR3) * VMM_MAX_CPU_COUNT]; 1461 1461 1462 1462 /* ---- end small stuff ---- */ … … 1468 1468 } VM; 1469 1469 #ifndef VBOX_FOR_DTRACE_LIB 1470 AssertCompileSizeAlignment(VM, 16384);1470 //AssertCompileSizeAlignment(VM, 16384); 1471 1471 #endif 1472 1472 -
trunk/include/VBox/vmm/vm.mac
r93593 r93609 143 143 .mm resb 192 144 144 alignb 64 145 .pdm resb 8 320145 .pdm resb 8448 146 146 alignb 64 147 147 .iom resb 1152 -
trunk/include/VBox/vmm/vmm.h
r93470 r93609 321 321 /** Old style device compat: Set ring-0 critical section. */ 322 322 VMMR0_DO_PDM_DEVICE_COMPAT_SET_CRITSECT, 323 /** Call PDMR0QueueCreateReqHandler. */ 324 VMMR0_DO_PDM_QUEUE_CREATE, 323 325 324 326 /** Set a GVMM or GMM configuration value. */ -
trunk/include/VBox/vmm/vmmr3vtable-def.h
r93470 r93609 609 609 VTABLE_ENTRY(PDMQueueAlloc) 610 610 VTABLE_ENTRY(PDMQueueInsert) 611 VTABLE_ ENTRY(PDMQueueInsertEx)611 VTABLE_RESERVED(pfnPDMR3Reserved11) 612 612 613 613 VTABLE_ENTRY(PDMR3ThreadDestroy) -
trunk/src/VBox/VMM/Makefile.kmk
r93595 r93609 488 488 $(if-expr defined(VBOX_WITH_DBGF_TRACING), VMMR0/PDMR0DevHlpTracing.cpp,) \ 489 489 VMMR0/PDMR0Driver.cpp \ 490 VMMR0/PDMR0Queue.cpp \ 490 491 VMMR0/PGMR0.cpp \ 491 492 VMMR0/PGMR0Pool.cpp \ -
trunk/src/VBox/VMM/VMMAll/PDMAll.cpp
r93115 r93609 212 212 { 213 213 /* Queue for ring-3 execution. */ 214 PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)PDMQueueAlloc(pVM ->pdm.s.pDevHlpQueueR0);214 PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)PDMQueueAlloc(pVM, pVM->pdm.s.hDevHlpQueue, pVM); 215 215 if (pTask) 216 216 { … … 218 218 pTask->pDevInsR3 = NIL_RTR3PTR; /* not required */ 219 219 pTask->u.IoApicSetEoi.uVector = uVector; 220 PDMQueueInsert Ex(pVM->pdm.s.pDevHlpQueueR0, &pTask->Core, 0);220 PDMQueueInsert(pVM, pVM->pdm.s.hDevHlpQueue, pVM, &pTask->Core); 221 221 } 222 222 else … … 250 250 { 251 251 /* Queue for ring-3 execution. */ 252 PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)PDMQueueAlloc(pVM ->pdm.s.pDevHlpQueueR0);252 PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)PDMQueueAlloc(pVM, pVM->pdm.s.hDevHlpQueue, pVM); 253 253 if (pTask) 254 254 { … … 258 258 pTask->u.IoApicSendMsi.Msi = *pMsi; 259 259 pTask->u.IoApicSendMsi.uTagSrc = uTagSrc; 260 PDMQueueInsert Ex(pVM->pdm.s.pDevHlpQueueR0, &pTask->Core, 0);260 PDMQueueInsert(pVM, pVM->pdm.s.hDevHlpQueue, pVM, &pTask->Core); 261 261 } 262 262 else -
trunk/src/VBox/VMM/VMMAll/PDMAllQueue.cpp
r93115 r93609 31 31 #include <iprt/asm.h> 32 32 #include <iprt/assert.h> 33 34 35 /** 36 * Allocate an item from a queue. 33 #include <iprt/string.h> 34 35 36 /********************************************************************************************************************************* 37 * Defined Constants And Macros * 38 *********************************************************************************************************************************/ 39 /* 40 * Macros for thoroughly validating a queue handle and ownership. 41 */ 42 #define PDMQUEUE_HANDLE_TO_VARS_RETURN_COMMON(a_cbMax, a_cbTotalMax) \ 43 AssertReturn(cbItem >= sizeof(PDMQUEUEITEMCORE), pQueue->rcOkay = VERR_INTERNAL_ERROR_4); \ 44 AssertReturn(cbItem <= (a_cbMax), pQueue->rcOkay = VERR_INTERNAL_ERROR_4); \ 45 \ 46 /* paranoia^3: */ \ 47 AssertReturn(cItems > 0, pQueue->rcOkay = VERR_INTERNAL_ERROR_4); \ 48 AssertReturn(cItems <= PDMQUEUE_MAX_ITEMS, pQueue->rcOkay = VERR_INTERNAL_ERROR_4); \ 49 AssertReturn(cbItem * cItems <= (a_cbTotalMax), pQueue->rcOkay = VERR_INTERNAL_ERROR_4) 50 51 #ifdef IN_RING0 52 # define PDMQUEUE_HANDLE_TO_VARS_RETURN(a_pVM, a_hQueue, a_pvOwner) \ 53 AssertPtrReturn((a_pvOwner), VERR_INVALID_PARAMETER); \ 54 \ 55 AssertCompile(RT_ELEMENTS((a_pVM)->pdm.s.apRing0Queues) == RT_ELEMENTS((a_pVM)->pdmr0.s.aQueues)); \ 56 AssertReturn((a_hQueue) < RT_ELEMENTS((a_pVM)->pdmr0.s.aQueues), VERR_INVALID_HANDLE); \ 57 AssertReturn((a_hQueue) < (a_pVM)->pdmr0.s.cQueues, VERR_INVALID_HANDLE); \ 58 AssertReturn((a_pVM)->pdmr0.s.aQueues[(a_hQueue)].pvOwner == (a_pvOwner), VERR_INVALID_HANDLE); \ 59 PPDMQUEUE pQueue = (a_pVM)->pdmr0.s.aQueues[(a_hQueue)].pQueue; \ 60 AssertPtrReturn(pQueue, VERR_INVALID_HANDLE); \ 61 AssertReturn(pQueue->u32Magic == PDMQUEUE_MAGIC, VERR_INVALID_HANDLE); \ 62 AssertReturn(pQueue->rcOkay == VINF_SUCCESS, pQueue->rcOkay); \ 63 \ 64 uint32_t const cbItem = (a_pVM)->pdmr0.s.aQueues[(a_hQueue)].cbItem; \ 65 uint32_t const cItems = (a_pVM)->pdmr0.s.aQueues[(a_hQueue)].cItems; \ 66 uint32_t const offItems = (a_pVM)->pdmr0.s.aQueues[(a_hQueue)].offItems; \ 67 \ 68 /* paranoia^2: */ \ 69 AssertReturn(pQueue->cbItem == cbItem, pQueue->rcOkay = VERR_INTERNAL_ERROR_3); \ 70 AssertReturn(pQueue->cItems == cItems, pQueue->rcOkay = VERR_INTERNAL_ERROR_3); \ 71 AssertReturn(pQueue->offItems == offItems, pQueue->rcOkay = VERR_INTERNAL_ERROR_3); \ 72 \ 73 PDMQUEUE_HANDLE_TO_VARS_RETURN_COMMON(PDMQUEUE_MAX_ITEM_SIZE, PDMQUEUE_MAX_TOTAL_SIZE_R0) 74 75 #else 76 # define PDMQUEUE_HANDLE_TO_VARS_RETURN(a_pVM, a_hQueue, a_pvOwner) \ 77 AssertPtrReturn((a_pvOwner), VERR_INVALID_PARAMETER); \ 78 \ 79 PPDMQUEUE pQueue; \ 80 if ((a_hQueue) < RT_ELEMENTS((a_pVM)->pdm.s.apRing0Queues)) \ 81 pQueue = (a_pVM)->pdm.s.apRing0Queues[(a_hQueue)]; \ 82 else \ 83 { \ 84 (a_hQueue) -= RT_ELEMENTS((a_pVM)->pdm.s.apRing0Queues); \ 85 AssertReturn((a_pVM)->pdm.s.cRing3Queues, VERR_INVALID_HANDLE); \ 86 pQueue = (a_pVM)->pdm.s.papRing3Queues[(a_hQueue)]; \ 87 } \ 88 AssertPtrReturn(pQueue, VERR_INVALID_HANDLE); \ 89 AssertReturn(pQueue->u32Magic == PDMQUEUE_MAGIC, VERR_INVALID_HANDLE); \ 90 AssertReturn(pQueue->u.Gen.pvOwner == (a_pvOwner), VERR_INVALID_HANDLE); \ 91 AssertReturn(pQueue->rcOkay == VINF_SUCCESS, pQueue->rcOkay); \ 92 \ 93 uint32_t const cbItem = pQueue->cbItem; \ 94 uint32_t const cItems = pQueue->cItems; \ 95 uint32_t const offItems = pQueue->offItems; \ 96 \ 97 PDMQUEUE_HANDLE_TO_VARS_RETURN_COMMON(PDMQUEUE_MAX_ITEM_SIZE, PDMQUEUE_MAX_TOTAL_SIZE_R3) 98 99 #endif 100 101 102 /** 103 * Commmon function for initializing the shared queue structure. 104 */ 105 void pdmQueueInit(PPDMQUEUE pQueue, uint32_t cbBitmap, uint32_t cbItem, uint32_t cItems, 106 const char *pszName, PDMQUEUETYPE enmType, RTR3PTR pfnCallback, RTR3PTR pvOwner) 107 { 108 Assert(cbBitmap * 8 >= cItems); 109 110 pQueue->u32Magic = PDMQUEUE_MAGIC; 111 pQueue->cbItem = cbItem; 112 pQueue->cItems = cItems; 113 pQueue->offItems = RT_UOFFSETOF(PDMQUEUE, bmAlloc) + cbBitmap; 114 pQueue->rcOkay = VINF_SUCCESS; 115 pQueue->u32Padding = 0; 116 pQueue->hTimer = NIL_TMTIMERHANDLE; 117 pQueue->cMilliesInterval = 0; 118 pQueue->enmType = enmType; 119 pQueue->u.Gen.pfnCallback = pfnCallback; 120 pQueue->u.Gen.pvOwner = pvOwner; 121 RTStrCopy(pQueue->szName, sizeof(pQueue->szName), pszName); 122 pQueue->iPending = UINT32_MAX; 123 RT_BZERO(pQueue->bmAlloc, cbBitmap); 124 ASMBitSetRange(pQueue->bmAlloc, 0, cItems); 125 126 uint8_t *pbItem = (uint8_t *)&pQueue->bmAlloc[0] + cbBitmap; 127 while (cItems-- > 0) 128 { 129 ((PPDMQUEUEITEMCORE)pbItem)->u64View = UINT64_C(0xfeedfeedfeedfeed); 130 131 /* next */ 132 pbItem += cbItem; 133 } 134 } 135 136 137 /** 138 * Allocate an item from a queue, extended version. 139 * 37 140 * The allocated item must be handed on to PDMR3QueueInsert() after the 38 141 * data have been filled in. 39 142 * 40 * @returns Pointer to allocated queue item. 41 * @returns NULL on failure. The queue is exhausted. 42 * @param pQueue The queue handle. 143 * @returns VBox status code. 144 * @param pVM Pointer to the cross context VM structure w/ ring-0. 145 * @param hQueue The queue handle. 146 * @param pvOwner The queue owner. 147 * @param ppNew Where to return the item pointer on success. 43 148 * @thread Any thread. 44 149 */ 45 VMMDECL(PPDMQUEUEITEMCORE) PDMQueueAlloc(PPDMQUEUE pQueue) 46 { 47 Assert(RT_VALID_PTR(pQueue) && pQueue->CTX_SUFF(pVM)); 48 PPDMQUEUEITEMCORE pNew; 49 uint32_t iNext; 50 uint32_t i; 51 do 150 VMMDECL(int) PDMQueueAllocEx(PVMCC pVM, PDMQUEUEHANDLE hQueue, void *pvOwner, PPDMQUEUEITEMCORE *ppNew) 151 { 152 /* 153 * Validate and translate input. 154 */ 155 *ppNew = NULL; 156 PDMQUEUE_HANDLE_TO_VARS_RETURN(pVM, hQueue, pvOwner); 157 158 /* 159 * Do the allocation. 160 */ 161 uint32_t cEmptyScans = 0; 162 for (;;) 52 163 { 53 i = pQueue->iFreeTail; 54 if (i == pQueue->iFreeHead) 164 int32_t iBit = ASMBitFirstSet(pQueue->bmAlloc, cItems); 165 if (iBit >= 0) 166 { 167 if (ASMAtomicBitTestAndClear(pQueue->bmAlloc, iBit)) 168 { 169 PPDMQUEUEITEMCORE pNew = (PPDMQUEUEITEMCORE)&((uint8_t *)pQueue)[offItems + iBit * cbItem]; 170 pNew->u64View = UINT64_C(0xbeefbeefbeefbeef); 171 *ppNew = pNew; 172 return VINF_SUCCESS; 173 } 174 cEmptyScans = 0; 175 } 176 else if (++cEmptyScans < 16) 177 ASMNopPause(); 178 else 55 179 { 56 180 STAM_REL_COUNTER_INC(&pQueue->StatAllocFailures); 57 return NULL;181 return VERR_OUT_OF_RESOURCES; 58 182 } 59 pNew = pQueue->aFreeItems[i].CTX_SUFF(pItem); 60 iNext = (i + 1) % (pQueue->cItems + PDMQUEUE_FREE_SLACK); 61 } while (!ASMAtomicCmpXchgU32(&pQueue->iFreeTail, iNext, i)); 62 return pNew; 183 } 184 } 185 186 187 /** 188 * Allocate an item from a queue. 189 * 190 * The allocated item must be handed on to PDMR3QueueInsert() after the 191 * data have been filled in. 192 * 193 * @returns VBox status code. 194 * @param pVM Pointer to the cross context VM structure w/ ring-0. 195 * @param hQueue The queue handle. 196 * @param pvOwner The queue owner. 197 * @param ppNew Where to return the item pointer on success. 198 * @thread Any thread. 199 */ 200 VMMDECL(PPDMQUEUEITEMCORE) PDMQueueAlloc(PVMCC pVM, PDMQUEUEHANDLE hQueue, void *pvOwner) 201 { 202 PPDMQUEUEITEMCORE pNew = NULL; 203 int rc = PDMQueueAllocEx(pVM, hQueue, pvOwner, &pNew); 204 if (RT_SUCCESS(rc)) 205 return pNew; 206 return NULL; 63 207 } 64 208 … … 67 211 * Sets the FFs and fQueueFlushed. 68 212 * 69 * @param pQueue The PDM queue. 70 */ 71 static void pdmQueueSetFF(PPDMQUEUE pQueue) 72 { 73 PVM pVM = pQueue->CTX_SUFF(pVM); 213 * @param pVM Pointer to the cross context VM structure w/ ring-0. 214 */ 215 static void pdmQueueSetFF(PVMCC pVM) 216 { 74 217 Log2(("PDMQueueInsert: VM_FF_PDM_QUEUES %d -> 1\n", VM_FF_IS_SET(pVM, VM_FF_PDM_QUEUES))); 75 218 VM_FF_SET(pVM, VM_FF_PDM_QUEUES); … … 87 230 * have been passed to this function it must not be touched! 88 231 * 89 * @param pQueue The queue handle. 90 * @param pItem The item to insert. 232 * @returns VBox status code. 233 * @param pVM Pointer to the cross context VM structure w/ ring-0. 234 * @param hQueue The queue handle. 235 * @param pvOwner The queue owner. 236 * @param pInsert The item to insert. 91 237 * @thread Any thread. 92 238 */ 93 VMMDECL(void) PDMQueueInsert(PPDMQUEUE pQueue, PPDMQUEUEITEMCORE pItem) 94 { 95 Assert(RT_VALID_PTR(pQueue) && pQueue->CTX_SUFF(pVM)); 96 AssertPtr(pItem); 97 98 #if 0 /* the paranoid android version: */ 99 void *pvNext; 100 do 239 VMMDECL(int) PDMQueueInsert(PVMCC pVM, PDMQUEUEHANDLE hQueue, void *pvOwner, PPDMQUEUEITEMCORE pInsert) 240 { 241 /* 242 * Validate and translate input. 243 */ 244 PDMQUEUE_HANDLE_TO_VARS_RETURN(pVM, hQueue, pvOwner); 245 246 uint8_t * const pbItems = (uint8_t *)pQueue + offItems; 247 uintptr_t const offInsert = (uintptr_t)pInsert - (uintptr_t)pbItems; 248 uintptr_t const iInsert = offInsert / cbItem; 249 AssertReturn(iInsert < cItems, VERR_INVALID_PARAMETER); 250 AssertReturn(iInsert * cbItem == offInsert, VERR_INVALID_PARAMETER); 251 252 AssertReturn(ASMBitTest(pQueue->bmAlloc, iInsert) == false, VERR_INVALID_PARAMETER); 253 254 /* 255 * Append the item to the pending list. 256 */ 257 for (;;) 101 258 { 102 pvNext = ASMAtomicUoReadPtr((void * volatile *)&pQueue->CTX_SUFF(pPending)); 103 ASMAtomicUoWritePtr((void * volatile *)&pItem->CTX_SUFF(pNext), pvNext); 104 } while (!ASMAtomicCmpXchgPtr(&pQueue->CTX_SUFF(pPending), pItem, pvNext)); 105 #else 106 PPDMQUEUEITEMCORE pNext; 107 do 108 { 109 pNext = pQueue->CTX_SUFF(pPending); 110 pItem->CTX_SUFF(pNext) = pNext; 111 } while (!ASMAtomicCmpXchgPtr(&pQueue->CTX_SUFF(pPending), pItem, pNext)); 112 #endif 259 uint32_t const iOldPending = ASMAtomicUoReadU32(&pQueue->iPending); 260 pInsert->iNext = iOldPending; 261 if (ASMAtomicCmpXchgU32(&pQueue->iPending, iInsert, iOldPending)) 262 break; 263 ASMNopPause(); 264 } 113 265 114 266 if (pQueue->hTimer == NIL_TMTIMERHANDLE) 115 pdmQueueSetFF(p Queue);267 pdmQueueSetFF(pVM); 116 268 STAM_REL_COUNTER_INC(&pQueue->StatInsert); 117 269 STAM_STATS({ ASMAtomicIncU32(&pQueue->cStatPending); }); 118 } 119 120 121 /** 122 * Queue an item. 123 * 124 * The item must have been obtained using PDMQueueAlloc(). Once the item 125 * have been passed to this function it must not be touched! 126 * 127 * @param pQueue The queue handle. 128 * @param pItem The item to insert. 129 * @param NanoMaxDelay The maximum delay before processing the queue, in nanoseconds. 130 * This applies only to GC. 131 * @thread Any thread. 132 */ 133 VMMDECL(void) PDMQueueInsertEx(PPDMQUEUE pQueue, PPDMQUEUEITEMCORE pItem, uint64_t NanoMaxDelay) 134 { 135 NOREF(NanoMaxDelay); 136 PDMQueueInsert(pQueue, pItem); 137 #ifdef IN_RC 138 PVM pVM = pQueue->CTX_SUFF(pVM); 139 /** @todo figure out where to put this, the next bit should go there too. 140 if (NanoMaxDelay) 270 271 return VINF_SUCCESS; 272 } 273 274 275 /** 276 * Schedule the queue for flushing (processing) if necessary. 277 * 278 * @returns VBox status code. 279 * @retval VINF_SUCCESS if a flush was necessary. 280 * @retval VINF_NO_CHANGE if no flushing needed. 281 * 282 * @param pVM The cross context VM structure. 283 * @param pvOwner The alleged queue owner. 284 * @param hQueue The queueu to maybe flush. 285 */ 286 VMMDECL(int) PDMQueueFlushIfNecessary(PVMCC pVM, PDMQUEUEHANDLE hQueue, void *pvOwner) 287 { 288 /* 289 * Validate input. 290 */ 291 PDMQUEUE_HANDLE_TO_VARS_RETURN(pVM, hQueue, pvOwner); 292 RT_NOREF(offItems); 293 294 /* 295 * Check and maybe flush. 296 */ 297 if (ASMAtomicUoReadU32(&pQueue->iPending) != UINT32_MAX) 141 298 { 142 299 pdmQueueSetFF(pVM); 300 return VINF_SUCCESS; 143 301 } 144 else */ 145 { 146 VMCPU_FF_SET(VMMGetCpu0(pVM), VMCPU_FF_TO_R3); 147 Log2(("PDMQueueInsertEx: Setting VMCPU_FF_TO_R3\n")); 148 } 149 #endif 150 } 151 152 153 /** 154 * Gets the ring-0 pointer for the specified queue. 155 * 156 * @returns The ring-0 address of the queue. 157 * @returns NULL if pQueue is invalid. 158 * @param pQueue The queue handle. 159 */ 160 VMMDECL(R0PTRTYPE(PPDMQUEUE)) PDMQueueR0Ptr(PPDMQUEUE pQueue) 161 { 162 AssertPtr(pQueue); 163 Assert(pQueue->pVMR3); 164 #ifdef IN_RING0 165 AssertPtr(pQueue->pVMR0); 166 return pQueue; 167 #else 168 Assert(pQueue->pVMR0 || SUPR3IsDriverless()); 169 return MMHyperCCToR0(pQueue->CTX_SUFF(pVM), pQueue); 170 #endif 171 } 172 173 174 /** 175 * Schedule the queue for flushing (processing) if necessary. 176 * 177 * @returns @c true if necessary, @c false if not. 178 * @param pQueue The queue. 179 */ 180 VMMDECL(bool) PDMQueueFlushIfNecessary(PPDMQUEUE pQueue) 181 { 182 AssertPtr(pQueue); 183 if ( pQueue->pPendingR3 != NIL_RTR3PTR 184 || pQueue->pPendingR0 != NIL_RTR0PTR) 185 { 186 pdmQueueSetFF(pQueue); 187 return false; 188 } 189 return false; 190 } 191 302 return VINF_NO_CHANGE; 303 } 304 -
trunk/src/VBox/VMM/VMMR0/PDMR0DevHlp.cpp
r93115 r93609 245 245 246 246 /* queue for ring-3 execution. */ 247 PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)PDMQueueAlloc(pGVM ->pdm.s.pDevHlpQueueR0);247 PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)PDMQueueAlloc(pGVM, pGVM->pdm.s.hDevHlpQueue, pGVM); 248 248 AssertReturnVoid(pTask); 249 249 … … 253 253 pTask->u.PciSetIrq.iLevel = iLevel; 254 254 pTask->u.PciSetIrq.uTagSrc = uTagSrc; 255 pTask->u.PciSetIrq. pPciDevR3 = MMHyperR0ToR3(pGVM, pPciDev);256 257 PDMQueueInsert Ex(pGVM->pdm.s.pDevHlpQueueR0, &pTask->Core, 0);255 pTask->u.PciSetIrq.idxPciDev = pPciDev->Int.s.idxSubDev; 256 257 PDMQueueInsert(pGVM, pGVM->pdm.s.hDevHlpQueue, pGVM, &pTask->Core); 258 258 } 259 259 … … 581 581 582 582 583 /** Converts a queue handle to a ring-0 queue pointer. */584 DECLINLINE(PPDMQUEUE) pdmR0DevHlp_QueueToPtr(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue)585 {586 PDMDEV_ASSERT_DEVINS(pDevIns);587 return (PPDMQUEUE)MMHyperR3ToCC(pDevIns->Internal.s.pGVM, hQueue);588 }589 590 591 583 /** @interface_method_impl{PDMDEVHLPR0,pfnQueueAlloc} */ 592 584 static DECLCALLBACK(PPDMQUEUEITEMCORE) pdmR0DevHlp_QueueAlloc(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue) 593 585 { 594 return PDMQueueAlloc(pdmR0DevHlp_QueueToPtr(pDevIns, hQueue)); 586 PDMDEV_ASSERT_DEVINS(pDevIns); 587 return PDMQueueAlloc(pDevIns->Internal.s.pGVM, hQueue, pDevIns); 595 588 } 596 589 597 590 598 591 /** @interface_method_impl{PDMDEVHLPR0,pfnQueueInsert} */ 599 static DECLCALLBACK(void) pdmR0DevHlp_QueueInsert(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue, PPDMQUEUEITEMCORE pItem) 600 { 601 return PDMQueueInsert(pdmR0DevHlp_QueueToPtr(pDevIns, hQueue), pItem); 592 static DECLCALLBACK(int) pdmR0DevHlp_QueueInsert(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue, PPDMQUEUEITEMCORE pItem) 593 { 594 PDMDEV_ASSERT_DEVINS(pDevIns); 595 return PDMQueueInsert(pDevIns->Internal.s.pGVM, hQueue, pDevIns, pItem); 602 596 } 603 597 … … 606 600 static DECLCALLBACK(bool) pdmR0DevHlp_QueueFlushIfNecessary(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue) 607 601 { 608 return PDMQueueFlushIfNecessary(pdmR0DevHlp_QueueToPtr(pDevIns, hQueue)); 602 PDMDEV_ASSERT_DEVINS(pDevIns); 603 return PDMQueueFlushIfNecessary(pDevIns->Internal.s.pGVM, hQueue, pDevIns) == VINF_SUCCESS; 609 604 } 610 605 … … 1786 1781 { 1787 1782 /* queue for ring-3 execution. */ 1788 PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)PDMQueueAlloc(pGVM ->pdm.s.pDevHlpQueueR0);1783 PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)PDMQueueAlloc(pGVM, pGVM->pdm.s.hDevHlpQueue, pGVM); 1789 1784 if (pTask) 1790 1785 { … … 1796 1791 pTask->u.IoApicSetIrq.uTagSrc = uTagSrc; 1797 1792 1798 PDMQueueInsert Ex(pGVM->pdm.s.pDevHlpQueueR0, &pTask->Core, 0);1793 PDMQueueInsert(pGVM, pGVM->pdm.s.hDevHlpQueue, pGVM, &pTask->Core); 1799 1794 } 1800 1795 else … … 1975 1970 1976 1971 /* queue for ring-3 execution. */ 1977 PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)PDMQueueAlloc(pGVM ->pdm.s.pDevHlpQueueR0);1972 PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)PDMQueueAlloc(pGVM, pGVM->pdm.s.hDevHlpQueue, pGVM); 1978 1973 AssertReturn(pTask, false); 1979 1974 … … 1985 1980 pTask->u.IsaSetIrq.uTagSrc = uTagSrc; 1986 1981 1987 PDMQueueInsert Ex(pGVM->pdm.s.pDevHlpQueueR0, &pTask->Core, 0);1982 PDMQueueInsert(pGVM, pGVM->pdm.s.hDevHlpQueue, pGVM, &pTask->Core); 1988 1983 return false; 1989 1984 } -
trunk/src/VBox/VMM/VMMR0/PDMR0DevHlpTracing.cpp
r93115 r93609 408 408 409 409 /* queue for ring-3 execution. */ 410 PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)PDMQueueAlloc(pGVM ->pdm.s.pDevHlpQueueR0);410 PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)PDMQueueAlloc(pGVM, pGVM->pdm.s.hDevHlpQueue, pGVM); 411 411 AssertReturnVoid(pTask); 412 412 … … 416 416 pTask->u.PciSetIrq.iLevel = iLevel; 417 417 pTask->u.PciSetIrq.uTagSrc = uTagSrc; 418 pTask->u.PciSetIrq. pPciDevR3 = MMHyperR0ToR3(pGVM, pPciDev);419 420 PDMQueueInsert Ex(pGVM->pdm.s.pDevHlpQueueR0, &pTask->Core, 0);418 pTask->u.PciSetIrq.idxPciDev = pPciDev->Int.s.idxSubDev; 419 420 PDMQueueInsert(pGVM, pGVM->pdm.s.hDevHlpQueue, pGVM, &pTask->Core); 421 421 } 422 422 -
trunk/src/VBox/VMM/VMMR0/PDMR0Device.cpp
r93554 r93609 193 193 if (pDevIns) 194 194 pdmR0DeviceDestroy(pGVM, pDevIns, i); 195 } 196 197 i = pGVM->pdmr0.s.cQueues; 198 while (i-- > 0) 199 { 200 if (pGVM->pdmr0.s.aQueues[i].pQueue != NULL) 201 pdmR0QueueDestroy(pGVM, i); 195 202 } 196 203 } -
trunk/src/VBox/VMM/VMMR0/VMMR0.cpp
r93554 r93609 2072 2072 } 2073 2073 2074 case VMMR0_DO_PDM_QUEUE_CREATE: 2075 { 2076 if (!pReqHdr || u64Arg || idCpu != 0) 2077 return VERR_INVALID_PARAMETER; 2078 rc = PDMR0QueueCreateReqHandler(pGVM, (PPDMQUEUECREATEREQ)pReqHdr); 2079 break; 2080 } 2081 2074 2082 /* 2075 2083 * Requests to the internal networking service. -
trunk/src/VBox/VMM/VMMR3/PDMDevHlp.cpp
r93554 r93609 2747 2747 } 2748 2748 2749 PPDMQUEUE pQueue = NULL; 2750 int rc = PDMR3QueueCreateDevice(pVM, pDevIns, cbItem, cItems, cMilliesInterval, pfnCallback, fRZEnabled, pszName, &pQueue); 2751 *phQueue = (uintptr_t)pQueue; 2752 2753 LogFlow(("pdmR3DevHlp_QueueCreate: caller='%s'/%d: returns %Rrc *ppQueue=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, rc, *phQueue)); 2749 int rc = PDMR3QueueCreateDevice(pVM, pDevIns, cbItem, cItems, cMilliesInterval, pfnCallback, fRZEnabled, pszName, phQueue); 2750 2751 LogFlow(("pdmR3DevHlp_QueueCreate: caller='%s'/%d: returns %Rrc *phQueue=%p\n", 2752 pDevIns->pReg->szName, pDevIns->iInstance, rc, *phQueue)); 2754 2753 return rc; 2755 2754 } … … 2770 2769 static DECLCALLBACK(PPDMQUEUEITEMCORE) pdmR3DevHlp_QueueAlloc(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue) 2771 2770 { 2772 return PDMQueueAlloc(pdmR3DevHlp_QueueToPtr(pDevIns, hQueue)); 2771 PDMDEV_ASSERT_DEVINS(pDevIns); 2772 return PDMQueueAlloc(pDevIns->Internal.s.pVMR3, hQueue, pDevIns); 2773 2773 } 2774 2774 2775 2775 2776 2776 /** @interface_method_impl{PDMDEVHLPR3,pfnQueueInsert} */ 2777 static DECLCALLBACK( void) pdmR3DevHlp_QueueInsert(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue, PPDMQUEUEITEMCORE pItem)2778 { 2779 return PDMQueueInsert(p dmR3DevHlp_QueueToPtr(pDevIns, hQueue), pItem);2777 static DECLCALLBACK(int) pdmR3DevHlp_QueueInsert(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue, PPDMQUEUEITEMCORE pItem) 2778 { 2779 return PDMQueueInsert(pDevIns->Internal.s.pVMR3, hQueue, pDevIns, pItem); 2780 2780 } 2781 2781 … … 2784 2784 static DECLCALLBACK(bool) pdmR3DevHlp_QueueFlushIfNecessary(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue) 2785 2785 { 2786 return PDMQueueFlushIfNecessary(p dmR3DevHlp_QueueToPtr(pDevIns, hQueue));2786 return PDMQueueFlushIfNecessary(pDevIns->Internal.s.pVMR3, hQueue, pDevIns) == VINF_SUCCESS; 2787 2787 } 2788 2788 … … 6360 6360 { 6361 6361 /* Same as pdmR3DevHlp_PCISetIrq, except we've got a tag already. */ 6362 PPDMPCIDEV pPciDev = pTask->u.PciSetIrq.pPciDevR3; 6362 PPDMDEVINSR3 pDevIns = pTask->pDevInsR3; 6363 PPDMPCIDEV pPciDev = pTask->u.PciSetIrq.idxPciDev < RT_ELEMENTS(pDevIns->apPciDevs) 6364 ? pDevIns->apPciDevs[pTask->u.PciSetIrq.idxPciDev] : NULL; 6363 6365 if (pPciDev) 6364 6366 { … … 6373 6375 } 6374 6376 else 6375 AssertReleaseMsgFailed(("No PCI device registered!\n"));6377 AssertReleaseMsgFailed(("No PCI device given! (%#x)\n", pPciDev->Int.s.idxSubDev)); 6376 6378 break; 6377 6379 } -
trunk/src/VBox/VMM/VMMR3/PDMDevice.cpp
r93115 r93609 131 131 * Get the RC & R0 devhlps and create the devhlp R3 task queue. 132 132 */ 133 rc = PDMR3QueueCreateInternal(pVM, sizeof(PDMDEVHLPTASK), 8, 0, pdmR3DevHlpQueueConsumer, true, "DevHlp",134 &pVM->pdm.s. pDevHlpQueueR3);133 rc = PDMR3QueueCreateInternal(pVM, sizeof(PDMDEVHLPTASK), pVM->cCpus * 8, 0, pdmR3DevHlpQueueConsumer, true, "DevHlp", 134 &pVM->pdm.s.hDevHlpQueue); 135 135 AssertRCReturn(rc, rc); 136 pVM->pdm.s.pDevHlpQueueR0 = PDMQueueR0Ptr(pVM->pdm.s.pDevHlpQueueR3);137 136 138 137 /* -
trunk/src/VBox/VMM/VMMR3/PDMDriver.cpp
r93115 r93609 1255 1255 1256 1256 1257 /**1258 * Conversion from handle to queue pointer (temporary).1259 */1260 DECLINLINE(PPDMQUEUE) pdmR3DrvHlp_QueueToPtr(PPDMDRVINS pDrvIns, PDMQUEUEHANDLE hQueue)1261 {1262 PDMDRV_ASSERT_DRVINS(pDrvIns);1263 RT_NOREF(pDrvIns);1264 return (PPDMQUEUE)hQueue;1265 }1266 1267 1268 1257 /** @interface_method_impl{PDMDRVHLPR3,pfnQueueCreate} */ 1269 1258 static DECLCALLBACK(int) pdmR3DrvHlp_QueueCreate(PPDMDRVINS pDrvIns, uint32_t cbItem, uint32_t cItems, uint32_t cMilliesInterval, … … 1282 1271 } 1283 1272 1284 PPDMQUEUE pQueue = NULL; 1285 int rc = PDMR3QueueCreateDriver(pVM, pDrvIns, cbItem, cItems, cMilliesInterval, pfnCallback, pszName, &pQueue); 1286 *phQueue = (PDMQUEUEHANDLE)pQueue; 1273 int rc = PDMR3QueueCreateDriver(pVM, pDrvIns, cbItem, cItems, cMilliesInterval, pfnCallback, pszName, phQueue); 1287 1274 1288 1275 LogFlow(("pdmR3DrvHlp_PDMQueueCreate: caller='%s'/%d: returns %Rrc *phQueue=%p\n", pDrvIns->pReg->szName, pDrvIns->iInstance, rc, *phQueue)); … … 1294 1281 static DECLCALLBACK(PPDMQUEUEITEMCORE) pdmR3DrvHlp_QueueAlloc(PPDMDRVINS pDrvIns, PDMQUEUEHANDLE hQueue) 1295 1282 { 1296 return PDMQueueAlloc(p dmR3DrvHlp_QueueToPtr(pDrvIns, hQueue));1283 return PDMQueueAlloc(pDrvIns->Internal.s.pVMR3, hQueue, pDrvIns); 1297 1284 } 1298 1285 1299 1286 1300 1287 /** @interface_method_impl{PDMDRVHLPR3,pfnQueueInsert} */ 1301 static DECLCALLBACK( void) pdmR3DrvHlp_QueueInsert(PPDMDRVINS pDrvIns, PDMQUEUEHANDLE hQueue, PPDMQUEUEITEMCORE pItem)1302 { 1303 return PDMQueueInsert(p dmR3DrvHlp_QueueToPtr(pDrvIns, hQueue), pItem);1288 static DECLCALLBACK(int) pdmR3DrvHlp_QueueInsert(PPDMDRVINS pDrvIns, PDMQUEUEHANDLE hQueue, PPDMQUEUEITEMCORE pItem) 1289 { 1290 return PDMQueueInsert(pDrvIns->Internal.s.pVMR3, hQueue, pDrvIns, pItem); 1304 1291 } 1305 1292 … … 1308 1295 static DECLCALLBACK(bool) pdmR3DrvHlp_QueueFlushIfNecessary(PPDMDRVINS pDrvIns, PDMQUEUEHANDLE hQueue) 1309 1296 { 1310 return PDMQueueFlushIfNecessary(pdmR3DrvHlp_QueueToPtr(pDrvIns, hQueue)); 1311 } 1312 1297 return PDMQueueFlushIfNecessary(pDrvIns->Internal.s.pVMR3, hQueue, pDrvIns) == VINF_SUCCESS; 1298 } 1313 1299 1314 1300 -
trunk/src/VBox/VMM/VMMR3/PDMQueue.cpp
r93115 r93609 31 31 #include <iprt/asm.h> 32 32 #include <iprt/assert.h> 33 #include <iprt/mem.h> 33 34 #include <iprt/thread.h> 34 35 … … 37 38 * Internal Functions * 38 39 *********************************************************************************************************************************/ 39 DECLINLINE(void) pdmR3QueueFreeItem(PPDMQUEUE pQueue, PPDMQUEUEITEMCORE pItem);40 static bool pdmR3QueueFlush(PPDMQUEUE pQueue);41 40 static DECLCALLBACK(void) pdmR3QueueTimer(PVM pVM, TMTIMERHANDLE hTimer, void *pvUser); 42 41 … … 54 53 * @param fRZEnabled Set if the queue will be used from RC/R0 and need to be allocated from the hyper heap. 55 54 * @param pszName The queue name. Unique. Not copied. 56 * @param ppQueue Where to store the queue handle. 55 * @param enmType Owner type. 56 * @param pvOwner The queue owner pointer. 57 * @param uCallback Callback function. 58 * @param phQueue Where to store the queue handle. 57 59 */ 58 60 static int pdmR3QueueCreate(PVM pVM, size_t cbItem, uint32_t cItems, uint32_t cMilliesInterval, bool fRZEnabled, 59 const char *pszName, PPDMQUEUE *ppQueue) 60 { 61 PUVM pUVM = pVM->pUVM; 62 63 /* 64 * Validate input. 65 */ 66 AssertMsgReturn(cbItem >= sizeof(PDMQUEUEITEMCORE) && cbItem < _1M, ("cbItem=%zu\n", cbItem), VERR_OUT_OF_RANGE); 67 AssertMsgReturn(cItems >= 1 && cItems <= _64K, ("cItems=%u\n", cItems), VERR_OUT_OF_RANGE); 61 const char *pszName, PDMQUEUETYPE enmType, void *pvOwner, uintptr_t uCallback, 62 PDMQUEUEHANDLE *phQueue) 63 { 64 /* 65 * Validate and adjust the input. 66 */ 67 VM_ASSERT_EMT0_RETURN(pVM, VERR_VM_THREAD_NOT_EMT); /* serialization by exclusivity */ 68 69 cbItem = RT_ALIGN(cbItem, sizeof(uint64_t)); 70 AssertMsgReturn(cbItem >= sizeof(PDMQUEUEITEMCORE) && cbItem < PDMQUEUE_MAX_ITEM_SIZE, ("cbItem=%zu\n", cbItem), 71 VERR_OUT_OF_RANGE); 72 AssertMsgReturn(cItems >= 1 && cItems <= PDMQUEUE_MAX_ITEMS, ("cItems=%u\n", cItems), VERR_OUT_OF_RANGE); 73 AssertMsgReturn((uint64_t)cbItem * cItems <= (fRZEnabled ? PDMQUEUE_MAX_TOTAL_SIZE_R0 : PDMQUEUE_MAX_TOTAL_SIZE_R3), 74 ("cItems=%u cbItem=%#x -> %#RX64, max %'u\n", cItems, cbItem, (uint64_t)cbItem * cItems, 75 fRZEnabled ? PDMQUEUE_MAX_TOTAL_SIZE_R0 : PDMQUEUE_MAX_TOTAL_SIZE_R3), 76 VERR_OUT_OF_RANGE); 77 AssertReturn(!fRZEnabled || enmType == PDMQUEUETYPE_INTERNAL || enmType == PDMQUEUETYPE_DEV, VERR_INVALID_PARAMETER); 78 if (SUPR3IsDriverless()) 79 fRZEnabled = false; 80 81 /* Unqiue name that fits within the szName field: */ 82 size_t cchName = strlen(pszName); 83 AssertReturn(cchName > 0, VERR_INVALID_NAME); 84 AssertMsgReturn(cchName < RT_SIZEOFMEMB(PDMQUEUE, szName), ("'%s' is too long\n", pszName), VERR_INVALID_NAME); 85 size_t i = pVM->pdm.s.cRing3Queues; 86 while (i-- > 0 ) 87 AssertMsgReturn(strcmp(pVM->pdm.s.papRing3Queues[i]->szName, pszName) != 0, ("%s\n", pszName), VERR_DUPLICATE); 88 i = pVM->pdm.s.cRing0Queues; 89 while (i-- > 0 ) 90 AssertMsgReturn(strcmp(pVM->pdm.s.apRing0Queues[i]->szName, pszName) != 0, ("%s\n", pszName), VERR_DUPLICATE); 68 91 69 92 /* 70 93 * Align the item size and calculate the structure size. 71 94 */ 72 cbItem = RT_ALIGN(cbItem, sizeof(RTUINTPTR)); 73 size_t cb = cbItem * cItems + RT_ALIGN_Z(RT_UOFFSETOF_DYN(PDMQUEUE, aFreeItems[cItems + PDMQUEUE_FREE_SLACK]), 16); 74 PPDMQUEUE pQueue; 75 int rc; 95 PPDMQUEUE pQueue; 96 PDMQUEUEHANDLE hQueue; 76 97 if (fRZEnabled) 77 rc = MMHyperAlloc(pVM, cb, 0, MM_TAG_PDM_QUEUE, (void **)&pQueue ); 98 { 99 /* Call ring-0 to allocate and create the queue: */ 100 PDMQUEUECREATEREQ Req; 101 Req.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC; 102 Req.Hdr.cbReq = sizeof(Req); 103 Req.cItems = cItems; 104 Req.cbItem = (uint32_t)cbItem; 105 Req.enmType = enmType; 106 Req.pvOwner = pvOwner; 107 Req.pfnCallback = (RTR3PTR)uCallback; 108 RTStrCopy(Req.szName, sizeof(Req.szName), pszName); 109 AssertCompileMembersSameSize(PDMQUEUECREATEREQ, szName, PDMQUEUE, szName); 110 Req.hQueue = NIL_PDMQUEUEHANDLE; 111 112 int rc = VMMR3CallR0(pVM, VMMR0_DO_PDM_QUEUE_CREATE, 0, &Req.Hdr); 113 if (RT_FAILURE(rc)) 114 return rc; 115 hQueue = Req.hQueue; 116 AssertReturn(hQueue < RT_ELEMENTS(pVM->pdm.s.apRing0Queues), VERR_INTERNAL_ERROR_2); 117 pQueue = pVM->pdm.s.apRing0Queues[hQueue]; 118 AssertPtrReturn(pQueue, VERR_INTERNAL_ERROR_3); 119 AssertReturn(pQueue->u32Magic == PDMQUEUE_MAGIC, VERR_INTERNAL_ERROR_4); 120 AssertReturn(pQueue->cbItem == cbItem, VERR_INTERNAL_ERROR_4); 121 AssertReturn(pQueue->cItems == cItems, VERR_INTERNAL_ERROR_4); 122 AssertReturn(pQueue->enmType == enmType, VERR_INTERNAL_ERROR_4); 123 AssertReturn(pQueue->u.Gen.pvOwner == pvOwner, VERR_INTERNAL_ERROR_4); 124 AssertReturn(pQueue->u.Gen.pfnCallback == (RTR3PTR)uCallback, VERR_INTERNAL_ERROR_4); 125 } 78 126 else 79 rc = MMR3HeapAllocZEx(pVM, MM_TAG_PDM_QUEUE, cb, (void **)&pQueue); 80 if (RT_FAILURE(rc)) 81 return rc; 82 83 /* 84 * Initialize the data fields. 85 */ 86 pQueue->pVMR3 = pVM; 87 pQueue->pVMR0 = fRZEnabled ? pVM->pVMR0ForCall : NIL_RTR0PTR; 88 pQueue->pszName = pszName; 89 pQueue->cMilliesInterval = cMilliesInterval; 90 pQueue->hTimer = NIL_TMTIMERHANDLE; 91 pQueue->cbItem = (uint32_t)cbItem; 92 pQueue->cItems = cItems; 93 //pQueue->pPendingR3 = NULL; 94 //pQueue->pPendingR0 = NULL; 95 //pQueue->pPendingRC = NULL; 96 pQueue->iFreeHead = cItems; 97 //pQueue->iFreeTail = 0; 98 PPDMQUEUEITEMCORE pItem = (PPDMQUEUEITEMCORE)((char *)pQueue + RT_ALIGN_Z(RT_UOFFSETOF_DYN(PDMQUEUE, aFreeItems[cItems + PDMQUEUE_FREE_SLACK]), 16)); 99 for (unsigned i = 0; i < cItems; i++, pItem = (PPDMQUEUEITEMCORE)((char *)pItem + cbItem)) 100 { 101 pQueue->aFreeItems[i].pItemR3 = pItem; 102 if (fRZEnabled) 103 pQueue->aFreeItems[i].pItemR0 = MMHyperR3ToR0(pVM, pItem); 127 { 128 /* Do it here using the paged heap: */ 129 uint32_t const cbBitmap = RT_ALIGN_32(RT_ALIGN_32(cItems, 64) / 8, 64); /* keep bitmap in it's own cacheline */ 130 uint32_t const cbQueue = RT_OFFSETOF(PDMQUEUE, bmAlloc) 131 + cbBitmap 132 + (uint32_t)cbItem * cItems; 133 pQueue = (PPDMQUEUE)RTMemPageAllocZ(cbQueue); 134 if (!pQueue) 135 return VERR_NO_PAGE_MEMORY; 136 pdmQueueInit(pQueue, cbBitmap, (uint32_t)cbItem, cItems, pszName, enmType, (RTR3PTR)uCallback, pvOwner); 137 138 uint32_t iQueue = pVM->pdm.s.cRing3Queues; 139 if (iQueue >= pVM->pdm.s.cRing3QueuesAlloc) 140 { 141 AssertLogRelMsgReturnStmt(iQueue < _16K, ("%#x\n", iQueue), RTMemPageFree(pQueue, cbQueue), VERR_TOO_MANY_OPENS); 142 143 uint32_t const cNewAlloc = RT_ALIGN_32(iQueue, 64) + 64; 144 PPDMQUEUE *papQueuesNew = (PPDMQUEUE *)RTMemAllocZ(cNewAlloc * sizeof(papQueuesNew[0])); 145 AssertLogRelMsgReturnStmt(papQueuesNew, ("cNewAlloc=%u\n", cNewAlloc), RTMemPageFree(pQueue, cbQueue), VERR_NO_MEMORY); 146 147 if (iQueue) 148 memcpy(papQueuesNew, pVM->pdm.s.papRing3Queues, iQueue * sizeof(papQueuesNew[0])); 149 PPDMQUEUE *papQueuesOld = ASMAtomicXchgPtrT(&pVM->pdm.s.papRing3Queues, papQueuesNew, PPDMQUEUE *); 150 pVM->pdm.s.cRing3QueuesAlloc = cNewAlloc; 151 RTMemFree(papQueuesOld); 152 } 153 154 pVM->pdm.s.papRing3Queues[iQueue] = pQueue; 155 pVM->pdm.s.cRing3Queues = iQueue + 1; 156 hQueue = iQueue + RT_ELEMENTS(pVM->pdm.s.apRing0Queues); 104 157 } 105 158 … … 109 162 if (cMilliesInterval) 110 163 { 111 char szName[ 32];112 RTStrPrintf(szName, sizeof(szName), "Que ue %s", pQueue->pszName);113 rc = TMR3TimerCreate(pVM, TMCLOCK_REAL, pdmR3QueueTimer, pQueue, TMTIMER_FLAGS_NO_RING0, szName, &pQueue->hTimer);164 char szName[48+6]; 165 RTStrPrintf(szName, sizeof(szName), "Que/%s", pQueue->szName); 166 int rc = TMR3TimerCreate(pVM, TMCLOCK_REAL, pdmR3QueueTimer, pQueue, TMTIMER_FLAGS_NO_RING0, szName, &pQueue->hTimer); 114 167 if (RT_SUCCESS(rc)) 115 168 { 116 169 rc = TMTimerSetMillies(pVM, pQueue->hTimer, cMilliesInterval); 117 if (RT_FAILURE(rc)) 170 if (RT_SUCCESS(rc)) 171 pQueue->cMilliesInterval = cMilliesInterval; 172 else 118 173 { 119 174 AssertMsgFailed(("TMTimerSetMillies failed rc=%Rrc\n", rc)); 120 175 int rc2 = TMR3TimerDestroy(pVM, pQueue->hTimer); AssertRC(rc2); 176 pQueue->hTimer = NIL_TMTIMERHANDLE; 121 177 } 122 178 } … … 125 181 if (RT_FAILURE(rc)) 126 182 { 127 if (fRZEnabled) 128 MMHyperFree(pVM, pQueue); 129 else 130 MMR3HeapFree(pQueue); 183 if (!fRZEnabled) 184 PDMR3QueueDestroy(pVM, hQueue, pvOwner); 185 /* else: will clean up queue when VM is destroyed */ 131 186 return rc; 132 187 } 133 134 /*135 * Insert into the queue list for timer driven queues.136 */137 pdmLock(pVM);138 pQueue->pNext = pUVM->pdm.s.pQueuesTimer;139 pUVM->pdm.s.pQueuesTimer = pQueue;140 pdmUnlock(pVM);141 }142 else143 {144 /*145 * Insert into the queue list for forced action driven queues.146 * This is a FIFO, so insert at the end.147 */148 /** @todo we should add a priority to the queues so we don't have to rely on149 * the initialization order to deal with problems like @bugref{1605} (pgm/pcnet150 * deadlock caused by the critsect queue to be last in the chain).151 * - Update, the critical sections are no longer using queues, so this isn't a real152 * problem any longer. The priority might be a nice feature for later though.153 */154 pdmLock(pVM);155 if (!pUVM->pdm.s.pQueuesForced)156 pUVM->pdm.s.pQueuesForced = pQueue;157 else158 {159 PPDMQUEUE pPrev = pUVM->pdm.s.pQueuesForced;160 while (pPrev->pNext)161 pPrev = pPrev->pNext;162 pPrev->pNext = pQueue;163 }164 pdmUnlock(pVM);165 188 } 166 189 … … 168 191 * Register the statistics. 169 192 */ 170 STAMR3RegisterF(pVM, &pQueue->cbItem, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES, "Item size.", "/PDM/Queue/%s/cbItem", pQueue->pszName); 171 STAMR3RegisterF(pVM, &pQueue->cItems, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Queue size.", "/PDM/Queue/%s/cItems", pQueue->pszName); 172 STAMR3RegisterF(pVM, &pQueue->StatAllocFailures, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "PDMQueueAlloc failures.", "/PDM/Queue/%s/AllocFailures", pQueue->pszName); 173 STAMR3RegisterF(pVM, &pQueue->StatInsert, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "Calls to PDMQueueInsert.", "/PDM/Queue/%s/Insert", pQueue->pszName); 174 STAMR3RegisterF(pVM, &pQueue->StatFlush, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "Calls to pdmR3QueueFlush.", "/PDM/Queue/%s/Flush", pQueue->pszName); 175 STAMR3RegisterF(pVM, &pQueue->StatFlushLeftovers, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Left over items after flush.", "/PDM/Queue/%s/FlushLeftovers", pQueue->pszName); 193 STAMR3RegisterF(pVM, &pQueue->cbItem, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES, 194 "Item size.", "/PDM/Queue/%s/cbItem", pQueue->szName); 195 STAMR3RegisterF(pVM, &pQueue->cItems, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, 196 "Queue size.", "/PDM/Queue/%s/cItems", pQueue->szName); 197 STAMR3RegisterF(pVM, &pQueue->rcOkay, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE, 198 "Non-zero means queue is busted.", "/PDM/Queue/%s/rcOkay", pQueue->szName); 199 STAMR3RegisterF(pVM, &pQueue->StatAllocFailures, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, 200 "PDMQueueAlloc failures.", "/PDM/Queue/%s/AllocFailures", pQueue->szName); 201 STAMR3RegisterF(pVM, &pQueue->StatInsert, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, 202 "Calls to PDMQueueInsert.", "/PDM/Queue/%s/Insert", pQueue->szName); 203 STAMR3RegisterF(pVM, &pQueue->StatFlush, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, 204 "Calls to pdmR3QueueFlush.", "/PDM/Queue/%s/Flush", pQueue->szName); 205 STAMR3RegisterF(pVM, &pQueue->StatFlushLeftovers, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, 206 "Left over items after flush.", "/PDM/Queue/%s/FlushLeftovers", pQueue->szName); 176 207 #ifdef VBOX_WITH_STATISTICS 177 STAMR3RegisterF(pVM, &pQueue->StatFlushPrf, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling pdmR3QueueFlush.", "/PDM/Queue/%s/FlushPrf", pQueue->pszName); 178 STAMR3RegisterF(pVM, (void *)&pQueue->cStatPending, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Pending items.", "/PDM/Queue/%s/Pending", pQueue->pszName); 208 STAMR3RegisterF(pVM, &pQueue->StatFlushPrf, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, 209 "Profiling pdmR3QueueFlush.", "/PDM/Queue/%s/FlushPrf", pQueue->szName); 210 STAMR3RegisterF(pVM, (void *)&pQueue->cStatPending, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, 211 "Pending items.", "/PDM/Queue/%s/Pending", pQueue->szName); 179 212 #endif 180 213 181 *p pQueue = pQueue;214 *phQueue = hQueue; 182 215 return VINF_SUCCESS; 183 216 } … … 196 229 * @param pfnCallback The consumer function. 197 230 * @param fRZEnabled Set if the queue must be usable from RC/R0. 198 * @param pszName The queue name. Unique. Not copied.199 * @param p pQueue Where to store the queue handle on success.231 * @param pszName The queue name. Unique. Copied. 232 * @param phQueue Where to store the queue handle on success. 200 233 * @thread Emulation thread only. 201 234 */ 202 VMMR3_INT_DECL(int) PDMR3QueueCreateDevice(PVM pVM, PPDMDEVINS pDevIns, size_t cbItem, uint32_t cItems, uint32_t cMilliesInterval, 203 PFNPDMQUEUEDEV pfnCallback, bool fRZEnabled, const char *pszName, PPDMQUEUE *ppQueue) 235 VMMR3_INT_DECL(int) PDMR3QueueCreateDevice(PVM pVM, PPDMDEVINS pDevIns, size_t cbItem, uint32_t cItems, 236 uint32_t cMilliesInterval, PFNPDMQUEUEDEV pfnCallback, 237 bool fRZEnabled, const char *pszName, PDMQUEUEHANDLE *phQueue) 204 238 { 205 239 LogFlow(("PDMR3QueueCreateDevice: pDevIns=%p cbItem=%d cItems=%d cMilliesInterval=%d pfnCallback=%p fRZEnabled=%RTbool pszName=%s\n", … … 210 244 */ 211 245 VM_ASSERT_EMT0(pVM); 212 if (!pfnCallback)213 {214 AssertMsgFailed(("No consumer callback!\n")); 215 return VERR_INVALID_PARAMETER;216 }246 AssertPtrReturn(pfnCallback, VERR_INVALID_POINTER); 247 AssertPtrReturn(pDevIns, VERR_INVALID_POINTER); 248 249 if (!(pDevIns->Internal.s.fIntFlags & PDMDEVINSINT_FLAGS_R0_ENABLED)) 250 fRZEnabled = false; 217 251 218 252 /* 219 253 * Create the queue. 220 254 */ 221 PPDMQUEUE pQueue;222 int rc = pdmR3QueueCreate(pVM, cbItem, cItems, cMilliesInterval, fRZEnabled, pszName, &pQueue);255 int rc = pdmR3QueueCreate(pVM, cbItem, cItems, cMilliesInterval, fRZEnabled, pszName, 256 PDMQUEUETYPE_DEV, pDevIns, (uintptr_t)pfnCallback, phQueue); 223 257 if (RT_SUCCESS(rc)) 224 { 225 pQueue->enmType = PDMQUEUETYPE_DEV; 226 pQueue->u.Dev.pDevIns = pDevIns; 227 pQueue->u.Dev.pfnCallback = pfnCallback; 228 229 *ppQueue = pQueue; 230 Log(("PDM: Created device queue %p; cbItem=%d cItems=%d cMillies=%d pfnCallback=%p pDevIns=%p\n", 231 pQueue, cbItem, cItems, cMilliesInterval, pfnCallback, pDevIns)); 232 } 258 Log(("PDM: Created device queue %#RX64; cbItem=%d cItems=%d cMillies=%d pfnCallback=%p pDevIns=%p\n", 259 *phQueue, cbItem, cItems, cMilliesInterval, pfnCallback, pDevIns)); 233 260 return rc; 234 261 } … … 246 273 * If 0 then the emulation thread will be notified whenever an item arrives. 247 274 * @param pfnCallback The consumer function. 248 * @param pszName The queue name. Unique. Not copied.249 * @param p pQueue Where to store the queue handle on success.275 * @param pszName The queue name. Unique. Copied. 276 * @param phQueue Where to store the queue handle on success. 250 277 * @thread Emulation thread only. 251 278 */ 252 279 VMMR3_INT_DECL(int) PDMR3QueueCreateDriver(PVM pVM, PPDMDRVINS pDrvIns, size_t cbItem, uint32_t cItems, uint32_t cMilliesInterval, 253 PFNPDMQUEUEDRV pfnCallback, const char *pszName, P PDMQUEUE *ppQueue)280 PFNPDMQUEUEDRV pfnCallback, const char *pszName, PDMQUEUEHANDLE *phQueue) 254 281 { 255 282 LogFlow(("PDMR3QueueCreateDriver: pDrvIns=%p cbItem=%d cItems=%d cMilliesInterval=%d pfnCallback=%p pszName=%s\n", … … 261 288 VM_ASSERT_EMT0(pVM); 262 289 AssertPtrReturn(pfnCallback, VERR_INVALID_POINTER); 290 AssertPtrReturn(pDrvIns, VERR_INVALID_POINTER); 263 291 264 292 /* 265 293 * Create the queue. 266 294 */ 267 PPDMQUEUE pQueue;268 int rc = pdmR3QueueCreate(pVM, cbItem, cItems, cMilliesInterval, false, pszName, &pQueue);295 int rc = pdmR3QueueCreate(pVM, cbItem, cItems, cMilliesInterval, false /*fRZEnabled*/, pszName, 296 PDMQUEUETYPE_DRV, pDrvIns, (uintptr_t)pfnCallback, phQueue); 269 297 if (RT_SUCCESS(rc)) 270 { 271 pQueue->enmType = PDMQUEUETYPE_DRV; 272 pQueue->u.Drv.pDrvIns = pDrvIns; 273 pQueue->u.Drv.pfnCallback = pfnCallback; 274 275 *ppQueue = pQueue; 276 Log(("PDM: Created driver queue %p; cbItem=%d cItems=%d cMillies=%d pfnCallback=%p pDrvIns=%p\n", 277 pQueue, cbItem, cItems, cMilliesInterval, pfnCallback, pDrvIns)); 278 } 298 Log(("PDM: Created driver queue %#RX64; cbItem=%d cItems=%d cMillies=%d pfnCallback=%p pDrvIns=%p\n", 299 *phQueue, cbItem, cItems, cMilliesInterval, pfnCallback, pDrvIns)); 279 300 return rc; 280 301 } … … 292 313 * @param pfnCallback The consumer function. 293 314 * @param fRZEnabled Set if the queue must be usable from RC/R0. 294 * @param pszName The queue name. Unique. Not copied.295 * @param p pQueue Where to store the queue handle on success.315 * @param pszName The queue name. Unique. Copied. 316 * @param phQueue Where to store the queue handle on success. 296 317 * @thread Emulation thread only. 297 318 */ 298 319 VMMR3_INT_DECL(int) PDMR3QueueCreateInternal(PVM pVM, size_t cbItem, uint32_t cItems, uint32_t cMilliesInterval, 299 PFNPDMQUEUEINT pfnCallback, bool fRZEnabled, const char *pszName, PPDMQUEUE *ppQueue) 320 PFNPDMQUEUEINT pfnCallback, bool fRZEnabled, 321 const char *pszName, PDMQUEUEHANDLE *phQueue) 300 322 { 301 323 LogFlow(("PDMR3QueueCreateInternal: cbItem=%d cItems=%d cMilliesInterval=%d pfnCallback=%p fRZEnabled=%RTbool pszName=%s\n", … … 311 333 * Create the queue. 312 334 */ 313 PPDMQUEUE pQueue;314 int rc = pdmR3QueueCreate(pVM, cbItem, cItems, cMilliesInterval, fRZEnabled, pszName, &pQueue);335 int rc = pdmR3QueueCreate(pVM, cbItem, cItems, cMilliesInterval, fRZEnabled, pszName, 336 PDMQUEUETYPE_INTERNAL, pVM, (uintptr_t)pfnCallback, phQueue); 315 337 if (RT_SUCCESS(rc)) 316 {317 pQueue->enmType = PDMQUEUETYPE_INTERNAL;318 pQueue->u.Int.pfnCallback = pfnCallback;319 320 *ppQueue = pQueue;321 338 Log(("PDM: Created internal queue %p; cbItem=%d cItems=%d cMillies=%d pfnCallback=%p\n", 322 pQueue, cbItem, cItems, cMilliesInterval, pfnCallback)); 323 } 339 *phQueue, cbItem, cItems, cMilliesInterval, pfnCallback)); 324 340 return rc; 325 341 } … … 338 354 * @param pvUser The user argument to the consumer function. 339 355 * @param pszName The queue name. Unique. Not copied. 340 * @param p pQueue Where to store the queue handle on success.356 * @param phQueue Where to store the queue handle on success. 341 357 * @thread Emulation thread only. 342 358 */ 343 VMMR3_INT_DECL(int) PDMR3QueueCreateExternal(PVM pVM, size_t cbItem, uint32_t cItems, uint32_t cMilliesInterval, 344 PFNPDMQUEUEEXT pfnCallback, void *pvUser, const char *pszName, PPDMQUEUE *ppQueue) 345 { 346 LogFlow(("PDMR3QueueCreateExternal: cbItem=%d cItems=%d cMilliesInterval=%d pfnCallback=%p pszName=%s\n", cbItem, cItems, cMilliesInterval, pfnCallback, pszName)); 359 VMMR3DECL(int) PDMR3QueueCreateExternal(PVM pVM, size_t cbItem, uint32_t cItems, uint32_t cMilliesInterval, 360 PFNPDMQUEUEEXT pfnCallback, void *pvUser, 361 const char *pszName, PDMQUEUEHANDLE *phQueue) 362 { 363 LogFlow(("PDMR3QueueCreateExternal: cbItem=%d cItems=%d cMilliesInterval=%d pfnCallback=%p pszName=%s\n", 364 cbItem, cItems, cMilliesInterval, pfnCallback, pszName)); 347 365 348 366 /* … … 355 373 * Create the queue. 356 374 */ 375 int rc = pdmR3QueueCreate(pVM, cbItem, cItems, cMilliesInterval, false /*fRZEnabled*/, pszName, 376 PDMQUEUETYPE_EXTERNAL, pvUser, (uintptr_t)pfnCallback, phQueue); 377 if (RT_SUCCESS(rc)) 378 Log(("PDM: Created external queue %p; cbItem=%d cItems=%d cMillies=%d pfnCallback=%p pvUser=%p\n", 379 *phQueue, cbItem, cItems, cMilliesInterval, pfnCallback, pvUser)); 380 return rc; 381 } 382 383 384 /** 385 * Destroy a queue. 386 * 387 * @returns VBox status code. 388 * @param pVM Pointer to the cross context VM structure. 389 * @param hQueue Handle to the queue that should be destroyed. 390 * @param pvOwner The owner address. 391 * @thread EMT(0) 392 * @note Externally visible mainly for testing purposes. 393 */ 394 VMMR3DECL(int) PDMR3QueueDestroy(PVM pVM, PDMQUEUEHANDLE hQueue, void *pvOwner) 395 { 396 LogFlow(("PDMR3QueueDestroy: hQueue=%p pvOwner=%p\n", hQueue, pvOwner)); 397 398 /* 399 * Validate input. 400 */ 401 VM_ASSERT_EMT0_RETURN(pVM, VERR_VM_THREAD_NOT_EMT); /* serialization */ 402 if (hQueue == NIL_PDMQUEUEHANDLE) 403 return VINF_SUCCESS; 404 357 405 PPDMQUEUE pQueue; 358 int rc = pdmR3QueueCreate(pVM, cbItem, cItems, cMilliesInterval, false, pszName, &pQueue); 359 if (RT_SUCCESS(rc)) 360 { 361 pQueue->enmType = PDMQUEUETYPE_EXTERNAL; 362 pQueue->u.Ext.pvUser = pvUser; 363 pQueue->u.Ext.pfnCallback = pfnCallback; 364 365 *ppQueue = pQueue; 366 Log(("PDM: Created external queue %p; cbItem=%d cItems=%d cMillies=%d pfnCallback=%p pvUser=%p\n", 367 pQueue, cbItem, cItems, cMilliesInterval, pfnCallback, pvUser)); 368 } 369 return rc; 370 } 371 372 373 /** 374 * Destroy a queue. 375 * 376 * @returns VBox status code. 377 * @param pQueue Queue to destroy. 378 * @thread Emulation thread only. 379 */ 380 VMMR3_INT_DECL(int) PDMR3QueueDestroy(PPDMQUEUE pQueue) 381 { 382 LogFlow(("PDMR3QueueDestroy: pQueue=%p\n", pQueue)); 383 384 /* 385 * Validate input. 386 */ 387 if (!pQueue) 388 return VERR_INVALID_PARAMETER; 389 Assert(pQueue && pQueue->pVMR3); 390 PVM pVM = pQueue->pVMR3; 391 PUVM pUVM = pVM->pUVM; 392 393 pdmLock(pVM); 394 395 /* 396 * Unlink it. 397 */ 398 if (pQueue->hTimer != NIL_TMTIMERHANDLE) 399 { 400 if (pUVM->pdm.s.pQueuesTimer != pQueue) 401 { 402 PPDMQUEUE pCur = pUVM->pdm.s.pQueuesTimer; 403 while (pCur) 404 { 405 if (pCur->pNext == pQueue) 406 { 407 pCur->pNext = pQueue->pNext; 408 break; 409 } 410 pCur = pCur->pNext; 411 } 412 AssertMsg(pCur, ("Didn't find the queue!\n")); 406 bool fRZEnabled = false; 407 if (hQueue < RT_ELEMENTS(pVM->pdm.s.apRing0Queues)) 408 { 409 AssertReturn(hQueue < pVM->pdm.s.cRing0Queues, VERR_INVALID_HANDLE); 410 pQueue = pVM->pdm.s.apRing0Queues[hQueue]; 411 AssertPtrReturn(pQueue, VERR_INVALID_HANDLE); 412 AssertReturn(pQueue->u32Magic == PDMQUEUE_MAGIC, VERR_INVALID_HANDLE); 413 AssertReturn(pQueue->u.Gen.pvOwner == pvOwner, VERR_INVALID_HANDLE); 414 415 /* Lazy bird: Cannot dynamically delete ring-0 capable queues. */ 416 AssertFailedReturn(VERR_NOT_SUPPORTED); 417 } 418 else 419 { 420 hQueue -= RT_ELEMENTS(pVM->pdm.s.apRing0Queues); 421 AssertReturn(hQueue < pVM->pdm.s.cRing3Queues, VERR_INVALID_HANDLE); 422 pQueue = pVM->pdm.s.papRing3Queues[hQueue]; 423 AssertPtrReturn(pQueue, VERR_INVALID_HANDLE); 424 AssertReturn(pQueue->u32Magic == PDMQUEUE_MAGIC, VERR_INVALID_HANDLE); 425 AssertReturn(pQueue->u.Gen.pvOwner == pvOwner, VERR_INVALID_HANDLE); 426 427 /* Enter the lock here to serialize with other EMTs traversing the handles. */ 428 pdmLock(pVM); 429 pVM->pdm.s.papRing3Queues[hQueue] = NULL; 430 if (hQueue + 1 == pVM->pdm.s.cRing3Queues) 431 { 432 while (hQueue > 0 && pVM->pdm.s.papRing3Queues[hQueue - 1] == NULL) 433 hQueue--; 434 pVM->pdm.s.cRing3Queues = hQueue; 413 435 } 414 else 415 pUVM->pdm.s.pQueuesTimer = pQueue->pNext; 416 } 417 else 418 { 419 if (pUVM->pdm.s.pQueuesForced != pQueue) 420 { 421 PPDMQUEUE pCur = pUVM->pdm.s.pQueuesForced; 422 while (pCur) 423 { 424 if (pCur->pNext == pQueue) 425 { 426 pCur->pNext = pQueue->pNext; 427 break; 428 } 429 pCur = pCur->pNext; 430 } 431 AssertMsg(pCur, ("Didn't find the queue!\n")); 432 } 433 else 434 pUVM->pdm.s.pQueuesForced = pQueue->pNext; 435 } 436 pQueue->pNext = NULL; 437 pQueue->pVMR3 = NULL; 438 pdmUnlock(pVM); 436 pQueue->u32Magic = PDMQUEUE_MAGIC_DEAD; 437 pdmUnlock(pVM); 438 } 439 439 440 440 /* 441 441 * Deregister statistics. 442 442 */ 443 STAMR3DeregisterF(pVM->pUVM, "/PDM/Queue/%s/ cbItem", pQueue->pszName);443 STAMR3DeregisterF(pVM->pUVM, "/PDM/Queue/%s/*", pQueue->szName); 444 444 445 445 /* … … 451 451 pQueue->hTimer = NIL_TMTIMERHANDLE; 452 452 } 453 if (pQueue->pVMR0) 454 { 455 pQueue->pVMR0 = NIL_RTR0PTR; 456 MMHyperFree(pVM, pQueue); 457 } 458 else 459 MMR3HeapFree(pQueue); 453 if (!fRZEnabled) 454 RTMemPageFree(pQueue, pQueue->offItems + pQueue->cbItem * pQueue->cItems); 455 456 return VINF_SUCCESS; 457 } 458 459 460 /** 461 * Destroy a all queues with a given owner. 462 * 463 * @returns VBox status code. 464 * @param pVM The cross context VM structure. 465 * @param pvOwner The owner pointer. 466 * @param enmType Owner type. 467 * @thread EMT(0) 468 */ 469 static int pdmR3QueueDestroyByOwner(PVM pVM, void *pvOwner, PDMQUEUETYPE enmType) 470 { 471 LogFlow(("pdmR3QueueDestroyByOwner: pvOwner=%p enmType=%d\n", pvOwner, enmType)); 472 473 /* 474 * Validate input. 475 */ 476 AssertPtrReturn(pvOwner, VERR_INVALID_PARAMETER); 477 AssertReturn(pvOwner != pVM, VERR_INVALID_PARAMETER); 478 VM_ASSERT_EMT0_RETURN(pVM, VERR_VM_THREAD_NOT_EMT); /* serialization */ 479 480 /* 481 * Scan and destroy. 482 */ 483 uint32_t i = pVM->pdm.s.cRing0Queues; 484 while (i-- > 0) 485 { 486 PPDMQUEUE pQueue = pVM->pdm.s.apRing0Queues[i]; 487 if ( pQueue 488 && pQueue->u.Gen.pvOwner == pvOwner 489 && pQueue->enmType == enmType) 490 { 491 /* Not supported at runtime. */ 492 VM_ASSERT_STATE_RETURN(pVM, VMSTATE_DESTROYING, VERR_WRONG_ORDER); 493 } 494 } 495 496 i = pVM->pdm.s.cRing3Queues; 497 while (i-- > 0) 498 { 499 PPDMQUEUE pQueue = pVM->pdm.s.papRing3Queues[i]; 500 if ( pQueue 501 && pQueue->u.Gen.pvOwner == pvOwner 502 && pQueue->enmType == enmType) 503 PDMR3QueueDestroy(pVM, i + RT_ELEMENTS(pVM->pdm.s.apRing0Queues), pvOwner); 504 } 460 505 461 506 return VINF_SUCCESS; … … 469 514 * @param pVM The cross context VM structure. 470 515 * @param pDevIns Device instance. 471 * @thread E mulation thread only.516 * @thread EMT(0) 472 517 */ 473 518 VMMR3_INT_DECL(int) PDMR3QueueDestroyDevice(PVM pVM, PPDMDEVINS pDevIns) 474 519 { 475 520 LogFlow(("PDMR3QueueDestroyDevice: pDevIns=%p\n", pDevIns)); 476 477 /* 478 * Validate input. 479 */ 480 if (!pDevIns) 481 return VERR_INVALID_PARAMETER; 482 483 PUVM pUVM = pVM->pUVM; 484 pdmLock(pVM); 485 486 /* 487 * Unlink it. 488 */ 489 PPDMQUEUE pQueueNext = pUVM->pdm.s.pQueuesTimer; 490 PPDMQUEUE pQueue = pUVM->pdm.s.pQueuesForced; 491 do 492 { 493 while (pQueue) 494 { 495 if ( pQueue->enmType == PDMQUEUETYPE_DEV 496 && pQueue->u.Dev.pDevIns == pDevIns) 497 { 498 PPDMQUEUE pQueueDestroy = pQueue; 499 pQueue = pQueue->pNext; 500 int rc = PDMR3QueueDestroy(pQueueDestroy); 501 AssertRC(rc); 502 } 503 else 504 pQueue = pQueue->pNext; 505 } 506 507 /* next queue list */ 508 pQueue = pQueueNext; 509 pQueueNext = NULL; 510 } while (pQueue); 511 512 pdmUnlock(pVM); 513 return VINF_SUCCESS; 521 return pdmR3QueueDestroyByOwner(pVM, pDevIns, PDMQUEUETYPE_DEV); 514 522 } 515 523 … … 521 529 * @param pVM The cross context VM structure. 522 530 * @param pDrvIns Driver instance. 523 * @thread E mulation thread only.531 * @thread EMT(0) 524 532 */ 525 533 VMMR3_INT_DECL(int) PDMR3QueueDestroyDriver(PVM pVM, PPDMDRVINS pDrvIns) 526 534 { 527 535 LogFlow(("PDMR3QueueDestroyDriver: pDrvIns=%p\n", pDrvIns)); 528 529 /* 530 * Validate input. 531 */ 532 if (!pDrvIns) 533 return VERR_INVALID_PARAMETER; 534 535 PUVM pUVM = pVM->pUVM; 536 pdmLock(pVM); 537 538 /* 539 * Unlink it. 540 */ 541 PPDMQUEUE pQueueNext = pUVM->pdm.s.pQueuesTimer; 542 PPDMQUEUE pQueue = pUVM->pdm.s.pQueuesForced; 543 do 544 { 545 while (pQueue) 546 { 547 if ( pQueue->enmType == PDMQUEUETYPE_DRV 548 && pQueue->u.Drv.pDrvIns == pDrvIns) 536 return pdmR3QueueDestroyByOwner(pVM, pDrvIns, PDMQUEUETYPE_DRV); 537 } 538 539 540 /** 541 * Free an item. 542 * 543 * @param pQueue The queue. 544 * @param pItem The item. 545 */ 546 DECLINLINE(void) pdmR3QueueFreeItem(PPDMQUEUE pQueue, uint8_t *pbItems, uint32_t cbItem, PPDMQUEUEITEMCORE pItem) 547 { 548 pItem->u64View = UINT64_C(0xfeedfeedfeedfeed); 549 550 uintptr_t const offItem = (uintptr_t)pItem - (uintptr_t)pbItems; 551 uintptr_t const iItem = offItem / cbItem; 552 Assert(!(offItem % cbItem)); 553 Assert(iItem < pQueue->cItems); 554 AssertReturnVoidStmt(ASMAtomicBitTestAndSet(pQueue->bmAlloc, iItem) == false, pQueue->rcOkay = VERR_INTERNAL_ERROR_4); 555 STAM_STATS({ ASMAtomicDecU32(&pQueue->cStatPending); }); 556 } 557 558 559 560 /** 561 * Process pending items in one queue. 562 * 563 * @returns VBox status code. 564 * @param pVM The cross context VM structure. 565 * @param pQueue The queue needing flushing. 566 */ 567 static int pdmR3QueueFlush(PVM pVM, PPDMQUEUE pQueue) 568 { 569 STAM_PROFILE_START(&pQueue->StatFlushPrf,p); 570 571 uint32_t const cbItem = pQueue->cbItem; 572 uint32_t const cItems = pQueue->cItems; 573 uint8_t * const pbItems = (uint8_t *)pQueue + pQueue->offItems; 574 575 /* 576 * Get the list and reverse it into a pointer list (inserted in LIFO order to avoid locking). 577 */ 578 uint32_t cPending = 0; 579 PPDMQUEUEITEMCORE pHead = NULL; 580 { 581 uint32_t iCur = ASMAtomicXchgU32(&pQueue->iPending, UINT32_MAX); 582 do 583 { 584 AssertMsgReturn(iCur < cItems, ("%#x vs %#x\n", iCur, cItems), pQueue->rcOkay = VERR_INTERNAL_ERROR_5); 585 AssertReturn(ASMBitTest(pQueue->bmAlloc, iCur) == false, pQueue->rcOkay = VERR_INTERNAL_ERROR_3); 586 PPDMQUEUEITEMCORE pCur = (PPDMQUEUEITEMCORE)&pbItems[iCur * cbItem]; 587 588 iCur = pCur->iNext; 589 ASMCompilerBarrier(); /* paranoia */ 590 pCur->pNext = pHead; 591 pHead = pCur; 592 cPending++; 593 } while (iCur != UINT32_MAX); 594 } 595 RT_NOREF(cPending); 596 597 /* 598 * Feed the items to the consumer function. 599 */ 600 Log2(("pdmR3QueueFlush: pQueue=%p enmType=%d pHead=%p cItems=%u\n", pQueue, pQueue->enmType, pHead, cPending)); 601 switch (pQueue->enmType) 602 { 603 case PDMQUEUETYPE_DEV: 604 while (pHead) 549 605 { 550 PPDMQUEUE pQueueDestroy = pQueue; 551 pQueue = pQueue->pNext; 552 int rc = PDMR3QueueDestroy(pQueueDestroy); 553 AssertRC(rc); 606 if (!pQueue->u.Dev.pfnCallback(pQueue->u.Dev.pDevIns, pHead)) 607 break; 608 PPDMQUEUEITEMCORE pFree = pHead; 609 pHead = pHead->pNext; 610 ASMCompilerBarrier(); /* paranoia */ 611 pdmR3QueueFreeItem(pQueue, pbItems, cbItem, pFree); 554 612 } 555 else 556 pQueue = pQueue->pNext; 613 break; 614 615 case PDMQUEUETYPE_DRV: 616 while (pHead) 617 { 618 if (!pQueue->u.Drv.pfnCallback(pQueue->u.Drv.pDrvIns, pHead)) 619 break; 620 PPDMQUEUEITEMCORE pFree = pHead; 621 pHead = pHead->pNext; 622 ASMCompilerBarrier(); /* paranoia */ 623 pdmR3QueueFreeItem(pQueue, pbItems, cbItem, pFree); 624 } 625 break; 626 627 case PDMQUEUETYPE_INTERNAL: 628 while (pHead) 629 { 630 if (!pQueue->u.Int.pfnCallback(pVM, pHead)) 631 break; 632 PPDMQUEUEITEMCORE pFree = pHead; 633 pHead = pHead->pNext; 634 ASMCompilerBarrier(); /* paranoia */ 635 pdmR3QueueFreeItem(pQueue, pbItems, cbItem, pFree); 636 } 637 break; 638 639 case PDMQUEUETYPE_EXTERNAL: 640 while (pHead) 641 { 642 if (!pQueue->u.Ext.pfnCallback(pQueue->u.Ext.pvUser, pHead)) 643 break; 644 PPDMQUEUEITEMCORE pFree = pHead; 645 pHead = pHead->pNext; 646 ASMCompilerBarrier(); /* paranoia */ 647 pdmR3QueueFreeItem(pQueue, pbItems, cbItem, pFree); 648 } 649 break; 650 651 default: 652 AssertMsgFailed(("Invalid queue type %d\n", pQueue->enmType)); 653 break; 654 } 655 656 /* 657 * Success? 658 */ 659 if (!pHead) 660 { /* likely */ } 661 else 662 { 663 /* 664 * Reverse the list and turn it back into index chain. 665 */ 666 uint32_t iPendingHead = UINT32_MAX; 667 do 668 { 669 PPDMQUEUEITEMCORE pInsert = pHead; 670 pHead = pHead->pNext; 671 ASMCompilerBarrier(); /* paranoia */ 672 pInsert->iNext = iPendingHead; 673 iPendingHead = ((uintptr_t)pInsert - (uintptr_t)pbItems) / cbItem; 674 } while (pHead); 675 676 /* 677 * Insert the list at the tail of the pending list. If someone races 678 * us there, we have to join the new LIFO with the old. 679 */ 680 for (;;) 681 { 682 if (ASMAtomicCmpXchgU32(&pQueue->iPending, iPendingHead, UINT32_MAX)) 683 break; 684 685 uint32_t const iNewPending = ASMAtomicXchgU32(&pQueue->iPending, UINT32_MAX); 686 if (iNewPending != UINT32_MAX) 687 { 688 /* Find the last entry and chain iPendingHead onto it. */ 689 uint32_t iCur = iNewPending; 690 for (;;) 691 { 692 AssertReturn(iCur < cItems, pQueue->rcOkay = VERR_INTERNAL_ERROR_2); 693 AssertReturn(ASMBitTest(pQueue->bmAlloc, iCur) == false, pQueue->rcOkay = VERR_INTERNAL_ERROR_3); 694 PPDMQUEUEITEMCORE pCur = (PPDMQUEUEITEMCORE)&pbItems[iCur * cbItem]; 695 iCur = pCur->iNext; 696 if (iCur == UINT32_MAX) 697 { 698 pCur->iNext = iPendingHead; 699 break; 700 } 701 } 702 703 iPendingHead = iNewPending; 704 } 557 705 } 558 706 559 /* next queue list */ 560 pQueue = pQueueNext; 561 pQueueNext = NULL; 562 } while (pQueue); 563 564 pdmUnlock(pVM); 707 STAM_REL_COUNTER_INC(&pQueue->StatFlushLeftovers); 708 } 709 710 STAM_PROFILE_STOP(&pQueue->StatFlushPrf,p); 565 711 return VINF_SUCCESS; 566 712 } … … 573 719 * @param pVM The cross context VM structure. 574 720 * @thread Emulation thread only. 575 */ 576 VMMR3_INT_DECL(void) PDMR3QueueFlushAll(PVM pVM) 721 * @note Internal, but exported for use in the testcase. 722 */ 723 VMMR3DECL(void) PDMR3QueueFlushAll(PVM pVM) 577 724 { 578 725 VM_ASSERT_EMT(pVM); … … 593 740 ASMAtomicBitClear(&pVM->pdm.s.fQueueFlushing, PDM_QUEUE_FLUSH_FLAG_PENDING_BIT); 594 741 595 for (PPDMQUEUE pCur = pVM->pUVM->pdm.s.pQueuesForced; pCur; pCur = pCur->pNext) 596 if ( pCur->pPendingR3 597 || pCur->pPendingR0) 598 pdmR3QueueFlush(pCur); 742 /* Scan the ring-0 queues: */ 743 size_t i = pVM->pdm.s.cRing0Queues; 744 while (i-- > 0) 745 { 746 PPDMQUEUE pQueue = pVM->pdm.s.apRing0Queues[i]; 747 if ( pQueue 748 && pQueue->iPending != UINT32_MAX 749 && pQueue->hTimer == NIL_TMTIMERHANDLE 750 && pQueue->rcOkay == VINF_SUCCESS) 751 pdmR3QueueFlush(pVM, pQueue); 752 } 753 754 /* Scan the ring-3 queues: */ 755 /** @todo Deal with destroy concurrency issues. */ 756 i = pVM->pdm.s.cRing3Queues; 757 while (i-- > 0) 758 { 759 PPDMQUEUE pQueue = pVM->pdm.s.papRing3Queues[i]; 760 if ( pQueue 761 && pQueue->iPending != UINT32_MAX 762 && pQueue->hTimer == NIL_TMTIMERHANDLE 763 && pQueue->rcOkay == VINF_SUCCESS) 764 pdmR3QueueFlush(pVM, pQueue); 765 } 599 766 600 767 ASMAtomicBitClear(&pVM->pdm.s.fQueueFlushing, PDM_QUEUE_FLUSH_FLAG_ACTIVE_BIT); … … 609 776 610 777 611 /**612 * Process pending items in one queue.613 *614 * @returns Success indicator.615 * If false the item the consumer said "enough!".616 * @param pQueue The queue.617 */618 static bool pdmR3QueueFlush(PPDMQUEUE pQueue)619 {620 STAM_PROFILE_START(&pQueue->StatFlushPrf,p);621 622 /*623 * Get the lists.624 */625 PPDMQUEUEITEMCORE pItems = ASMAtomicXchgPtrT(&pQueue->pPendingR3, NULL, PPDMQUEUEITEMCORE);626 RTR0PTR pItemsR0 = ASMAtomicXchgR0Ptr(&pQueue->pPendingR0, NIL_RTR0PTR);627 628 AssertMsgReturn( pItemsR0629 || pItems,630 ("Someone is racing us? This shouldn't happen!\n"),631 true);632 633 /*634 * Reverse the list (it's inserted in LIFO order to avoid semaphores, remember).635 */636 PPDMQUEUEITEMCORE pCur = pItems;637 pItems = NULL;638 while (pCur)639 {640 PPDMQUEUEITEMCORE pInsert = pCur;641 pCur = pCur->pNextR3;642 pInsert->pNextR3 = pItems;643 pItems = pInsert;644 }645 646 /*647 * Do the same for any pending R0 items.648 */649 while (pItemsR0)650 {651 PPDMQUEUEITEMCORE pInsert = (PPDMQUEUEITEMCORE)MMHyperR0ToR3(pQueue->pVMR3, pItemsR0);652 pItemsR0 = pInsert->pNextR0;653 pInsert->pNextR0 = NIL_RTR0PTR;654 pInsert->pNextR3 = pItems;655 pItems = pInsert;656 }657 658 /*659 * Feed the items to the consumer function.660 */661 Log2(("pdmR3QueueFlush: pQueue=%p enmType=%d pItems=%p\n", pQueue, pQueue->enmType, pItems));662 switch (pQueue->enmType)663 {664 case PDMQUEUETYPE_DEV:665 while (pItems)666 {667 if (!pQueue->u.Dev.pfnCallback(pQueue->u.Dev.pDevIns, pItems))668 break;669 pCur = pItems;670 pItems = pItems->pNextR3;671 pdmR3QueueFreeItem(pQueue, pCur);672 }673 break;674 675 case PDMQUEUETYPE_DRV:676 while (pItems)677 {678 if (!pQueue->u.Drv.pfnCallback(pQueue->u.Drv.pDrvIns, pItems))679 break;680 pCur = pItems;681 pItems = pItems->pNextR3;682 pdmR3QueueFreeItem(pQueue, pCur);683 }684 break;685 686 case PDMQUEUETYPE_INTERNAL:687 while (pItems)688 {689 if (!pQueue->u.Int.pfnCallback(pQueue->pVMR3, pItems))690 break;691 pCur = pItems;692 pItems = pItems->pNextR3;693 pdmR3QueueFreeItem(pQueue, pCur);694 }695 break;696 697 case PDMQUEUETYPE_EXTERNAL:698 while (pItems)699 {700 if (!pQueue->u.Ext.pfnCallback(pQueue->u.Ext.pvUser, pItems))701 break;702 pCur = pItems;703 pItems = pItems->pNextR3;704 pdmR3QueueFreeItem(pQueue, pCur);705 }706 break;707 708 default:709 AssertMsgFailed(("Invalid queue type %d\n", pQueue->enmType));710 break;711 }712 713 /*714 * Success?715 */716 if (pItems)717 {718 /*719 * Reverse the list.720 */721 pCur = pItems;722 pItems = NULL;723 while (pCur)724 {725 PPDMQUEUEITEMCORE pInsert = pCur;726 pCur = pInsert->pNextR3;727 pInsert->pNextR3 = pItems;728 pItems = pInsert;729 }730 731 /*732 * Insert the list at the tail of the pending list.733 */734 for (;;)735 {736 if (ASMAtomicCmpXchgPtr(&pQueue->pPendingR3, pItems, NULL))737 break;738 PPDMQUEUEITEMCORE pPending = ASMAtomicXchgPtrT(&pQueue->pPendingR3, NULL, PPDMQUEUEITEMCORE);739 if (pPending)740 {741 pCur = pPending;742 while (pCur->pNextR3)743 pCur = pCur->pNextR3;744 pCur->pNextR3 = pItems;745 pItems = pPending;746 }747 }748 749 STAM_REL_COUNTER_INC(&pQueue->StatFlushLeftovers);750 STAM_PROFILE_STOP(&pQueue->StatFlushPrf,p);751 return false;752 }753 754 STAM_PROFILE_STOP(&pQueue->StatFlushPrf,p);755 return true;756 }757 758 759 /**760 * Free an item.761 *762 * @param pQueue The queue.763 * @param pItem The item.764 */765 DECLINLINE(void) pdmR3QueueFreeItem(PPDMQUEUE pQueue, PPDMQUEUEITEMCORE pItem)766 {767 VM_ASSERT_EMT(pQueue->pVMR3);768 769 int i = pQueue->iFreeHead;770 int iNext = (i + 1) % (pQueue->cItems + PDMQUEUE_FREE_SLACK);771 772 pQueue->aFreeItems[i].pItemR3 = pItem;773 if (pQueue->pVMR0)774 pQueue->aFreeItems[i].pItemR0 = MMHyperR3ToR0(pQueue->pVMR3, pItem);775 776 if (!ASMAtomicCmpXchgU32(&pQueue->iFreeHead, iNext, i))777 AssertMsgFailed(("huh? i=%d iNext=%d iFreeHead=%d iFreeTail=%d\n", i, iNext, pQueue->iFreeHead, pQueue->iFreeTail));778 STAM_STATS({ ASMAtomicDecU32(&pQueue->cStatPending); });779 }780 781 778 782 779 /** … … 788 785 Assert(hTimer == pQueue->hTimer); 789 786 790 if ( pQueue->pPendingR3791 || pQueue->pPendingR0)792 pdmR3QueueFlush(pQueue); 787 if (pQueue->iPending != UINT32_MAX) 788 pdmR3QueueFlush(pVM, pQueue); 789 793 790 int rc = TMTimerSetMillies(pVM, hTimer, pQueue->cMilliesInterval); 794 791 AssertRC(rc); -
trunk/src/VBox/VMM/include/PDMInternal.h
r93554 r93609 985 985 986 986 987 /** Extra space in the free array. */ 988 #define PDMQUEUE_FREE_SLACK 16 987 /** Max number of items in a queue. */ 988 #define PDMQUEUE_MAX_ITEMS _16K 989 /** Max item size. */ 990 #define PDMQUEUE_MAX_ITEM_SIZE _1M 991 /** Max total queue item size for ring-0 capable queues. */ 992 #define PDMQUEUE_MAX_TOTAL_SIZE_R0 _8M 993 /** Max total queue item size for ring-3 only queues. */ 994 #define PDMQUEUE_MAX_TOTAL_SIZE_R3 _32M 989 995 990 996 /** … … 1003 1009 } PDMQUEUETYPE; 1004 1010 1005 /** Pointer to a PDM Queue. */1006 typedef struct PDMQUEUE *PPDMQUEUE;1007 1008 1011 /** 1009 1012 * PDM Queue. … … 1011 1014 typedef struct PDMQUEUE 1012 1015 { 1013 /** Pointer to the next queue in the list. */ 1014 R3PTRTYPE(PPDMQUEUE) pNext; 1016 /** Magic value (PDMQUEUE_MAGIC). */ 1017 uint32_t u32Magic; 1018 /** Item size (bytes). */ 1019 uint32_t cbItem; 1020 /** Number of items in the queue. */ 1021 uint32_t cItems; 1022 /** Offset of the the queue items relative to the PDMQUEUE structure. */ 1023 uint32_t offItems; 1024 1025 /** Interval timer. Only used if cMilliesInterval is non-zero. */ 1026 TMTIMERHANDLE hTimer; 1027 /** The interval between checking the queue for events. 1028 * The realtime timer below is used to do the waiting. 1029 * If 0, the queue will use the VM_FF_PDM_QUEUE forced action. */ 1030 uint32_t cMilliesInterval; 1031 1032 /** This is VINF_SUCCESS if the queue is okay, error status if not. */ 1033 int32_t rcOkay; 1034 uint32_t u32Padding; 1035 1036 /** Queue type. */ 1037 PDMQUEUETYPE enmType; 1015 1038 /** Type specific data. */ 1016 1039 union … … 1046 1069 R3PTRTYPE(void *) pvUser; 1047 1070 } Ext; 1071 struct 1072 { 1073 /** Generic callback pointer. */ 1074 RTR3PTR pfnCallback; 1075 /** Generic owner pointer. */ 1076 RTR3PTR pvOwner; 1077 } Gen; 1048 1078 } u; 1049 /** Queue type. */1050 PDMQUEUETYPE enmType;1051 /** The interval between checking the queue for events.1052 * The realtime timer below is used to do the waiting.1053 * If 0, the queue will use the VM_FF_PDM_QUEUE forced action. */1054 uint32_t cMilliesInterval;1055 /** Interval timer. Only used if cMilliesInterval is non-zero. */1056 TMTIMERHANDLE hTimer;1057 /** Pointer to the VM - R3. */1058 PVMR3 pVMR3;1059 /** LIFO of pending items - R3. */1060 R3PTRTYPE(PPDMQUEUEITEMCORE) volatile pPendingR3;1061 /** Pointer to the VM - R0. */1062 PVMR0 pVMR0;1063 /** LIFO of pending items - R0. */1064 R0PTRTYPE(PPDMQUEUEITEMCORE) volatile pPendingR0;1065 1066 /** Item size (bytes). */1067 uint32_t cbItem;1068 /** Number of items in the queue. */1069 uint32_t cItems;1070 /** Index to the free head (where we insert). */1071 uint32_t volatile iFreeHead;1072 /** Index to the free tail (where we remove). */1073 uint32_t volatile iFreeTail;1074 1079 1075 1080 /** Unique queue name. */ 1076 R3PTRTYPE(const char *) pszName; 1077 #if HC_ARCH_BITS == 32 1078 RTR3PTR Alignment1; 1079 #endif 1081 char szName[40]; 1082 1083 /** LIFO of pending items (item index), UINT32_MAX if empty. */ 1084 uint32_t volatile iPending; 1085 1086 /** State: Pending items. */ 1087 uint32_t volatile cStatPending; 1080 1088 /** Stat: Times PDMQueueAlloc fails. */ 1081 1089 STAMCOUNTER StatAllocFailures; … … 1086 1094 /** Stat: Queue flushes with pending items left over. */ 1087 1095 STAMCOUNTER StatFlushLeftovers; 1088 #ifdef VBOX_WITH_STATISTICS1089 1096 /** State: Profiling the flushing. */ 1090 1097 STAMPROFILE StatFlushPrf; 1091 /** State: Pending items. */ 1092 uint32_t volatile cStatPending; 1093 uint32_t volatile cAlignment; 1094 #endif 1095 1096 /** Array of pointers to free items. Variable size. */ 1097 struct PDMQUEUEFREEITEM 1098 { 1099 /** Pointer to the free item - HC Ptr. */ 1100 R3PTRTYPE(PPDMQUEUEITEMCORE) volatile pItemR3; 1101 /** Pointer to the free item - HC Ptr. */ 1102 R0PTRTYPE(PPDMQUEUEITEMCORE) volatile pItemR0; 1103 } aFreeItems[1]; 1098 uint64_t au64Padding[3]; 1099 1100 /** Allocation bitmap: Set bits means free, clear means allocated. */ 1101 RT_FLEXIBLE_ARRAY_EXTENSION 1102 uint64_t bmAlloc[RT_FLEXIBLE_ARRAY]; 1103 /* The items follows after the end of the bitmap */ 1104 1104 } PDMQUEUE; 1105 AssertCompileMemberAlignment(PDMQUEUE, bmAlloc, 64); 1106 /** Pointer to a PDM Queue. */ 1107 typedef struct PDMQUEUE *PPDMQUEUE; 1108 1109 /** Magic value PDMQUEUE::u32Magic (Bud Powell). */ 1110 #define PDMQUEUE_MAGIC UINT32_C(0x19240927) 1111 /** Magic value PDMQUEUE::u32Magic after destroy. */ 1112 #define PDMQUEUE_MAGIC_DEAD UINT32_C(0x19660731) 1105 1113 1106 1114 /** @name PDM::fQueueFlushing … … 1115 1123 #define PDM_QUEUE_FLUSH_FLAG_PENDING_BIT 1 1116 1124 /** @} */ 1125 1126 /** 1127 * Ring-0 queue 1128 * 1129 * @author bird (2022-02-04) 1130 */ 1131 typedef struct PDMQUEUER0 1132 { 1133 /** Pointer to the shared queue data. */ 1134 R0PTRTYPE(PPDMQUEUE) pQueue; 1135 /** The memory allocation. */ 1136 RTR0MEMOBJ hMemObj; 1137 /** The ring-3 mapping object. */ 1138 RTR0MEMOBJ hMapObj; 1139 /** The owner pointer. This is NULL if not allocated. */ 1140 RTR0PTR pvOwner; 1141 /** Queue item size. */ 1142 uint32_t cbItem; 1143 /** Number of queue items. */ 1144 uint32_t cItems; 1145 /** Offset of the the queue items relative to the PDMQUEUE structure. */ 1146 uint32_t offItems; 1147 uint32_t u32Reserved; 1148 } PDMQUEUER0; 1117 1149 1118 1150 … … 1187 1219 AssertCompileMemberAlignment(PDMTASKSET, fTriggered, 64); 1188 1220 AssertCompileMemberAlignment(PDMTASKSET, aTasks, 64); 1189 /** Magic value for PDMTASKSET::u32Magic . */1190 #define PDMTASKSET_MAGIC UINT32_C(0x193 20314)1221 /** Magic value for PDMTASKSET::u32Magic (Quincy Delight Jones Jr.). */ 1222 #define PDMTASKSET_MAGIC UINT32_C(0x19330314) 1191 1223 /** Pointer to a task set. */ 1192 1224 typedef PDMTASKSET *PPDMTASKSET; … … 1253 1285 struct PDMDEVHLPTASKPCISETIRQ 1254 1286 { 1255 /** Pointer to the PCI device (R3 Ptr). */1256 R3PTRTYPE(PPDMPCIDEV) pPciDevR3;1287 /** Index of the PCI device (into PDMDEVINSR3::apPciDevs). */ 1288 uint32_t idxPciDev; 1257 1289 /** The IRQ */ 1258 int 1290 int32_t iIrq; 1259 1291 /** The new level. */ 1260 int 1292 int32_t iLevel; 1261 1293 /** The IRQ tag and source. */ 1262 1294 uint32_t uTagSrc; … … 1419 1451 /** @name Queues 1420 1452 * @{ */ 1421 /** Queue in which devhlp tasks are queued for R3 execution - R3 Ptr. */ 1422 R3PTRTYPE(PPDMQUEUE) pDevHlpQueueR3; 1423 /** Queue in which devhlp tasks are queued for R3 execution - R0 Ptr. */ 1424 R0PTRTYPE(PPDMQUEUE) pDevHlpQueueR0; 1425 /** Pointer to the queue which should be manually flushed - R0 Ptr. 1426 * Only touched by EMT. */ 1427 R0PTRTYPE(struct PDMQUEUE *) pQueueFlushR0; 1453 /** Number of ring-0 capable queues in apQueues. */ 1454 uint32_t cRing0Queues; 1455 uint32_t u32Padding1; 1456 /** Array of ring-0 capable queues running in parallel to PDMR0PERVM::aQueues. */ 1457 R3PTRTYPE(PPDMQUEUE) apRing0Queues[16]; 1458 /** Number of ring-3 only queues */ 1459 uint32_t cRing3Queues; 1460 /** The allocation size of the ring-3 queue handle table. */ 1461 uint32_t cRing3QueuesAlloc; 1462 /** Handle table for the ring-3 only queues. */ 1463 R3PTRTYPE(PPDMQUEUE *) papRing3Queues; 1464 1465 /** Queue in which devhlp tasks are queued for R3 execution. */ 1466 PDMQUEUEHANDLE hDevHlpQueue; 1428 1467 /** Bitmask controlling the queue flushing. 1429 1468 * See PDM_QUEUE_FLUSH_FLAG_ACTIVE and PDM_QUEUE_FLUSH_FLAG_PENDING. */ … … 1507 1546 /** Number of valid ring-0 device instances (apDevInstances). */ 1508 1547 uint32_t cDevInstances; 1509 uint32_t u32Padding ;1548 uint32_t u32Padding1; 1510 1549 /** Pointer to ring-0 device instances. */ 1511 1550 R0PTRTYPE(struct PDMDEVINSR0 *) apDevInstances[190]; 1551 /** Number of valid ring-0 queue instances (aQueues). */ 1552 uint32_t cQueues; 1553 uint32_t u32Padding2; 1554 /** Array of ring-0 queues. */ 1555 PDMQUEUER0 aQueues[16]; 1512 1556 } PDMR0PERVM; 1513 1557 … … 1519 1563 { 1520 1564 /** @todo move more stuff over here. */ 1521 1522 /** Linked list of timer driven PDM queues.1523 * Currently serialized by PDM::CritSect. */1524 R3PTRTYPE(struct PDMQUEUE *) pQueuesTimer;1525 /** Linked list of force action driven PDM queues.1526 * Currently serialized by PDM::CritSect. */1527 R3PTRTYPE(struct PDMQUEUE *) pQueuesForced;1528 1565 1529 1566 /** Lock protecting the lists below it. */ … … 1660 1697 char *pdmR3FileR3(const char *pszFile, bool fShared); 1661 1698 int pdmR3LoadR3U(PUVM pUVM, const char *pszFilename, const char *pszName); 1662 1699 #endif /* IN_RING3 */ 1700 1701 void pdmQueueInit(PPDMQUEUE pQueue, uint32_t cbBitmap, uint32_t cbItem, uint32_t cItems, 1702 const char *pszName, PDMQUEUETYPE enmType, RTR3PTR pfnCallback, RTR3PTR pvOwner); 1703 1704 #ifdef IN_RING3 1663 1705 int pdmR3TaskInit(PVM pVM); 1664 1706 void pdmR3TaskTerm(PVM pVM); … … 1677 1719 int pdmR3ThreadSuspendAll(PVM pVM); 1678 1720 1679 # ifdef VBOX_WITH_PDM_ASYNC_COMPLETION1721 # ifdef VBOX_WITH_PDM_ASYNC_COMPLETION 1680 1722 int pdmR3AsyncCompletionInit(PVM pVM); 1681 1723 int pdmR3AsyncCompletionTerm(PVM pVM); … … 1688 1730 int pdmR3AsyncCompletionTemplateDestroyDriver(PVM pVM, PPDMDRVINS pDrvIns); 1689 1731 int pdmR3AsyncCompletionTemplateDestroyUsb(PVM pVM, PPDMUSBINS pUsbIns); 1690 # endif1691 1692 # ifdef VBOX_WITH_NETSHAPER1732 # endif 1733 1734 # ifdef VBOX_WITH_NETSHAPER 1693 1735 int pdmR3NetShaperInit(PVM pVM); 1694 1736 int pdmR3NetShaperTerm(PVM pVM); 1695 # endif1737 # endif 1696 1738 1697 1739 int pdmR3BlkCacheInit(PVM pVM); 1698 1740 void pdmR3BlkCacheTerm(PVM pVM); 1699 1741 int pdmR3BlkCacheResume(PVM pVM); 1700 1701 1742 #endif /* IN_RING3 */ 1702 1743 … … 1726 1767 #ifdef IN_RING0 1727 1768 DECLHIDDEN(bool) pdmR0IsaSetIrq(PGVM pGVM, int iIrq, int iLevel, uint32_t uTagSrc); 1769 DECLHIDDEN(void) pdmR0QueueDestroy(PGVM pGVM, uint32_t iQueue); 1770 1728 1771 #endif 1729 1772 -
trunk/src/VBox/VMM/testcase/Makefile.kmk
r93115 r93609 69 69 tstCompressionBenchmark \ 70 70 tstIEMCheckMc \ 71 tstPDMQueue \ 71 72 tstSSM \ 72 73 tstVMMR0CallHost-1 \ … … 459 460 endif 460 461 endif 462 463 # 464 # PDM Queue tests. 465 # 466 tstPDMQueue_TEMPLATE := VBOXR3EXE 467 tstPDMQueue_DEFS = $(VMM_COMMON_DEFS) 468 tstPDMQueue_SOURCES := tstPDMQueue.cpp 469 tstPDMQueue_LIBS := $(LIB_VMM) $(LIB_RUNTIME) 461 470 462 471
Note:
See TracChangeset
for help on using the changeset viewer.