VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMAll/PDMAllQueue.cpp@ 78298

Last change on this file since 78298 was 76553, checked in by vboxsync, 6 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 6.1 KB
Line 
1/* $Id: PDMAllQueue.cpp 76553 2019-01-01 01:45:53Z vboxsync $ */
2/** @file
3 * PDM Queue - Transport data and tasks to EMT and R3.
4 */
5
6/*
7 * Copyright (C) 2006-2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define LOG_GROUP LOG_GROUP_PDM_QUEUE
23#include "PDMInternal.h"
24#include <VBox/vmm/pdm.h>
25#ifndef IN_RC
26# ifdef VBOX_WITH_REM
27# include <VBox/vmm/rem.h>
28# endif
29# include <VBox/vmm/mm.h>
30#endif
31#include <VBox/vmm/vm.h>
32#include <iprt/errcore.h>
33#include <VBox/log.h>
34#include <iprt/asm.h>
35#include <iprt/assert.h>
36
37
38/**
39 * Allocate an item from a queue.
40 * The allocated item must be handed on to PDMR3QueueInsert() after the
41 * data have been filled in.
42 *
43 * @returns Pointer to allocated queue item.
44 * @returns NULL on failure. The queue is exhausted.
45 * @param pQueue The queue handle.
46 * @thread Any thread.
47 */
48VMMDECL(PPDMQUEUEITEMCORE) PDMQueueAlloc(PPDMQUEUE pQueue)
49{
50 Assert(VALID_PTR(pQueue) && pQueue->CTX_SUFF(pVM));
51 PPDMQUEUEITEMCORE pNew;
52 uint32_t iNext;
53 uint32_t i;
54 do
55 {
56 i = pQueue->iFreeTail;
57 if (i == pQueue->iFreeHead)
58 {
59 STAM_REL_COUNTER_INC(&pQueue->StatAllocFailures);
60 return NULL;
61 }
62 pNew = pQueue->aFreeItems[i].CTX_SUFF(pItem);
63 iNext = (i + 1) % (pQueue->cItems + PDMQUEUE_FREE_SLACK);
64 } while (!ASMAtomicCmpXchgU32(&pQueue->iFreeTail, iNext, i));
65 return pNew;
66}
67
68
69/**
70 * Sets the FFs and fQueueFlushed.
71 *
72 * @param pQueue The PDM queue.
73 */
74static void pdmQueueSetFF(PPDMQUEUE pQueue)
75{
76 PVM pVM = pQueue->CTX_SUFF(pVM);
77 Log2(("PDMQueueInsert: VM_FF_PDM_QUEUES %d -> 1\n", VM_FF_IS_SET(pVM, VM_FF_PDM_QUEUES)));
78 VM_FF_SET(pVM, VM_FF_PDM_QUEUES);
79 ASMAtomicBitSet(&pVM->pdm.s.fQueueFlushing, PDM_QUEUE_FLUSH_FLAG_PENDING_BIT);
80#ifdef IN_RING3
81# ifdef VBOX_WITH_REM
82 REMR3NotifyQueuePending(pVM); /** @todo r=bird: we can remove REMR3NotifyQueuePending and let VMR3NotifyFF do the work. */
83# endif
84 VMR3NotifyGlobalFFU(pVM->pUVM, VMNOTIFYFF_FLAGS_DONE_REM);
85#endif
86}
87
88
89/**
90 * Queue an item.
91 * The item must have been obtained using PDMQueueAlloc(). Once the item
92 * have been passed to this function it must not be touched!
93 *
94 * @param pQueue The queue handle.
95 * @param pItem The item to insert.
96 * @thread Any thread.
97 */
98VMMDECL(void) PDMQueueInsert(PPDMQUEUE pQueue, PPDMQUEUEITEMCORE pItem)
99{
100 Assert(VALID_PTR(pQueue) && pQueue->CTX_SUFF(pVM));
101 Assert(VALID_PTR(pItem));
102
103#if 0 /* the paranoid android version: */
104 void *pvNext;
105 do
106 {
107 pvNext = ASMAtomicUoReadPtr((void * volatile *)&pQueue->CTX_SUFF(pPending));
108 ASMAtomicUoWritePtr((void * volatile *)&pItem->CTX_SUFF(pNext), pvNext);
109 } while (!ASMAtomicCmpXchgPtr(&pQueue->CTX_SUFF(pPending), pItem, pvNext));
110#else
111 PPDMQUEUEITEMCORE pNext;
112 do
113 {
114 pNext = pQueue->CTX_SUFF(pPending);
115 pItem->CTX_SUFF(pNext) = pNext;
116 } while (!ASMAtomicCmpXchgPtr(&pQueue->CTX_SUFF(pPending), pItem, pNext));
117#endif
118
119 if (!pQueue->pTimer)
120 pdmQueueSetFF(pQueue);
121 STAM_REL_COUNTER_INC(&pQueue->StatInsert);
122 STAM_STATS({ ASMAtomicIncU32(&pQueue->cStatPending); });
123}
124
125
126/**
127 * Queue an item.
128 * The item must have been obtained using PDMQueueAlloc(). Once the item
129 * have been passed to this function it must not be touched!
130 *
131 * @param pQueue The queue handle.
132 * @param pItem The item to insert.
133 * @param NanoMaxDelay The maximum delay before processing the queue, in nanoseconds.
134 * This applies only to GC.
135 * @thread Any thread.
136 */
137VMMDECL(void) PDMQueueInsertEx(PPDMQUEUE pQueue, PPDMQUEUEITEMCORE pItem, uint64_t NanoMaxDelay)
138{
139 NOREF(NanoMaxDelay);
140 PDMQueueInsert(pQueue, pItem);
141#ifdef IN_RC
142 PVM pVM = pQueue->CTX_SUFF(pVM);
143 /** @todo figure out where to put this, the next bit should go there too.
144 if (NanoMaxDelay)
145 {
146
147 }
148 else */
149 {
150 VMCPU_FF_SET(VMMGetCpu0(pVM), VMCPU_FF_TO_R3);
151 Log2(("PDMQueueInsertEx: Setting VMCPU_FF_TO_R3\n"));
152 }
153#endif
154}
155
156
157
158/**
159 * Gets the RC pointer for the specified queue.
160 *
161 * @returns The RC address of the queue.
162 * @returns NULL if pQueue is invalid.
163 * @param pQueue The queue handle.
164 */
165VMMDECL(RCPTRTYPE(PPDMQUEUE)) PDMQueueRCPtr(PPDMQUEUE pQueue)
166{
167 Assert(VALID_PTR(pQueue));
168 Assert(pQueue->pVMR3 && pQueue->pVMRC);
169#ifdef IN_RC
170 return pQueue;
171#else
172 return MMHyperCCToRC(pQueue->CTX_SUFF(pVM), pQueue);
173#endif
174}
175
176
177/**
178 * Gets the ring-0 pointer for the specified queue.
179 *
180 * @returns The ring-0 address of the queue.
181 * @returns NULL if pQueue is invalid.
182 * @param pQueue The queue handle.
183 */
184VMMDECL(R0PTRTYPE(PPDMQUEUE)) PDMQueueR0Ptr(PPDMQUEUE pQueue)
185{
186 Assert(VALID_PTR(pQueue));
187 Assert(pQueue->pVMR3 && pQueue->pVMR0);
188#ifdef IN_RING0
189 return pQueue;
190#else
191 return MMHyperCCToR0(pQueue->CTX_SUFF(pVM), pQueue);
192#endif
193}
194
195
196/**
197 * Schedule the queue for flushing (processing) if necessary.
198 *
199 * @returns @c true if necessary, @c false if not.
200 * @param pQueue The queue.
201 */
202VMMDECL(bool) PDMQueueFlushIfNecessary(PPDMQUEUE pQueue)
203{
204 AssertPtr(pQueue);
205 if ( pQueue->pPendingR3 != NIL_RTR3PTR
206 || pQueue->pPendingR0 != NIL_RTR0PTR
207 || pQueue->pPendingRC != NIL_RTRCPTR)
208 {
209 pdmQueueSetFF(pQueue);
210 return false;
211 }
212 return false;
213}
214
Note: See TracBrowser for help on using the repository browser.

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