- Timestamp:
- Jul 1, 2009 2:46:19 PM (16 years ago)
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/PDMInternal.h
r21035 r21128 724 724 } PDMQUEUE; 725 725 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 726 741 727 742 /** … … 888 903 * Only touched by EMT. */ 889 904 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; 892 908 893 909 /** Head of the PDM Thread list. (singly linked) */ -
trunk/src/VBox/VMM/PDMQueue.cpp
r21126 r21128 627 627 LogFlow(("PDMR3QueuesFlush:\n")); 628 628 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 */ 629 637 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); 636 641 do 637 642 { 638 643 for (PPDMQUEUE pCur = pVM->pdm.s.pQueuesForced; pCur; pCur = pCur->pNext) 639 {640 644 if ( pCur->pPendingR3 641 645 || pCur->pPendingR0 642 646 || 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); 670 652 } 671 653 } -
trunk/src/VBox/VMM/VMMAll/PDMAllQueue.cpp
r20874 r21128 92 92 Log2(("PDMQueueInsert: VM_FF_PDM_QUEUES %d -> 1\n", VM_FF_ISSET(pVM, VM_FF_PDM_QUEUES))); 93 93 VM_FF_SET(pVM, VM_FF_PDM_QUEUES); 94 ASMAtomicBitSet(&pVM->pdm.s.fQueueFlushing, PDM_QUEUE_FLUSH_FLAG_PENDING_BIT); 94 95 #ifdef IN_RING3 95 96 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.