VirtualBox

Changeset 98570 in vbox for trunk/src/VBox/VMM


Ignore:
Timestamp:
Feb 14, 2023 9:33:06 PM (2 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
155854
Message:

VMM/PDMQueue: Use the ListCritSect to relax ring-3 queue creation and destruction restrictions, to avoid annoying assertions (audio driver destruction). bugref:10093

Location:
trunk/src/VBox/VMM
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR3/PDMQueue.cpp

    r98103 r98570  
    4848*   Internal Functions                                                                                                           *
    4949*********************************************************************************************************************************/
     50static int                  pdmR3QueueDestroyLocked(PVM pVM, PDMQUEUEHANDLE hQueue, void *pvOwner);
    5051static DECLCALLBACK(void)   pdmR3QueueTimer(PVM pVM, TMTIMERHANDLE hTimer, void *pvUser);
    5152
     
    6162 * @param   cMilliesInterval    Number of milliseconds between polling the queue.
    6263 *                              If 0 then the emulation thread will be notified whenever an item arrives.
    63  * @param   fRZEnabled          Set if the queue will be used from RC/R0 and need to be allocated from the hyper heap.
     64 * @param   fRZEnabled          Set if the queue will be used from RC/R0,
     65 *                              these can only be created from EMT0.
    6466 * @param   pszName             The queue name. Unique. Not copied.
    6567 * @param   enmType             Owner type.
     
    6769 * @param   uCallback           Callback function.
    6870 * @param   phQueue             Where to store the queue handle.
    69  */
    70 static int pdmR3QueueCreate(PVM pVM, size_t cbItem, uint32_t cItems, uint32_t cMilliesInterval, bool fRZEnabled,
    71                             const char *pszName, PDMQUEUETYPE enmType, void *pvOwner, uintptr_t uCallback,
    72                             PDMQUEUEHANDLE *phQueue)
     71 *
     72 * @thread  Emulation thread only. When @a fRZEnables is true only EMT0.
     73 * @note    Caller owns ListCritSect.
     74 */
     75static int pdmR3QueueCreateLocked(PVM pVM, size_t cbItem, uint32_t cItems, uint32_t cMilliesInterval, bool fRZEnabled,
     76                                  const char *pszName, PDMQUEUETYPE enmType, void *pvOwner, uintptr_t uCallback,
     77                                  PDMQUEUEHANDLE *phQueue)
    7378{
    7479    /*
    7580     * Validate and adjust the input.
    7681     */
    77     VM_ASSERT_EMT0_RETURN(pVM, VERR_VM_THREAD_NOT_EMT); /* serialization by exclusivity */
     82    if (fRZEnabled)
     83        VM_ASSERT_EMT0_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
     84    else
     85        VM_ASSERT_EMT_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
    7886
    7987    cbItem = RT_ALIGN(cbItem, sizeof(uint64_t));
     
    192200        {
    193201            if (!fRZEnabled)
    194                 PDMR3QueueDestroy(pVM, hQueue, pvOwner);
     202                pdmR3QueueDestroyLocked(pVM, hQueue, pvOwner);
    195203            /* else: will clean up queue when VM is destroyed */
    196204            return rc;
     
    241249 * @param   pszName             The queue name. Unique. Copied.
    242250 * @param   phQueue             Where to store the queue handle on success.
    243  * @thread  Emulation thread only.
     251 * @thread  Emulation thread only. Only EMT0 when @a fRZEnables is true.
    244252 */
    245253VMMR3_INT_DECL(int) PDMR3QueueCreateDevice(PVM pVM, PPDMDEVINS pDevIns, size_t cbItem, uint32_t cItems,
     
    263271     * Create the queue.
    264272     */
    265     int rc = pdmR3QueueCreate(pVM, cbItem, cItems, cMilliesInterval, fRZEnabled, pszName,
    266                               PDMQUEUETYPE_DEV, pDevIns, (uintptr_t)pfnCallback, phQueue);
     273    int rc = RTCritSectEnter(&pVM->pUVM->pdm.s.ListCritSect);
     274    AssertRCReturn(rc, rc);
     275
     276    rc = pdmR3QueueCreateLocked(pVM, cbItem, cItems, cMilliesInterval, fRZEnabled, pszName,
     277                                PDMQUEUETYPE_DEV, pDevIns, (uintptr_t)pfnCallback, phQueue);
     278
     279    RTCritSectLeave(&pVM->pUVM->pdm.s.ListCritSect);
    267280    if (RT_SUCCESS(rc))
    268281        Log(("PDM: Created device queue %#RX64; cbItem=%d cItems=%d cMillies=%d pfnCallback=%p pDevIns=%p\n",
     
    303316     * Create the queue.
    304317     */
    305     int rc = pdmR3QueueCreate(pVM, cbItem, cItems, cMilliesInterval, false /*fRZEnabled*/, pszName,
    306                               PDMQUEUETYPE_DRV, pDrvIns, (uintptr_t)pfnCallback, phQueue);
     318    int rc = RTCritSectEnter(&pVM->pUVM->pdm.s.ListCritSect);
     319    AssertRCReturn(rc, rc);
     320
     321    rc = pdmR3QueueCreateLocked(pVM, cbItem, cItems, cMilliesInterval, false /*fRZEnabled*/, pszName,
     322                                PDMQUEUETYPE_DRV, pDrvIns, (uintptr_t)pfnCallback, phQueue);
     323
     324    RTCritSectLeave(&pVM->pUVM->pdm.s.ListCritSect);
    307325    if (RT_SUCCESS(rc))
    308326        Log(("PDM: Created driver queue %#RX64; cbItem=%d cItems=%d cMillies=%d pfnCallback=%p pDrvIns=%p\n",
     
    325343 * @param   pszName             The queue name. Unique. Copied.
    326344 * @param   phQueue             Where to store the queue handle on success.
    327  * @thread  Emulation thread only.
     345 * @thread  Emulation thread only. When @a fRZEnables is true only EMT0.
    328346 */
    329347VMMR3_INT_DECL(int) PDMR3QueueCreateInternal(PVM pVM, size_t cbItem, uint32_t cItems, uint32_t cMilliesInterval,
     
    343361     * Create the queue.
    344362     */
    345     int rc = pdmR3QueueCreate(pVM, cbItem, cItems, cMilliesInterval, fRZEnabled, pszName,
    346                               PDMQUEUETYPE_INTERNAL, pVM, (uintptr_t)pfnCallback, phQueue);
     363    int rc = RTCritSectEnter(&pVM->pUVM->pdm.s.ListCritSect);
     364    AssertRCReturn(rc, rc);
     365
     366    rc = pdmR3QueueCreateLocked(pVM, cbItem, cItems, cMilliesInterval, fRZEnabled, pszName,
     367                                PDMQUEUETYPE_INTERNAL, pVM, (uintptr_t)pfnCallback, phQueue);
     368
     369    RTCritSectLeave(&pVM->pUVM->pdm.s.ListCritSect);
    347370    if (RT_SUCCESS(rc))
    348371        Log(("PDM: Created internal queue %p; cbItem=%d cItems=%d cMillies=%d pfnCallback=%p\n",
     
    383406     * Create the queue.
    384407     */
    385     int rc = pdmR3QueueCreate(pVM, cbItem, cItems, cMilliesInterval, false /*fRZEnabled*/, pszName,
    386                               PDMQUEUETYPE_EXTERNAL, pvUser, (uintptr_t)pfnCallback, phQueue);
     408    int rc = RTCritSectEnter(&pVM->pUVM->pdm.s.ListCritSect);
     409    AssertRCReturn(rc, rc);
     410
     411    rc = pdmR3QueueCreateLocked(pVM, cbItem, cItems, cMilliesInterval, false /*fRZEnabled*/, pszName,
     412                                PDMQUEUETYPE_EXTERNAL, pvUser, (uintptr_t)pfnCallback, phQueue);
     413
     414    RTCritSectLeave(&pVM->pUVM->pdm.s.ListCritSect);
    387415    if (RT_SUCCESS(rc))
    388416        Log(("PDM: Created external queue %p; cbItem=%d cItems=%d cMillies=%d pfnCallback=%p pvUser=%p\n",
     
    399427 * @param   hQueue      Handle to the queue that should be destroyed.
    400428 * @param   pvOwner     The owner address.
    401  * @thread  EMT(0)
    402  * @note    Externally visible mainly for testing purposes.
    403  */
    404 VMMR3DECL(int) PDMR3QueueDestroy(PVM pVM, PDMQUEUEHANDLE hQueue, void *pvOwner)
    405 {
    406     LogFlow(("PDMR3QueueDestroy: hQueue=%p pvOwner=%p\n", hQueue, pvOwner));
     429 * @thread  EMT
     430 */
     431static int pdmR3QueueDestroyLocked(PVM pVM, PDMQUEUEHANDLE hQueue, void *pvOwner)
     432{
     433    LogFlow(("pdmR3QueueDestroyLocked: hQueue=%p pvOwner=%p\n", hQueue, pvOwner));
     434    Assert(RTCritSectIsOwner(&pVM->pUVM->pdm.s.ListCritSect));
    407435
    408436    /*
    409437     * Validate input.
    410438     */
    411     VM_ASSERT_EMT0_RETURN(pVM, VERR_VM_THREAD_NOT_EMT); /* serialization */
     439    VM_ASSERT_EMT_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
    412440    if (hQueue == NIL_PDMQUEUEHANDLE)
    413441        return VINF_SUCCESS;
     
    469497
    470498/**
     499 * Destroy a queue.
     500 *
     501 * @returns VBox status code.
     502 * @param   pVM         Pointer to the cross context VM structure.
     503 * @param   hQueue      Handle to the queue that should be destroyed.
     504 * @param   pvOwner     The owner address.
     505 * @thread  EMT
     506 * @note    Externally visible mainly for testing purposes.
     507 */
     508VMMR3DECL(int) PDMR3QueueDestroy(PVM pVM, PDMQUEUEHANDLE hQueue, void *pvOwner)
     509{
     510    PUVM const pUVM = pVM->pUVM;
     511    RTCritSectEnter(&pUVM->pdm.s.ListCritSect);
     512
     513    int rc = pdmR3QueueDestroyLocked(pVM, hQueue, pvOwner);
     514
     515    RTCritSectLeave(&pUVM->pdm.s.ListCritSect);
     516    return rc;
     517}
     518
     519
     520/**
    471521 * Destroy a all queues with a given owner.
    472522 *
     
    475525 * @param   pvOwner     The owner pointer.
    476526 * @param   enmType     Owner type.
    477  * @thread  EMT(0)
     527 * @thread  EMT
    478528 */
    479529static int pdmR3QueueDestroyByOwner(PVM pVM, void *pvOwner, PDMQUEUETYPE enmType)
     
    486536    AssertPtrReturn(pvOwner, VERR_INVALID_PARAMETER);
    487537    AssertReturn(pvOwner != pVM, VERR_INVALID_PARAMETER);
    488     VM_ASSERT_EMT0_RETURN(pVM, VERR_VM_THREAD_NOT_EMT); /* serialization */
     538    VM_ASSERT_EMT_RETURN(pVM, VERR_VM_THREAD_NOT_EMT); /* Not requiring EMT0 here as we cannot destroy RZ capable ones here. */
    489539
    490540    /*
    491541     * Scan and destroy.
    492542     */
     543    PUVM const pUVM = pVM->pUVM;
     544    RTCritSectEnter(&pUVM->pdm.s.ListCritSect);
     545
    493546    uint32_t i = pVM->pdm.s.cRing0Queues;
    494547    while (i-- > 0)
     
    511564            && pQueue->u.Gen.pvOwner == pvOwner
    512565            && pQueue->enmType       == enmType)
    513             PDMR3QueueDestroy(pVM, i + RT_ELEMENTS(pVM->pdm.s.apRing0Queues), pvOwner);
    514     }
    515 
     566            pdmR3QueueDestroyLocked(pVM, i + RT_ELEMENTS(pVM->pdm.s.apRing0Queues), pvOwner);
     567    }
     568
     569    RTCritSectLeave(&pUVM->pdm.s.ListCritSect);
    516570    return VINF_SUCCESS;
    517571}
     
    813867DECLHIDDEN(void) pdmR3QueueTerm(PVM pVM)
    814868{
     869    PUVM const pUVM = pVM->pUVM;
     870    RTCritSectEnter(&pUVM->pdm.s.ListCritSect);
     871
    815872    if (pVM->pdm.s.papRing3Queues)
    816873    {
     
    824881                PPDMQUEUE pQueue = pVM->pdm.s.papRing3Queues[i];
    825882
    826                 PDMR3QueueDestroy(pVM, RT_ELEMENTS(pVM->pdm.s.apRing0Queues) + i, pQueue->u.Gen.pvOwner);
     883                pdmR3QueueDestroyLocked(pVM, RT_ELEMENTS(pVM->pdm.s.apRing0Queues) + i, pQueue->u.Gen.pvOwner);
    827884                Assert(!pVM->pdm.s.papRing3Queues[i]);
    828885            }
     
    832889        pVM->pdm.s.papRing3Queues    = NULL;
    833890    }
    834 }
     891
     892    RTCritSectLeave(&pUVM->pdm.s.ListCritSect);
     893}
  • trunk/src/VBox/VMM/include/PDMInternal.h

    r98122 r98570  
    15141514    /** Array of ring-0 capable queues running in parallel to PDMR0PERVM::aQueues. */
    15151515    R3PTRTYPE(PPDMQUEUE)            apRing0Queues[16];
    1516     /** Number of ring-3 only queues  */
     1516
     1517    /** Number of ring-3 only queues.
     1518     * PDMUSERPERVM::ListCritSect protects this and the next two members. */
    15171519    uint32_t                        cRing3Queues;
    15181520    /** The allocation size of the ring-3 queue handle table. */
     
    16501652    /** @todo move more stuff over here. */
    16511653
    1652     /** Lock protecting the lists below it. */
     1654    /** Lock protecting the lists below it and the queue list. */
    16531655    RTCRITSECT                      ListCritSect;
    16541656    /** Pointer to list of loaded modules. */
Note: See TracChangeset for help on using the changeset viewer.

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