VirtualBox

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

Last change on this file was 106061, checked in by vboxsync, 2 months ago

Copyright year updates by scm.

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