VirtualBox

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

Last change on this file since 92270 was 87700, checked in by vboxsync, 4 years ago

SUPDrv,++: Experimental support for wrapping .r0 modules in native kernel modules on linux, so that perf and similar tools work better. Minor IOC version increase as SUP_IOCTL_LDR_OPEN now support just opening a module w/o preparing the loading. SUPDrv must export all the symbols in g_aFunctions the linux way now, or linux won't see them, so introduced a SUPR0_EXPORT_SYMBOL macro similar to RT_EXPORT_SYMBOL. bugref:9937

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.6 KB
Line 
1/* $Id: SUPDrvSem.cpp 87700 2021-02-10 20:21:04Z vboxsync $ */
2/** @file
3 * VBoxDrv - The VirtualBox Support Driver - Common OS agnostic.
4 */
5
6/*
7 * Copyright (C) 2006-2020 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}
102SUPR0_EXPORT_SYMBOL(SUPSemEventCreate);
103
104
105SUPDECL(int) SUPSemEventClose(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent)
106{
107 uint32_t h32;
108 PSUPDRVOBJ pObj;
109
110 /*
111 * Input validation.
112 */
113 AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
114 if (hEvent == NIL_SUPSEMEVENT)
115 return VINF_SUCCESS;
116 h32 = (uint32_t)(uintptr_t)hEvent;
117 if (h32 != (uintptr_t)hEvent)
118 return VERR_INVALID_HANDLE;
119
120 /*
121 * Do the job.
122 */
123 pObj = (PSUPDRVOBJ)RTHandleTableFreeWithCtx(pSession->hHandleTable, h32, SUPDRV_HANDLE_CTX_EVENT);
124 if (!pObj)
125 return VERR_INVALID_HANDLE;
126
127 Assert(pObj->cUsage >= 2);
128 SUPR0ObjRelease(pObj, pSession); /* The free call above. */
129 return SUPR0ObjRelease(pObj, pSession); /* The handle table reference. */
130}
131SUPR0_EXPORT_SYMBOL(SUPSemEventClose);
132
133
134SUPDECL(int) SUPSemEventSignal(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent)
135{
136 int rc;
137 uint32_t h32;
138 PSUPDRVOBJ pObj;
139
140 /*
141 * Input validation.
142 */
143 AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
144 h32 = (uint32_t)(uintptr_t)hEvent;
145 if (h32 != (uintptr_t)hEvent)
146 return VERR_INVALID_HANDLE;
147 pObj = (PSUPDRVOBJ)RTHandleTableLookupWithCtx(pSession->hHandleTable, h32, SUPDRV_HANDLE_CTX_EVENT);
148 if (!pObj)
149 return VERR_INVALID_HANDLE;
150
151 /*
152 * Do the job.
153 */
154 rc = RTSemEventSignal((RTSEMEVENT)pObj->pvUser1);
155
156 SUPR0ObjRelease(pObj, pSession);
157 return rc;
158}
159SUPR0_EXPORT_SYMBOL(SUPSemEventSignal);
160
161
162static int supR0SemEventWaitEx(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent, uint32_t fFlags, uint64_t uTimeout)
163{
164 int rc;
165 uint32_t h32;
166 PSUPDRVOBJ pObj;
167
168 /*
169 * Input validation.
170 */
171 AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
172 h32 = (uint32_t)(uintptr_t)hEvent;
173 if (h32 != (uintptr_t)hEvent)
174 return VERR_INVALID_HANDLE;
175 pObj = (PSUPDRVOBJ)RTHandleTableLookupWithCtx(pSession->hHandleTable, h32, SUPDRV_HANDLE_CTX_EVENT);
176 if (!pObj)
177 return VERR_INVALID_HANDLE;
178
179 /*
180 * Do the job.
181 */
182 rc = RTSemEventWaitEx((RTSEMEVENT)pObj->pvUser1, fFlags, uTimeout);
183
184 SUPR0ObjRelease(pObj, pSession);
185 return rc;
186}
187
188
189SUPDECL(int) SUPSemEventWait(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent, uint32_t cMillies)
190{
191 uint32_t fFlags = RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_MILLISECS | RTSEMWAIT_FLAGS_UNINTERRUPTIBLE;
192 if (cMillies == RT_INDEFINITE_WAIT)
193 fFlags |= RTSEMWAIT_FLAGS_INDEFINITE;
194 return supR0SemEventWaitEx(pSession, hEvent, fFlags, cMillies);
195}
196SUPR0_EXPORT_SYMBOL(SUPSemEventWait);
197
198
199SUPDECL(int) SUPSemEventWaitNoResume(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent, uint32_t cMillies)
200{
201 uint32_t fFlags = RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_MILLISECS | RTSEMWAIT_FLAGS_INTERRUPTIBLE;
202 if (cMillies == RT_INDEFINITE_WAIT)
203 fFlags |= RTSEMWAIT_FLAGS_INDEFINITE;
204 return supR0SemEventWaitEx(pSession, hEvent, fFlags, cMillies);
205}
206SUPR0_EXPORT_SYMBOL(SUPSemEventWaitNoResume);
207
208
209SUPDECL(int) SUPSemEventWaitNsAbsIntr(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent, uint64_t uNsTimeout)
210{
211 uint32_t fFlags = RTSEMWAIT_FLAGS_ABSOLUTE | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_INTERRUPTIBLE;
212 return supR0SemEventWaitEx(pSession, hEvent, fFlags, uNsTimeout);
213}
214SUPR0_EXPORT_SYMBOL(SUPSemEventWaitNsAbsIntr);
215
216
217SUPDECL(int) SUPSemEventWaitNsRelIntr(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent, uint64_t cNsTimeout)
218{
219 uint32_t fFlags = RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_INTERRUPTIBLE;
220 return supR0SemEventWaitEx(pSession, hEvent, fFlags, cNsTimeout);
221}
222SUPR0_EXPORT_SYMBOL(SUPSemEventWaitNsRelIntr);
223
224
225SUPDECL(uint32_t) SUPSemEventGetResolution(PSUPDRVSESSION pSession)
226{
227 RT_NOREF1(pSession);
228 Assert(SUP_IS_SESSION_VALID(pSession));
229 return RTSemEventGetResolution();
230}
231SUPR0_EXPORT_SYMBOL(SUPSemEventGetResolution);
232
233
234/**
235 * Destructor for objects created by SUPSemEventMultiCreate.
236 *
237 * @param pvObj The object handle.
238 * @param pvUser1 The IPRT event handle.
239 * @param pvUser2 NULL.
240 */
241static DECLCALLBACK(void) supR0SemEventMultiDestructor(void *pvObj, void *pvUser1, void *pvUser2)
242{
243 Assert(pvUser2 == NULL);
244 RT_NOREF2(pvObj, pvUser2);
245 RTSemEventMultiDestroy((RTSEMEVENTMULTI)pvUser1);
246}
247
248
249SUPDECL(int) SUPSemEventMultiCreate(PSUPDRVSESSION pSession, PSUPSEMEVENTMULTI phEventMulti)
250{
251 int rc;
252 RTSEMEVENTMULTI hEventMultReal;
253
254 /*
255 * Input validation.
256 */
257 AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
258 AssertPtrReturn(phEventMulti, VERR_INVALID_POINTER);
259
260 /*
261 * Create the event semaphore object.
262 */
263 rc = RTSemEventMultiCreate(&hEventMultReal);
264 if (RT_SUCCESS(rc))
265 {
266 void *pvObj = SUPR0ObjRegister(pSession, SUPDRVOBJTYPE_SEM_EVENT_MULTI, supR0SemEventMultiDestructor, hEventMultReal, NULL);
267 if (pvObj)
268 {
269 uint32_t h32;
270 rc = RTHandleTableAllocWithCtx(pSession->hHandleTable, pvObj, SUPDRV_HANDLE_CTX_EVENT_MULTI, &h32);
271 if (RT_SUCCESS(rc))
272 {
273 *phEventMulti = (SUPSEMEVENTMULTI)(uintptr_t)h32;
274 return VINF_SUCCESS;
275 }
276 SUPR0ObjRelease(pvObj, pSession);
277 }
278 else
279 RTSemEventMultiDestroy(hEventMultReal);
280 }
281 return rc;
282}
283SUPR0_EXPORT_SYMBOL(SUPSemEventMultiCreate);
284
285
286SUPDECL(int) SUPSemEventMultiClose(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti)
287{
288 uint32_t h32;
289 PSUPDRVOBJ pObj;
290
291 /*
292 * Input validation.
293 */
294 AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
295 if (hEventMulti == NIL_SUPSEMEVENTMULTI)
296 return VINF_SUCCESS;
297 h32 = (uint32_t)(uintptr_t)hEventMulti;
298 if (h32 != (uintptr_t)hEventMulti)
299 return VERR_INVALID_HANDLE;
300
301 /*
302 * Do the job.
303 */
304 pObj = (PSUPDRVOBJ)RTHandleTableFreeWithCtx(pSession->hHandleTable, h32, SUPDRV_HANDLE_CTX_EVENT_MULTI);
305 if (!pObj)
306 return VERR_INVALID_HANDLE;
307
308 Assert(pObj->cUsage >= 2);
309 SUPR0ObjRelease(pObj, pSession); /* The free call above. */
310 return SUPR0ObjRelease(pObj, pSession); /* The handle table reference. */
311}
312SUPR0_EXPORT_SYMBOL(SUPSemEventMultiClose);
313
314
315SUPDECL(int) SUPSemEventMultiSignal(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti)
316{
317 int rc;
318 uint32_t h32;
319 PSUPDRVOBJ pObj;
320
321 /*
322 * Input validation.
323 */
324 AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
325 h32 = (uint32_t)(uintptr_t)hEventMulti;
326 if (h32 != (uintptr_t)hEventMulti)
327 return VERR_INVALID_HANDLE;
328 pObj = (PSUPDRVOBJ)RTHandleTableLookupWithCtx(pSession->hHandleTable, h32, SUPDRV_HANDLE_CTX_EVENT_MULTI);
329 if (!pObj)
330 return VERR_INVALID_HANDLE;
331
332 /*
333 * Do the job.
334 */
335 rc = RTSemEventMultiSignal((RTSEMEVENTMULTI)pObj->pvUser1);
336
337 SUPR0ObjRelease(pObj, pSession);
338 return rc;
339}
340SUPR0_EXPORT_SYMBOL(SUPSemEventMultiSignal);
341
342
343SUPDECL(int) SUPSemEventMultiReset(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti)
344{
345 int rc;
346 uint32_t h32;
347 PSUPDRVOBJ pObj;
348
349 /*
350 * Input validation.
351 */
352 AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
353 h32 = (uint32_t)(uintptr_t)hEventMulti;
354 if (h32 != (uintptr_t)hEventMulti)
355 return VERR_INVALID_HANDLE;
356 pObj = (PSUPDRVOBJ)RTHandleTableLookupWithCtx(pSession->hHandleTable, h32, SUPDRV_HANDLE_CTX_EVENT_MULTI);
357 if (!pObj)
358 return VERR_INVALID_HANDLE;
359
360 /*
361 * Do the job.
362 */
363 rc = RTSemEventMultiReset((RTSEMEVENTMULTI)pObj->pvUser1);
364
365 SUPR0ObjRelease(pObj, pSession);
366 return rc;
367}
368SUPR0_EXPORT_SYMBOL(SUPSemEventMultiReset);
369
370
371static int supR0SemEventMultiWaitEx(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint32_t fFlags, uint64_t uTimeout)
372{
373 int rc;
374 uint32_t h32;
375 PSUPDRVOBJ pObj;
376
377 /*
378 * Input validation.
379 */
380 AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
381 h32 = (uint32_t)(uintptr_t)hEventMulti;
382 if (h32 != (uintptr_t)hEventMulti)
383 return VERR_INVALID_HANDLE;
384 pObj = (PSUPDRVOBJ)RTHandleTableLookupWithCtx(pSession->hHandleTable, h32, SUPDRV_HANDLE_CTX_EVENT_MULTI);
385 if (!pObj)
386 return VERR_INVALID_HANDLE;
387
388 /*
389 * Do the job.
390 */
391 rc = RTSemEventMultiWaitEx((RTSEMEVENTMULTI)pObj->pvUser1, fFlags, uTimeout);
392
393 SUPR0ObjRelease(pObj, pSession);
394 return rc;
395}
396
397
398SUPDECL(int) SUPSemEventMultiWait(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint32_t cMillies)
399{
400 uint32_t fFlags = RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_MILLISECS | RTSEMWAIT_FLAGS_UNINTERRUPTIBLE;
401 if (cMillies == RT_INDEFINITE_WAIT)
402 fFlags |= RTSEMWAIT_FLAGS_INDEFINITE;
403 return supR0SemEventMultiWaitEx(pSession, hEventMulti, fFlags, cMillies);
404}
405SUPR0_EXPORT_SYMBOL(SUPSemEventMultiWait);
406
407
408
409SUPDECL(int) SUPSemEventMultiWaitNoResume(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint32_t cMillies)
410{
411 uint32_t fFlags = RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_MILLISECS | RTSEMWAIT_FLAGS_INTERRUPTIBLE;
412 if (cMillies == RT_INDEFINITE_WAIT)
413 fFlags |= RTSEMWAIT_FLAGS_INDEFINITE;
414 return supR0SemEventMultiWaitEx(pSession, hEventMulti, fFlags, cMillies);
415}
416SUPR0_EXPORT_SYMBOL(SUPSemEventMultiWaitNoResume);
417
418
419SUPDECL(int) SUPSemEventMultiWaitNsAbsIntr(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint64_t uNsTimeout)
420{
421 uint32_t fFlags = RTSEMWAIT_FLAGS_ABSOLUTE | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_INTERRUPTIBLE;
422 return supR0SemEventMultiWaitEx(pSession, hEventMulti, fFlags, uNsTimeout);
423}
424SUPR0_EXPORT_SYMBOL(SUPSemEventMultiWaitNsAbsIntr);
425
426
427SUPDECL(int) SUPSemEventMultiWaitNsRelIntr(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint64_t cNsTimeout)
428{
429 uint32_t fFlags = RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_INTERRUPTIBLE;
430 return supR0SemEventMultiWaitEx(pSession, hEventMulti, fFlags, cNsTimeout);
431}
432SUPR0_EXPORT_SYMBOL(SUPSemEventMultiWaitNsRelIntr);
433
434
435SUPDECL(uint32_t) SUPSemEventMultiGetResolution(PSUPDRVSESSION pSession)
436{
437 RT_NOREF1(pSession);
438 Assert(SUP_IS_SESSION_VALID(pSession));
439 return RTSemEventMultiGetResolution();
440}
441SUPR0_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