VirtualBox

Changeset 21128 in vbox for trunk


Ignore:
Timestamp:
Jul 1, 2009 2:46:19 PM (16 years ago)
Author:
vboxsync
Message:

PDMQueue: Fixed the flushing loop when a consumer (NAT?) had had enough.

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

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/PDMInternal.h

    r21035 r21128  
    724724} PDMQUEUE;
    725725
     726/** @name PDM::fQueueFlushing
     727 * @{ */
     728/** Indicating that an queue insert has been performed. */
     729#define PDM_QUEUE_FLUSH_FLAG_ACTIVE         RT_BIT_32(PDM_QUEUE_FLUSH_FLAG_ACTIVE_BIT)
     730/** The bit number for PDM_QUEUE_FLUSH_FLAG_ACTIVE_BIT.  */
     731#define PDM_QUEUE_FLUSH_FLAG_ACTIVE_BIT     0
     732/** Indicating there are pending items.
     733 * This is make sure we don't miss inserts happening during flushing. The FF
     734 * cannot be used for this since it has to be cleared immediately to prevent
     735 * other EMTs from spinning. */
     736#define PDM_QUEUE_FLUSH_FLAG_PENDING        RT_BIT_32(PDM_QUEUE_FLUSH_FLAG_PENDING_BIT)
     737/** The bit number for PDM_QUEUE_FLUSH_FLAG_PENDING.  */
     738#define PDM_QUEUE_FLUSH_FLAG_PENDING_BIT    1
     739/** }@  */
     740
    726741
    727742/**
     
    888903     * Only touched by EMT. */
    889904    RCPTRTYPE(struct PDMQUEUE *)    pQueueFlushRC;
    890     /** Set if we're currently checking queues to prevent other VCPUs from doing the same concurrently. */
    891     volatile uint32_t               fQueueFlushing;
     905    /** Bitmask controlling the queue flushing.
     906     * See PDM_QUEUE_FLUSH_FLAG_ACTIVE and PDM_QUEUE_FLUSH_FLAG_PENDING. */
     907    uint32_t volatile               fQueueFlushing;
    892908
    893909    /** Head of the PDM Thread list. (singly linked) */
  • trunk/src/VBox/VMM/PDMQueue.cpp

    r21126 r21128  
    627627    LogFlow(("PDMR3QueuesFlush:\n"));
    628628
     629    /*
     630     * Only let one EMT flushing queues at any one time to queue preserve order
     631     * and to avoid wasting time. The FF is always cleared here, because it's
     632     * only used to get someones attention. Queue inserts occuring during the
     633     * flush are caught using the pending bit.
     634     *
     635     * Note. The order in which the FF and pending bit are set and cleared is important.
     636     */
    629637    VM_FF_CLEAR(pVM, VM_FF_PDM_QUEUES);
    630 
    631 check_queue:
    632     /* Prevent other VCPUs from flushing queues at the same time; we'll never flush an item twice, but the order might change. */
    633     if (ASMAtomicCmpXchgU32(&pVM->pdm.s.fQueueFlushing, 1, 0))
    634     {
    635         /* Use atomic test and clear to prevent useless checks; pdmR3QueueFlush is SMP safe. */
     638    if (!ASMAtomicBitTestAndSet(&pVM->pdm.s.fQueueFlushing, PDM_QUEUE_FLUSH_FLAG_ACTIVE_BIT))
     639    {
     640        ASMAtomicBitClear(&pVM->pdm.s.fQueueFlushing, PDM_QUEUE_FLUSH_FLAG_PENDING_BIT);
    636641        do
    637642        {
    638643            for (PPDMQUEUE pCur = pVM->pdm.s.pQueuesForced; pCur; pCur = pCur->pNext)
    639             {
    640644                if (    pCur->pPendingR3
    641645                    ||  pCur->pPendingR0
    642646                    ||  pCur->pPendingRC)
    643                 {
    644                     if (    pdmR3QueueFlush(pCur)
    645                         &&  (   pCur->pPendingR3
    646                              || pCur->pPendingR0))
    647                         /* new items arrived while flushing. */
    648                         pdmR3QueueFlush(pCur);
    649                 }
    650             }
    651         }
    652         while (VM_FF_TESTANDCLEAR(pVM, VM_FF_PDM_QUEUES_BIT));
    653 
    654         ASMAtomicXchgU32(&pVM->pdm.s.fQueueFlushing, 0);
    655 
    656         /* Check if we missed anything. */
    657         for (PPDMQUEUE pCur = pVM->pdm.s.pQueuesForced; pCur; pCur = pCur->pNext)
    658         {
    659             if (    pCur->pPendingR3
    660                 ||  pCur->pPendingR0
    661                 ||  pCur->pPendingRC)
    662             {
    663                 VM_FF_SET(pVM, VM_FF_PDM_QUEUES);
    664                 break;
    665             }
    666         }
    667         if (VM_FF_TESTANDCLEAR(pVM, VM_FF_PDM_QUEUES_BIT))
    668             goto check_queue;
    669 
     647                    pdmR3QueueFlush(pCur);
     648            VM_FF_CLEAR(pVM, VM_FF_PDM_QUEUES);
     649        } while (ASMAtomicBitTestAndClear(&pVM->pdm.s.fQueueFlushing, PDM_QUEUE_FLUSH_FLAG_PENDING_BIT));
     650
     651        ASMAtomicBitClear(&pVM->pdm.s.fQueueFlushing, PDM_QUEUE_FLUSH_FLAG_ACTIVE_BIT);
    670652    }
    671653}
  • trunk/src/VBox/VMM/VMMAll/PDMAllQueue.cpp

    r20874 r21128  
    9292        Log2(("PDMQueueInsert: VM_FF_PDM_QUEUES %d -> 1\n", VM_FF_ISSET(pVM, VM_FF_PDM_QUEUES)));
    9393        VM_FF_SET(pVM, VM_FF_PDM_QUEUES);
     94        ASMAtomicBitSet(&pVM->pdm.s.fQueueFlushing, PDM_QUEUE_FLUSH_FLAG_PENDING_BIT);
    9495#ifdef IN_RING3
    9596        REMR3NotifyQueuePending(pVM); /** @todo r=bird: we can remove REMR3NotifyQueuePending and let VMR3NotifyFF do the work. */
Note: See TracChangeset for help on using the changeset viewer.

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