VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/Support/SUPDrvSem.c@ 40282

Last change on this file since 40282 was 33167, checked in by vboxsync, 14 years ago

SUPDrv,SUPLib: Expose the high resolution event semaphore APIs.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.6 KB
Line 
1/* $Revision: 33167 $ */
2/** @file
3 * VBoxDrv - The VirtualBox Support Driver - Common OS agnostic.
4 */
5
6/*
7 * Copyright (C) 2006-2009 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 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27/*******************************************************************************
28* Header Files *
29*******************************************************************************/
30#define LOG_GROUP LOG_GROUP_SUP_DRV
31#define SUPDRV_AGNOSTIC
32#include "SUPDrvInternal.h"
33
34/** @todo trim this down. */
35#include <iprt/param.h>
36#include <iprt/alloc.h>
37#include <iprt/cpuset.h>
38#include <iprt/handletable.h>
39#include <iprt/mp.h>
40#include <iprt/power.h>
41#include <iprt/process.h>
42#include <iprt/semaphore.h>
43#include <iprt/spinlock.h>
44#include <iprt/thread.h>
45#include <iprt/uuid.h>
46
47#include <VBox/param.h>
48#include <VBox/log.h>
49#include <VBox/err.h>
50
51
52/**
53 * Destructor for objects created by SUPSemEventCreate.
54 *
55 * @param pvObj The object handle.
56 * @param pvUser1 The IPRT event handle.
57 * @param pvUser2 NULL.
58 */
59static DECLCALLBACK(void) supR0SemEventDestructor(void *pvObj, void *pvUser1, void *pvUser2)
60{
61 Assert(pvUser2 == NULL);
62 NOREF(pvObj);
63 RTSemEventDestroy((RTSEMEVENT)pvUser1);
64}
65
66
67SUPDECL(int) SUPSemEventCreate(PSUPDRVSESSION pSession, PSUPSEMEVENT phEvent)
68{
69 int rc;
70 RTSEMEVENT hEventReal;
71
72 /*
73 * Input validation.
74 */
75 AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
76 AssertPtrReturn(phEvent, VERR_INVALID_POINTER);
77
78 /*
79 * Create the event semaphore object.
80 */
81 rc = RTSemEventCreate(&hEventReal);
82 if (RT_SUCCESS(rc))
83 {
84 void *pvObj = SUPR0ObjRegister(pSession, SUPDRVOBJTYPE_SEM_EVENT, supR0SemEventDestructor, hEventReal, NULL);
85 if (pvObj)
86 {
87 uint32_t h32;
88 rc = RTHandleTableAllocWithCtx(pSession->hHandleTable, pvObj, SUPDRV_HANDLE_CTX_EVENT, &h32);
89 if (RT_SUCCESS(rc))
90 {
91 *phEvent = (SUPSEMEVENT)(uintptr_t)h32;
92 return VINF_SUCCESS;
93 }
94 SUPR0ObjRelease(pvObj, pSession);
95 }
96 else
97 RTSemEventDestroy(hEventReal);
98 }
99 return rc;
100}
101
102
103SUPDECL(int) SUPSemEventClose(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent)
104{
105 uint32_t h32;
106 PSUPDRVOBJ pObj;
107
108 /*
109 * Input validation.
110 */
111 AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
112 if (hEvent == NIL_SUPSEMEVENT)
113 return VINF_SUCCESS;
114 h32 = (uint32_t)(uintptr_t)hEvent;
115 if (h32 != (uintptr_t)hEvent)
116 return VERR_INVALID_HANDLE;
117
118 /*
119 * Do the job.
120 */
121 pObj = (PSUPDRVOBJ)RTHandleTableFreeWithCtx(pSession->hHandleTable, h32, SUPDRV_HANDLE_CTX_EVENT);
122 if (!pObj)
123 return VERR_INVALID_HANDLE;
124
125 Assert(pObj->cUsage >= 2);
126 SUPR0ObjRelease(pObj, pSession); /* The free call above. */
127 return SUPR0ObjRelease(pObj, pSession); /* The handle table reference. */
128}
129
130
131SUPDECL(int) SUPSemEventSignal(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent)
132{
133 int rc;
134 uint32_t h32;
135 PSUPDRVOBJ pObj;
136
137 /*
138 * Input validation.
139 */
140 AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
141 h32 = (uint32_t)(uintptr_t)hEvent;
142 if (h32 != (uintptr_t)hEvent)
143 return VERR_INVALID_HANDLE;
144 pObj = (PSUPDRVOBJ)RTHandleTableLookupWithCtx(pSession->hHandleTable, h32, SUPDRV_HANDLE_CTX_EVENT);
145 if (!pObj)
146 return VERR_INVALID_HANDLE;
147
148 /*
149 * Do the job.
150 */
151 rc = RTSemEventSignal((RTSEMEVENT)pObj->pvUser1);
152
153 SUPR0ObjRelease(pObj, pSession);
154 return rc;
155}
156
157
158static int supR0SemEventWaitEx(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent, uint32_t fFlags, uint64_t uTimeout)
159{
160 int rc;
161 uint32_t h32;
162 PSUPDRVOBJ pObj;
163
164 /*
165 * Input validation.
166 */
167 AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
168 h32 = (uint32_t)(uintptr_t)hEvent;
169 if (h32 != (uintptr_t)hEvent)
170 return VERR_INVALID_HANDLE;
171 pObj = (PSUPDRVOBJ)RTHandleTableLookupWithCtx(pSession->hHandleTable, h32, SUPDRV_HANDLE_CTX_EVENT);
172 if (!pObj)
173 return VERR_INVALID_HANDLE;
174
175 /*
176 * Do the job.
177 */
178 rc = RTSemEventWaitEx((RTSEMEVENT)pObj->pvUser1, fFlags, uTimeout);
179
180 SUPR0ObjRelease(pObj, pSession);
181 return rc;
182}
183
184
185SUPDECL(int) SUPSemEventWait(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent, uint32_t cMillies)
186{
187 uint32_t fFlags = RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_MILLISECS | RTSEMWAIT_FLAGS_UNINTERRUPTIBLE;
188 if (cMillies == RT_INDEFINITE_WAIT)
189 fFlags |= RTSEMWAIT_FLAGS_INDEFINITE;
190 return supR0SemEventWaitEx(pSession, hEvent, fFlags, cMillies);
191}
192
193
194SUPDECL(int) SUPSemEventWaitNoResume(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent, uint32_t cMillies)
195{
196 uint32_t fFlags = RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_MILLISECS | RTSEMWAIT_FLAGS_INTERRUPTIBLE;
197 if (cMillies == RT_INDEFINITE_WAIT)
198 fFlags |= RTSEMWAIT_FLAGS_INDEFINITE;
199 return supR0SemEventWaitEx(pSession, hEvent, fFlags, cMillies);
200}
201
202
203SUPDECL(int) SUPSemEventWaitNsAbsIntr(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent, uint64_t uNsTimeout)
204{
205 uint32_t fFlags = RTSEMWAIT_FLAGS_ABSOLUTE | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_INTERRUPTIBLE;
206 return supR0SemEventWaitEx(pSession, hEvent, fFlags, uNsTimeout);
207}
208
209
210SUPDECL(int) SUPSemEventWaitNsRelIntr(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent, uint64_t cNsTimeout)
211{
212 uint32_t fFlags = RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_INTERRUPTIBLE;
213 return supR0SemEventWaitEx(pSession, hEvent, fFlags, cNsTimeout);
214}
215
216
217SUPDECL(uint32_t) SUPSemEventGetResolution(PSUPDRVSESSION pSession)
218{
219 Assert(SUP_IS_SESSION_VALID(pSession));
220 return RTSemEventGetResolution();
221}
222
223
224/**
225 * Destructor for objects created by SUPSemEventMultiCreate.
226 *
227 * @param pvObj The object handle.
228 * @param pvUser1 The IPRT event handle.
229 * @param pvUser2 NULL.
230 */
231static DECLCALLBACK(void) supR0SemEventMultiDestructor(void *pvObj, void *pvUser1, void *pvUser2)
232{
233 Assert(pvUser2 == NULL);
234 NOREF(pvObj);
235 RTSemEventMultiDestroy((RTSEMEVENTMULTI)pvUser1);
236}
237
238
239SUPDECL(int) SUPSemEventMultiCreate(PSUPDRVSESSION pSession, PSUPSEMEVENTMULTI phEventMulti)
240{
241 int rc;
242 RTSEMEVENTMULTI hEventMultReal;
243
244 /*
245 * Input validation.
246 */
247 AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
248 AssertPtrReturn(phEventMulti, VERR_INVALID_POINTER);
249
250 /*
251 * Create the event semaphore object.
252 */
253 rc = RTSemEventMultiCreate(&hEventMultReal);
254 if (RT_SUCCESS(rc))
255 {
256 void *pvObj = SUPR0ObjRegister(pSession, SUPDRVOBJTYPE_SEM_EVENT_MULTI, supR0SemEventMultiDestructor, hEventMultReal, NULL);
257 if (pvObj)
258 {
259 uint32_t h32;
260 rc = RTHandleTableAllocWithCtx(pSession->hHandleTable, pvObj, SUPDRV_HANDLE_CTX_EVENT_MULTI, &h32);
261 if (RT_SUCCESS(rc))
262 {
263 *phEventMulti = (SUPSEMEVENTMULTI)(uintptr_t)h32;
264 return VINF_SUCCESS;
265 }
266 SUPR0ObjRelease(pvObj, pSession);
267 }
268 else
269 RTSemEventMultiDestroy(hEventMultReal);
270 }
271 return rc;
272}
273
274
275SUPDECL(int) SUPSemEventMultiClose(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti)
276{
277 uint32_t h32;
278 PSUPDRVOBJ pObj;
279
280 /*
281 * Input validation.
282 */
283 AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
284 if (hEventMulti == NIL_SUPSEMEVENTMULTI)
285 return VINF_SUCCESS;
286 h32 = (uint32_t)(uintptr_t)hEventMulti;
287 if (h32 != (uintptr_t)hEventMulti)
288 return VERR_INVALID_HANDLE;
289
290 /*
291 * Do the job.
292 */
293 pObj = (PSUPDRVOBJ)RTHandleTableFreeWithCtx(pSession->hHandleTable, h32, SUPDRV_HANDLE_CTX_EVENT_MULTI);
294 if (!pObj)
295 return VERR_INVALID_HANDLE;
296
297 Assert(pObj->cUsage >= 2);
298 SUPR0ObjRelease(pObj, pSession); /* The free call above. */
299 return SUPR0ObjRelease(pObj, pSession); /* The handle table reference. */
300}
301
302
303SUPDECL(int) SUPSemEventMultiSignal(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti)
304{
305 int rc;
306 uint32_t h32;
307 PSUPDRVOBJ pObj;
308
309 /*
310 * Input validation.
311 */
312 AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
313 h32 = (uint32_t)(uintptr_t)hEventMulti;
314 if (h32 != (uintptr_t)hEventMulti)
315 return VERR_INVALID_HANDLE;
316 pObj = (PSUPDRVOBJ)RTHandleTableLookupWithCtx(pSession->hHandleTable, h32, SUPDRV_HANDLE_CTX_EVENT_MULTI);
317 if (!pObj)
318 return VERR_INVALID_HANDLE;
319
320 /*
321 * Do the job.
322 */
323 rc = RTSemEventMultiSignal((RTSEMEVENTMULTI)pObj->pvUser1);
324
325 SUPR0ObjRelease(pObj, pSession);
326 return rc;
327}
328
329
330SUPDECL(int) SUPSemEventMultiReset(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti)
331{
332 int rc;
333 uint32_t h32;
334 PSUPDRVOBJ pObj;
335
336 /*
337 * Input validation.
338 */
339 AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
340 h32 = (uint32_t)(uintptr_t)hEventMulti;
341 if (h32 != (uintptr_t)hEventMulti)
342 return VERR_INVALID_HANDLE;
343 pObj = (PSUPDRVOBJ)RTHandleTableLookupWithCtx(pSession->hHandleTable, h32, SUPDRV_HANDLE_CTX_EVENT_MULTI);
344 if (!pObj)
345 return VERR_INVALID_HANDLE;
346
347 /*
348 * Do the job.
349 */
350 rc = RTSemEventMultiReset((RTSEMEVENTMULTI)pObj->pvUser1);
351
352 SUPR0ObjRelease(pObj, pSession);
353 return rc;
354}
355
356
357static int supR0SemEventMultiWaitEx(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint32_t fFlags, uint64_t uTimeout)
358{
359 int rc;
360 uint32_t h32;
361 PSUPDRVOBJ pObj;
362
363 /*
364 * Input validation.
365 */
366 AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
367 h32 = (uint32_t)(uintptr_t)hEventMulti;
368 if (h32 != (uintptr_t)hEventMulti)
369 return VERR_INVALID_HANDLE;
370 pObj = (PSUPDRVOBJ)RTHandleTableLookupWithCtx(pSession->hHandleTable, h32, SUPDRV_HANDLE_CTX_EVENT_MULTI);
371 if (!pObj)
372 return VERR_INVALID_HANDLE;
373
374 /*
375 * Do the job.
376 */
377 rc = RTSemEventMultiWaitEx((RTSEMEVENTMULTI)pObj->pvUser1, fFlags, uTimeout);
378
379 SUPR0ObjRelease(pObj, pSession);
380 return rc;
381}
382
383SUPDECL(int) SUPSemEventMultiWait(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint32_t cMillies)
384{
385 uint32_t fFlags = RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_MILLISECS | RTSEMWAIT_FLAGS_UNINTERRUPTIBLE;
386 if (cMillies == RT_INDEFINITE_WAIT)
387 fFlags |= RTSEMWAIT_FLAGS_INDEFINITE;
388 return supR0SemEventMultiWaitEx(pSession, hEventMulti, fFlags, cMillies);
389}
390
391
392
393SUPDECL(int) SUPSemEventMultiWaitNoResume(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint32_t cMillies)
394{
395 uint32_t fFlags = RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_MILLISECS | RTSEMWAIT_FLAGS_INTERRUPTIBLE;
396 if (cMillies == RT_INDEFINITE_WAIT)
397 fFlags |= RTSEMWAIT_FLAGS_INDEFINITE;
398 return supR0SemEventMultiWaitEx(pSession, hEventMulti, fFlags, cMillies);
399}
400
401
402SUPDECL(int) SUPSemEventMultiWaitNsAbsIntr(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint64_t uNsTimeout)
403{
404 uint32_t fFlags = RTSEMWAIT_FLAGS_ABSOLUTE | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_INTERRUPTIBLE;
405 return supR0SemEventMultiWaitEx(pSession, hEventMulti, fFlags, uNsTimeout);
406}
407
408
409SUPDECL(int) SUPSemEventMultiWaitNsRelIntr(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint64_t cNsTimeout)
410{
411 uint32_t fFlags = RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_INTERRUPTIBLE;
412 return supR0SemEventMultiWaitEx(pSession, hEventMulti, fFlags, cNsTimeout);
413}
414
415
416SUPDECL(uint32_t) SUPSemEventMultiGetResolution(PSUPDRVSESSION pSession)
417{
418 Assert(SUP_IS_SESSION_VALID(pSession));
419 return RTSemEventMultiGetResolution();
420}
421
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