VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/Support/SUPDrvSem.cpp@ 62564

Last change on this file since 62564 was 62490, checked in by vboxsync, 8 years ago

(C) 2016

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