VirtualBox

source: vbox/trunk/src/VBox/Runtime/r0drv/netbsd/semeventmulti-r0drv-netbsd.c@ 63376

最後變更 在這個檔案從63376是 63346,由 vboxsync 提交於 9 年 前

r0drv/netbsd: add/remove blank lines to reduce diff to FreeBSD.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 10.9 KB
 
1/* $Id: semeventmulti-r0drv-netbsd.c 63346 2016-08-11 18:51:48Z vboxsync $ */
2/** @file
3 * IPRT - Multiple Release Event Semaphores, Ring-0 Driver, NetBSD.
4 */
5
6/*
7 * Copyright (c) 2007 knut st. osmundsen <[email protected]>
8 *
9 * Permission is hereby granted, free of charge, to any person
10 * obtaining a copy of this software and associated documentation
11 * files (the "Software"), to deal in the Software without
12 * restriction, including without limitation the rights to use,
13 * copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following
16 * conditions:
17 *
18 * The above copyright notice and this permission notice shall be
19 * included in all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 * OTHER DEALINGS IN THE SOFTWARE.
29 */
30
31
32/*********************************************************************************************************************************
33* Header Files *
34*********************************************************************************************************************************/
35#define RTSEMEVENTMULTI_WITHOUT_REMAPPING
36#include "the-netbsd-kernel.h"
37#include "internal/iprt.h"
38#include <iprt/semaphore.h>
39
40#include <iprt/assert.h>
41#include <iprt/asm.h>
42#include <iprt/err.h>
43#include <iprt/mem.h>
44#include <iprt/lockvalidator.h>
45
46#include "sleepqueue-r0drv-netbsd.h"
47#include "internal/magics.h"
48
49
50/*********************************************************************************************************************************
51* Defined Constants And Macros *
52*********************************************************************************************************************************/
53/** @name fStateAndGen values
54 * @{ */
55/** The state bit number. */
56#define RTSEMEVENTMULTIBSD_STATE_BIT 0
57/** The state mask. */
58#define RTSEMEVENTMULTIBSD_STATE_MASK RT_BIT_32(RTSEMEVENTMULTIBSD_STATE_BIT)
59/** The generation mask. */
60#define RTSEMEVENTMULTIBSD_GEN_MASK ~RTSEMEVENTMULTIBSD_STATE_MASK
61/** The generation shift. */
62#define RTSEMEVENTMULTIBSD_GEN_SHIFT 1
63/** The initial variable value. */
64#define RTSEMEVENTMULTIBSD_STATE_GEN_INIT UINT32_C(0xfffffffc)
65/** @} */
66
67/*********************************************************************************************************************************
68* Structures and Typedefs *
69*********************************************************************************************************************************/
70/**
71 * NetBSD multiple release event semaphore.
72 */
73typedef struct RTSEMEVENTMULTIINTERNAL
74{
75 /** Magic value (RTSEMEVENTMULTI_MAGIC). */
76 uint32_t volatile u32Magic;
77 /** The object state bit and generation counter.
78 * The generation counter is incremented every time the object is
79 * signalled. */
80 uint32_t volatile fStateAndGen;
81 /** Reference counter. */
82 uint32_t volatile cRefs;
83} RTSEMEVENTMULTIINTERNAL, *PRTSEMEVENTMULTIINTERNAL;
84
85
86RTDECL(int) RTSemEventMultiCreate(PRTSEMEVENTMULTI phEventMultiSem)
87{
88 return RTSemEventMultiCreateEx(phEventMultiSem, 0 /*fFlags*/, NIL_RTLOCKVALCLASS, NULL);
89}
90
91
92RTDECL(int) RTSemEventMultiCreateEx(PRTSEMEVENTMULTI phEventMultiSem, uint32_t fFlags, RTLOCKVALCLASS hClass,
93 const char *pszNameFmt, ...)
94{
95 PRTSEMEVENTMULTIINTERNAL pThis;
96
97 AssertReturn(!(fFlags & ~RTSEMEVENTMULTI_FLAGS_NO_LOCK_VAL), VERR_INVALID_PARAMETER);
98 pThis = (PRTSEMEVENTMULTIINTERNAL)RTMemAlloc(sizeof(*pThis));
99 if (pThis)
100 {
101 pThis->u32Magic = RTSEMEVENTMULTI_MAGIC;
102 pThis->fStateAndGen = RTSEMEVENTMULTIBSD_STATE_GEN_INIT;
103 pThis->cRefs = 1;
104
105 *phEventMultiSem = pThis;
106 return VINF_SUCCESS;
107 }
108 return VERR_NO_MEMORY;
109}
110
111
112/**
113 * Retain a reference to the semaphore.
114 *
115 * @param pThis The semaphore.
116 */
117DECLINLINE(void) rtR0SemEventMultiBsdRetain(PRTSEMEVENTMULTIINTERNAL pThis)
118{
119 uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
120 Assert(cRefs && cRefs < 100000);
121}
122
123
124/**
125 * Release a reference, destroy the thing if necessary.
126 *
127 * @param pThis The semaphore.
128 */
129DECLINLINE(void) rtR0SemEventMultiBsdRelease(PRTSEMEVENTMULTIINTERNAL pThis)
130{
131 if (RT_UNLIKELY(ASMAtomicDecU32(&pThis->cRefs) == 0))
132 {
133 Assert(pThis->u32Magic != RTSEMEVENTMULTI_MAGIC);
134 RTMemFree(pThis);
135 }
136}
137
138
139RTDECL(int) RTSemEventMultiDestroy(RTSEMEVENTMULTI hEventMultiSem)
140{
141 /*
142 * Validate input.
143 */
144 PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem;
145 if (pThis == NIL_RTSEMEVENTMULTI)
146 return VINF_SUCCESS;
147 AssertPtrReturn(pThis, VERR_INVALID_PARAMETER);
148 AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER);
149 Assert(pThis->cRefs > 0);
150
151 /*
152 * Invalidate it and signal the object just in case.
153 */
154 ASMAtomicWriteU32(&pThis->u32Magic, ~RTSEMEVENTMULTI_MAGIC);
155 ASMAtomicAndU32(&pThis->fStateAndGen, RTSEMEVENTMULTIBSD_GEN_MASK);
156 rtR0SemBsdBroadcast(pThis);
157 rtR0SemEventMultiBsdRelease(pThis);
158 return VINF_SUCCESS;
159}
160
161
162RTDECL(int) RTSemEventMultiSignal(RTSEMEVENTMULTI hEventMultiSem)
163{
164 uint32_t fNew;
165 uint32_t fOld;
166
167 /*
168 * Validate input.
169 */
170 PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem;
171 if (!pThis)
172 return VERR_INVALID_PARAMETER;
173 AssertPtrReturn(pThis, VERR_INVALID_PARAMETER);
174 AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER);
175 rtR0SemEventMultiBsdRetain(pThis);
176
177 /*
178 * Signal the event object. The cause of the parnoia here is racing to try
179 * deal with racing RTSemEventMultiSignal calls (should probably be
180 * forbidden, but it's relatively easy to handle).
181 */
182 do
183 {
184 fNew = fOld = ASMAtomicUoReadU32(&pThis->fStateAndGen);
185 fNew += 1 << RTSEMEVENTMULTIBSD_GEN_SHIFT;
186 fNew |= RTSEMEVENTMULTIBSD_STATE_MASK;
187 }
188 while (!ASMAtomicCmpXchgU32(&pThis->fStateAndGen, fNew, fOld));
189
190 rtR0SemBsdBroadcast(pThis);
191 rtR0SemEventMultiBsdRelease(pThis);
192 return VINF_SUCCESS;
193}
194
195
196RTDECL(int) RTSemEventMultiReset(RTSEMEVENTMULTI hEventMultiSem)
197{
198 /*
199 * Validate input.
200 */
201 PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem;
202 if (!pThis)
203 return VERR_INVALID_PARAMETER;
204 AssertPtrReturn(pThis, VERR_INVALID_PARAMETER);
205 AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER);
206 rtR0SemEventMultiBsdRetain(pThis);
207
208 /*
209 * Reset it.
210 */
211 ASMAtomicAndU32(&pThis->fStateAndGen, ~RTSEMEVENTMULTIBSD_STATE_MASK);
212
213 rtR0SemEventMultiBsdRelease(pThis);
214 return VINF_SUCCESS;
215}
216
217
218/**
219 * Worker for RTSemEventMultiWaitEx and RTSemEventMultiWaitExDebug.
220 *
221 * @returns VBox status code.
222 * @param pThis The event semaphore.
223 * @param fFlags See RTSemEventMultiWaitEx.
224 * @param uTimeout See RTSemEventMultiWaitEx.
225 * @param pSrcPos The source code position of the wait.
226 */
227static int rtR0SemEventMultiBsdWait(PRTSEMEVENTMULTIINTERNAL pThis, uint32_t fFlags, uint64_t uTimeout,
228 PCRTLOCKVALSRCPOS pSrcPos)
229{
230 uint32_t fOrgStateAndGen;
231 int rc;
232
233 /*
234 * Validate the input.
235 */
236 AssertPtrReturn(pThis, VERR_INVALID_PARAMETER);
237 AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER);
238 AssertReturn(RTSEMWAIT_FLAGS_ARE_VALID(fFlags), VERR_INVALID_PARAMETER);
239 rtR0SemEventMultiBsdRetain(pThis);
240
241 /*
242 * Is the event already signalled or do we have to wait?
243 */
244 fOrgStateAndGen = ASMAtomicUoReadU32(&pThis->fStateAndGen);
245 if (fOrgStateAndGen & RTSEMEVENTMULTIBSD_STATE_MASK)
246 rc = VINF_SUCCESS;
247 else
248 {
249 /*
250 * We have to wait.
251 */
252 RTR0SEMBSDSLEEP Wait;
253 rc = rtR0SemBsdWaitInit(&Wait, fFlags, uTimeout, pThis);
254 if (RT_SUCCESS(rc))
255 {
256 for (;;)
257 {
258 /* The destruction test. */
259 if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENTMULTI_MAGIC))
260 rc = VERR_SEM_DESTROYED;
261 else
262 {
263 rtR0SemBsdWaitPrepare(&Wait);
264
265 /* Check the exit conditions. */
266 if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENTMULTI_MAGIC))
267 rc = VERR_SEM_DESTROYED;
268 else if (ASMAtomicUoReadU32(&pThis->fStateAndGen) != fOrgStateAndGen)
269 rc = VINF_SUCCESS;
270 else if (rtR0SemBsdWaitHasTimedOut(&Wait))
271 rc = VERR_TIMEOUT;
272 else if (rtR0SemBsdWaitWasInterrupted(&Wait))
273 rc = VERR_INTERRUPTED;
274 else
275 {
276 /* Do the wait and then recheck the conditions. */
277 rtR0SemBsdWaitDoIt(&Wait);
278 continue;
279 }
280 }
281 break;
282 }
283
284 rtR0SemBsdWaitDelete(&Wait);
285 }
286 }
287
288 rtR0SemEventMultiBsdRelease(pThis);
289 return rc;
290}
291
292
293RTDECL(int) RTSemEventMultiWaitEx(RTSEMEVENTMULTI hEventMultiSem, uint32_t fFlags, uint64_t uTimeout)
294{
295#ifndef RTSEMEVENT_STRICT
296 return rtR0SemEventMultiBsdWait(hEventMultiSem, fFlags, uTimeout, NULL);
297#else
298 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
299 return rtR0SemEventMultiBsdWait(hEventMultiSem, fFlags, uTimeout, &SrcPos);
300#endif
301}
302RT_EXPORT_SYMBOL(RTSemEventMultiWaitEx);
303
304
305RTDECL(int) RTSemEventMultiWaitExDebug(RTSEMEVENTMULTI hEventMultiSem, uint32_t fFlags, uint64_t uTimeout,
306 RTHCUINTPTR uId, RT_SRC_POS_DECL)
307{
308 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
309 return rtR0SemEventMultiBsdWait(hEventMultiSem, fFlags, uTimeout, &SrcPos);
310}
311RT_EXPORT_SYMBOL(RTSemEventMultiWaitExDebug);
312
313
314RTDECL(uint32_t) RTSemEventMultiGetResolution(void)
315{
316 return rtR0SemBsdWaitGetResolution();
317}
318RT_EXPORT_SYMBOL(RTSemEventMultiGetResolution);
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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