VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMAll/PDMAllCritSect.cpp@ 13791

Last change on this file since 13791 was 13791, checked in by vboxsync, 16 years ago

Moving data around

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 7.7 KB
Line 
1/* $Id: PDMAllCritSect.cpp 13791 2008-11-04 16:12:57Z vboxsync $ */
2/** @file
3 * PDM - Critical Sections, All Contexts.
4 */
5
6/*
7 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22
23/*******************************************************************************
24* Header Files *
25*******************************************************************************/
26#define LOG_GROUP LOG_GROUP_PDM//_CRITSECT
27#include "PDMInternal.h"
28#include <VBox/pdm.h>
29#include <VBox/mm.h>
30#include <VBox/vm.h>
31#include <VBox/err.h>
32#include <VBox/hwaccm.h>
33
34#include <VBox/log.h>
35#include <iprt/asm.h>
36#include <iprt/assert.h>
37#ifdef IN_RING3
38# include <iprt/semaphore.h>
39#endif
40
41
42/**
43 * Enters a PDM critical section.
44 *
45 * @returns VINF_SUCCESS if entered successfully.
46 * @returns rcBusy when encountering a busy critical section in GC/R0.
47 * @returns VERR_SEM_DESTROYED if the critical section is dead.
48 *
49 * @param pCritSect The PDM critical section to enter.
50 * @param rcBusy The status code to return when we're in GC or R0
51 * and the section is busy.
52 */
53VMMDECL(int) PDMCritSectEnter(PPDMCRITSECT pCritSect, int rcBusy)
54{
55 Assert(pCritSect->s.Core.cNestings < 8); /* useful to catch incorrect locking */
56#ifdef IN_RING3
57 NOREF(rcBusy);
58
59 STAM_STATS({ if (pCritSect->s.Core.cLockers >= 0 && !RTCritSectIsOwner(&pCritSect->s.Core)) STAM_COUNTER_INC(&pCritSect->s.StatContentionR3); });
60 int rc = RTCritSectEnter(&pCritSect->s.Core);
61 STAM_STATS({ if (pCritSect->s.Core.cNestings == 1) STAM_PROFILE_ADV_START(&pCritSect->s.StatLocked, l); });
62 return rc;
63
64#else /* !IN_RING3 */
65 AssertMsgReturn(pCritSect->s.Core.u32Magic == RTCRITSECT_MAGIC, ("%RX32\n", pCritSect->s.Core.u32Magic),
66 VERR_SEM_DESTROYED);
67 PVM pVM = pCritSect->s.CTX_SUFF(pVM);
68 Assert(pVM);
69
70 RTCPUID idCPU = VM_GET_VMCPUID(pVM);
71
72 /*
73 * Try to take the lock.
74 */
75 if (ASMAtomicCmpXchgS32(&pCritSect->s.Core.cLockers, 0, -1))
76 {
77 pCritSect->s.Core.cNestings = 1;
78 Assert(pVM->aCpu[idCPU].hNativeThread);
79 ASMAtomicXchgSize(&pCritSect->s.Core.NativeThreadOwner, pVM->aCpu[idCPU].hNativeThread);
80 STAM_PROFILE_ADV_START(&pCritSect->s.StatLocked, l);
81 return VINF_SUCCESS;
82 }
83
84 /*
85 * Nested?
86 */
87 if (pCritSect->s.Core.NativeThreadOwner == pVM->aCpu[idCPU].hNativeThread)
88 {
89 pCritSect->s.Core.cNestings++;
90 ASMAtomicIncS32(&pCritSect->s.Core.cLockers);
91 return VINF_SUCCESS;
92 }
93
94 /*
95 * Failed.
96 */
97 LogFlow(("PDMCritSectEnter: locked => R3 (%Vrc)\n", rcBusy));
98 STAM_COUNTER_INC(&pCritSect->s.StatContentionRZLock);
99 return rcBusy;
100#endif /* !IN_RING3 */
101}
102
103
104#ifdef IN_RING3
105/**
106 * Enters a PDM critical section.
107 *
108 * @returns VINF_SUCCESS if entered successfully.
109 * @returns rcBusy when encountering a busy critical section in GC/R0.
110 * @returns VERR_SEM_DESTROYED if the critical section is dead.
111 *
112 * @param pCritSect The PDM critical section to enter.
113 * @param fCallHost Whether this is a VMMGCCallHost() or VMMR0CallHost() request.
114 */
115VMMR3DECL(int) PDMR3CritSectEnterEx(PPDMCRITSECT pCritSect, bool fCallHost)
116{
117 int rc = PDMCritSectEnter(pCritSect, VERR_INTERNAL_ERROR);
118 if ( rc == VINF_SUCCESS
119 && fCallHost
120 && pCritSect->s.Core.Strict.ThreadOwner != NIL_RTTHREAD)
121 {
122 RTThreadWriteLockDec(pCritSect->s.Core.Strict.ThreadOwner);
123 ASMAtomicUoWriteSize(&pCritSect->s.Core.Strict.ThreadOwner, NIL_RTTHREAD);
124 }
125 return rc;
126}
127#endif /* IN_RING3 */
128
129
130/**
131 * Leaves a critical section entered with PDMCritSectEnter().
132 *
133 * @param pCritSect The PDM critical section to leave.
134 */
135VMMDECL(void) PDMCritSectLeave(PPDMCRITSECT pCritSect)
136{
137#ifdef IN_RING3
138# ifdef VBOX_WITH_STATISTICS
139 if (pCritSect->s.Core.cNestings == 1)
140 STAM_PROFILE_ADV_STOP(&pCritSect->s.StatLocked, l);
141# endif
142 RTSEMEVENT EventToSignal = pCritSect->s.EventToSignal;
143 if (RT_LIKELY(EventToSignal == NIL_RTSEMEVENT))
144 {
145 int rc = RTCritSectLeave(&pCritSect->s.Core);
146 AssertRC(rc);
147 }
148 else
149 {
150 pCritSect->s.EventToSignal = NIL_RTSEMEVENT;
151 int rc = RTCritSectLeave(&pCritSect->s.Core);
152 AssertRC(rc);
153 LogBird(("signalling %#x\n", EventToSignal));
154 rc = RTSemEventSignal(EventToSignal);
155 AssertRC(rc);
156 }
157
158#else /* !IN_RING3 */
159 Assert(VALID_PTR(pCritSect));
160 Assert(pCritSect->s.Core.u32Magic == RTCRITSECT_MAGIC);
161 Assert(pCritSect->s.Core.cNestings > 0);
162 Assert(pCritSect->s.Core.cLockers >= 0);
163 PVM pVM = pCritSect->s.CTX_SUFF(pVM);
164 Assert(pVM);
165 AssertMsg(pCritSect->s.Core.NativeThreadOwner == pVM->aCpu[VM_GET_VMCPUID(pVM)].hNativeThread, ("Owner %RX64 emt=%RX64\n", pCritSect->s.Core.NativeThreadOwner, pVM->aCpu[VM_GET_VMCPUID(pVM)].hNativeThread));
166
167 /*
168 * Deal with nested attempts first.
169 * (We're exploiting nesting to avoid queuing multiple R3 leaves for the same section.)
170 */
171 pCritSect->s.Core.cNestings--;
172 if (pCritSect->s.Core.cNestings > 0)
173 {
174 ASMAtomicDecS32(&pCritSect->s.Core.cLockers);
175 return;
176 }
177
178 /*
179 * Try leave it.
180 */
181 if (pCritSect->s.Core.cLockers == 0)
182 {
183 STAM_PROFILE_ADV_STOP(&pCritSect->s.StatLocked, l);
184 ASMAtomicXchgSize(&pCritSect->s.Core.NativeThreadOwner, NIL_RTNATIVETHREAD);
185 if (ASMAtomicCmpXchgS32(&pCritSect->s.Core.cLockers, -1, 0))
186 return;
187
188 /* darn, someone raced in on us. */
189 Assert(pVM->aCpu[VM_GET_VMCPUID(pVM)].hNativeThread);
190 ASMAtomicXchgSize(&pCritSect->s.Core.NativeThreadOwner, pVM->aCpu[VM_GET_VMCPUID(pVM)].hNativeThread);
191 STAM_PROFILE_ADV_START(&pCritSect->s.StatLocked, l);
192 }
193 pCritSect->s.Core.cNestings = 1;
194
195 /*
196 * Queue the request.
197 */
198 RTUINT i = pVM->pdm.s.cQueuedCritSectLeaves++;
199 LogFlow(("PDMCritSectLeave: [%d]=%p => R3\n", i, pCritSect));
200 AssertFatal(i < RT_ELEMENTS(pVM->pdm.s.apQueuedCritSectsLeaves));
201 pVM->pdm.s.apQueuedCritSectsLeaves[i] = MMHyperCCToR3(pVM, pCritSect);
202 VM_FF_SET(pVM, VM_FF_PDM_CRITSECT);
203 VM_FF_SET(pVM, VM_FF_TO_R3);
204 STAM_COUNTER_INC(&pVM->pdm.s.StatQueuedCritSectLeaves);
205 STAM_COUNTER_INC(&pCritSect->s.StatContentionRZUnlock);
206#endif /* !IN_RING3 */
207}
208
209
210/**
211 * Checks the caller is the owner of the critical section.
212 *
213 * @returns true if owner.
214 * @returns false if not owner.
215 * @param pCritSect The critical section.
216 */
217VMMDECL(bool) PDMCritSectIsOwner(PCPDMCRITSECT pCritSect)
218{
219#ifdef IN_RING3
220 return RTCritSectIsOwner(&pCritSect->s.Core);
221#else
222 PVM pVM = pCritSect->s.CTX_SUFF(pVM);
223 Assert(pVM);
224 return pCritSect->s.Core.NativeThreadOwner == pVM->aCpu[VM_GET_VMCPUID(pVM)].hNativeThread;
225#endif
226}
227
228
229/**
230 * Checks if a critical section is initialized or not.
231 *
232 * @returns true if initialized.
233 * @returns false if not initialized.
234 * @param pCritSect The critical section.
235 */
236VMMDECL(bool) PDMCritSectIsInitialized(PCPDMCRITSECT pCritSect)
237{
238 return pCritSect->s.Core.u32Magic == RTCRITSECT_MAGIC;
239}
240
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