VirtualBox

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

Last change on this file since 81071 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 Author Date Id Revision
File size: 12.8 KB
Line 
1/* $Id: SUPDrvSem.cpp 76553 2019-01-01 01:45:53Z vboxsync $ */
2/** @file
3 * VBoxDrv - The VirtualBox Support Driver - Common OS agnostic.
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 * 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 <iprt/errcore.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 RT_NOREF2(pvObj, pvUser2);
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 RT_NOREF1(pSession);
221 Assert(SUP_IS_SESSION_VALID(pSession));
222 return RTSemEventGetResolution();
223}
224
225
226/**
227 * Destructor for objects created by SUPSemEventMultiCreate.
228 *
229 * @param pvObj The object handle.
230 * @param pvUser1 The IPRT event handle.
231 * @param pvUser2 NULL.
232 */
233static DECLCALLBACK(void) supR0SemEventMultiDestructor(void *pvObj, void *pvUser1, void *pvUser2)
234{
235 Assert(pvUser2 == NULL);
236 RT_NOREF2(pvObj, pvUser2);
237 RTSemEventMultiDestroy((RTSEMEVENTMULTI)pvUser1);
238}
239
240
241SUPDECL(int) SUPSemEventMultiCreate(PSUPDRVSESSION pSession, PSUPSEMEVENTMULTI phEventMulti)
242{
243 int rc;
244 RTSEMEVENTMULTI hEventMultReal;
245
246 /*
247 * Input validation.
248 */
249 AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
250 AssertPtrReturn(phEventMulti, VERR_INVALID_POINTER);
251
252 /*
253 * Create the event semaphore object.
254 */
255 rc = RTSemEventMultiCreate(&hEventMultReal);
256 if (RT_SUCCESS(rc))
257 {
258 void *pvObj = SUPR0ObjRegister(pSession, SUPDRVOBJTYPE_SEM_EVENT_MULTI, supR0SemEventMultiDestructor, hEventMultReal, NULL);
259 if (pvObj)
260 {
261 uint32_t h32;
262 rc = RTHandleTableAllocWithCtx(pSession->hHandleTable, pvObj, SUPDRV_HANDLE_CTX_EVENT_MULTI, &h32);
263 if (RT_SUCCESS(rc))
264 {
265 *phEventMulti = (SUPSEMEVENTMULTI)(uintptr_t)h32;
266 return VINF_SUCCESS;
267 }
268 SUPR0ObjRelease(pvObj, pSession);
269 }
270 else
271 RTSemEventMultiDestroy(hEventMultReal);
272 }
273 return rc;
274}
275
276
277SUPDECL(int) SUPSemEventMultiClose(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti)
278{
279 uint32_t h32;
280 PSUPDRVOBJ pObj;
281
282 /*
283 * Input validation.
284 */
285 AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
286 if (hEventMulti == NIL_SUPSEMEVENTMULTI)
287 return VINF_SUCCESS;
288 h32 = (uint32_t)(uintptr_t)hEventMulti;
289 if (h32 != (uintptr_t)hEventMulti)
290 return VERR_INVALID_HANDLE;
291
292 /*
293 * Do the job.
294 */
295 pObj = (PSUPDRVOBJ)RTHandleTableFreeWithCtx(pSession->hHandleTable, h32, SUPDRV_HANDLE_CTX_EVENT_MULTI);
296 if (!pObj)
297 return VERR_INVALID_HANDLE;
298
299 Assert(pObj->cUsage >= 2);
300 SUPR0ObjRelease(pObj, pSession); /* The free call above. */
301 return SUPR0ObjRelease(pObj, pSession); /* The handle table reference. */
302}
303
304
305SUPDECL(int) SUPSemEventMultiSignal(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti)
306{
307 int rc;
308 uint32_t h32;
309 PSUPDRVOBJ pObj;
310
311 /*
312 * Input validation.
313 */
314 AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
315 h32 = (uint32_t)(uintptr_t)hEventMulti;
316 if (h32 != (uintptr_t)hEventMulti)
317 return VERR_INVALID_HANDLE;
318 pObj = (PSUPDRVOBJ)RTHandleTableLookupWithCtx(pSession->hHandleTable, h32, SUPDRV_HANDLE_CTX_EVENT_MULTI);
319 if (!pObj)
320 return VERR_INVALID_HANDLE;
321
322 /*
323 * Do the job.
324 */
325 rc = RTSemEventMultiSignal((RTSEMEVENTMULTI)pObj->pvUser1);
326
327 SUPR0ObjRelease(pObj, pSession);
328 return rc;
329}
330
331
332SUPDECL(int) SUPSemEventMultiReset(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti)
333{
334 int rc;
335 uint32_t h32;
336 PSUPDRVOBJ pObj;
337
338 /*
339 * Input validation.
340 */
341 AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
342 h32 = (uint32_t)(uintptr_t)hEventMulti;
343 if (h32 != (uintptr_t)hEventMulti)
344 return VERR_INVALID_HANDLE;
345 pObj = (PSUPDRVOBJ)RTHandleTableLookupWithCtx(pSession->hHandleTable, h32, SUPDRV_HANDLE_CTX_EVENT_MULTI);
346 if (!pObj)
347 return VERR_INVALID_HANDLE;
348
349 /*
350 * Do the job.
351 */
352 rc = RTSemEventMultiReset((RTSEMEVENTMULTI)pObj->pvUser1);
353
354 SUPR0ObjRelease(pObj, pSession);
355 return rc;
356}
357
358
359static int supR0SemEventMultiWaitEx(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint32_t fFlags, uint64_t uTimeout)
360{
361 int rc;
362 uint32_t h32;
363 PSUPDRVOBJ pObj;
364
365 /*
366 * Input validation.
367 */
368 AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
369 h32 = (uint32_t)(uintptr_t)hEventMulti;
370 if (h32 != (uintptr_t)hEventMulti)
371 return VERR_INVALID_HANDLE;
372 pObj = (PSUPDRVOBJ)RTHandleTableLookupWithCtx(pSession->hHandleTable, h32, SUPDRV_HANDLE_CTX_EVENT_MULTI);
373 if (!pObj)
374 return VERR_INVALID_HANDLE;
375
376 /*
377 * Do the job.
378 */
379 rc = RTSemEventMultiWaitEx((RTSEMEVENTMULTI)pObj->pvUser1, fFlags, uTimeout);
380
381 SUPR0ObjRelease(pObj, pSession);
382 return rc;
383}
384
385SUPDECL(int) SUPSemEventMultiWait(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint32_t cMillies)
386{
387 uint32_t fFlags = RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_MILLISECS | RTSEMWAIT_FLAGS_UNINTERRUPTIBLE;
388 if (cMillies == RT_INDEFINITE_WAIT)
389 fFlags |= RTSEMWAIT_FLAGS_INDEFINITE;
390 return supR0SemEventMultiWaitEx(pSession, hEventMulti, fFlags, cMillies);
391}
392
393
394
395SUPDECL(int) SUPSemEventMultiWaitNoResume(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint32_t cMillies)
396{
397 uint32_t fFlags = RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_MILLISECS | RTSEMWAIT_FLAGS_INTERRUPTIBLE;
398 if (cMillies == RT_INDEFINITE_WAIT)
399 fFlags |= RTSEMWAIT_FLAGS_INDEFINITE;
400 return supR0SemEventMultiWaitEx(pSession, hEventMulti, fFlags, cMillies);
401}
402
403
404SUPDECL(int) SUPSemEventMultiWaitNsAbsIntr(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint64_t uNsTimeout)
405{
406 uint32_t fFlags = RTSEMWAIT_FLAGS_ABSOLUTE | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_INTERRUPTIBLE;
407 return supR0SemEventMultiWaitEx(pSession, hEventMulti, fFlags, uNsTimeout);
408}
409
410
411SUPDECL(int) SUPSemEventMultiWaitNsRelIntr(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint64_t cNsTimeout)
412{
413 uint32_t fFlags = RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_INTERRUPTIBLE;
414 return supR0SemEventMultiWaitEx(pSession, hEventMulti, fFlags, cNsTimeout);
415}
416
417
418SUPDECL(uint32_t) SUPSemEventMultiGetResolution(PSUPDRVSESSION pSession)
419{
420 RT_NOREF1(pSession);
421 Assert(SUP_IS_SESSION_VALID(pSession));
422 return RTSemEventMultiGetResolution();
423}
424
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