VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/posix/semevent-posix.cpp@ 93115

Last change on this file since 93115 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 22.0 KB
Line 
1/* $Id: semevent-posix.cpp 93115 2022-01-01 11:31:46Z vboxsync $ */
2/** @file
3 * IPRT - Event Semaphore, POSIX.
4 */
5
6/*
7 * Copyright (C) 2006-2022 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#include <iprt/semaphore.h>
32#include "internal/iprt.h"
33
34#include <iprt/asm.h>
35#include <iprt/assert.h>
36#include <iprt/err.h>
37#include <iprt/mem.h>
38#include <iprt/lockvalidator.h>
39#include <iprt/time.h>
40
41#include "internal/mem.h"
42#include "internal/strict.h"
43
44#include <errno.h>
45#include <pthread.h>
46#include <unistd.h>
47#include <sys/time.h>
48#include <sched.h>
49
50#include "semwait.h"
51
52
53/*********************************************************************************************************************************
54* Structures and Typedefs *
55*********************************************************************************************************************************/
56
57/** Internal representation of the POSIX implementation of an Event semaphore.
58 * The POSIX implementation uses a mutex and a condition variable to implement
59 * the automatic reset event semaphore semantics.
60 */
61struct RTSEMEVENTINTERNAL
62{
63 /** pthread condition. */
64 pthread_cond_t Cond;
65 /** pthread mutex which protects the condition and the event state. */
66 pthread_mutex_t Mutex;
67 /** The state of the semaphore.
68 * This is operated while owning mutex and using atomic updating. */
69 volatile uint32_t u32State;
70 /** Number of waiters. */
71 volatile uint32_t cWaiters;
72#ifdef RTSEMEVENT_STRICT
73 /** Signallers. */
74 RTLOCKVALRECSHRD Signallers;
75 /** Indicates that lock validation should be performed. */
76 bool volatile fEverHadSignallers;
77#endif
78 /** The creation flags. */
79 uint32_t fFlags;
80 /** Set if we're using the monotonic clock. */
81 bool fMonotonicClock;
82};
83
84/** The values of the u32State variable in a RTSEMEVENTINTERNAL.
85 * @{ */
86/** The object isn't initialized. */
87#define EVENT_STATE_UNINITIALIZED 0
88/** The semaphore is signaled. */
89#define EVENT_STATE_SIGNALED 0xff00ff00
90/** The semaphore is not signaled. */
91#define EVENT_STATE_NOT_SIGNALED 0x00ff00ff
92/** @} */
93
94
95RTDECL(int) RTSemEventCreate(PRTSEMEVENT phEventSem)
96{
97 return RTSemEventCreateEx(phEventSem, 0 /*fFlags*/, NIL_RTLOCKVALCLASS, NULL);
98}
99
100
101RTDECL(int) RTSemEventCreateEx(PRTSEMEVENT phEventSem, uint32_t fFlags, RTLOCKVALCLASS hClass, const char *pszNameFmt, ...)
102{
103 AssertReturn(!(fFlags & ~(RTSEMEVENT_FLAGS_NO_LOCK_VAL | RTSEMEVENT_FLAGS_BOOTSTRAP_HACK)), VERR_INVALID_PARAMETER);
104 Assert(!(fFlags & RTSEMEVENT_FLAGS_BOOTSTRAP_HACK) || (fFlags & RTSEMEVENT_FLAGS_NO_LOCK_VAL));
105
106 /*
107 * Allocate semaphore handle.
108 */
109 int rc;
110 struct RTSEMEVENTINTERNAL *pThis;
111 if (!(fFlags & RTSEMEVENT_FLAGS_BOOTSTRAP_HACK))
112 pThis = (struct RTSEMEVENTINTERNAL *)RTMemAlloc(sizeof(*pThis));
113 else
114 pThis = (struct RTSEMEVENTINTERNAL *)rtMemBaseAlloc(sizeof(*pThis));
115 if (pThis)
116 {
117 /*
118 * Create the condition variable.
119 */
120 pthread_condattr_t CondAttr;
121 rc = pthread_condattr_init(&CondAttr);
122 if (!rc)
123 {
124#if defined(CLOCK_MONOTONIC) && defined(IPRT_HAVE_PTHREAD_CONDATTR_SETCLOCK)
125 /* ASSUMES RTTimeSystemNanoTS() == RTTimeNanoTS() == clock_gettime(CLOCK_MONOTONIC). */
126 rc = pthread_condattr_setclock(&CondAttr, CLOCK_MONOTONIC);
127 pThis->fMonotonicClock = rc == 0;
128#else
129 pThis->fMonotonicClock = false;
130#endif
131 rc = pthread_cond_init(&pThis->Cond, &CondAttr);
132 if (!rc)
133 {
134 /*
135 * Create the semaphore.
136 */
137 rc = pthread_mutex_init(&pThis->Mutex, NULL);
138 if (!rc)
139 {
140 pthread_condattr_destroy(&CondAttr);
141
142 ASMAtomicWriteU32(&pThis->u32State, EVENT_STATE_NOT_SIGNALED);
143 ASMAtomicWriteU32(&pThis->cWaiters, 0);
144 pThis->fFlags = fFlags;
145#ifdef RTSEMEVENT_STRICT
146 if (!pszNameFmt)
147 {
148 static uint32_t volatile s_iSemEventAnon = 0;
149 RTLockValidatorRecSharedInit(&pThis->Signallers, hClass, RTLOCKVAL_SUB_CLASS_ANY, pThis,
150 true /*fSignaller*/, !(fFlags & RTSEMEVENT_FLAGS_NO_LOCK_VAL),
151 "RTSemEvent-%u", ASMAtomicIncU32(&s_iSemEventAnon) - 1);
152 }
153 else
154 {
155 va_list va;
156 va_start(va, pszNameFmt);
157 RTLockValidatorRecSharedInitV(&pThis->Signallers, hClass, RTLOCKVAL_SUB_CLASS_ANY, pThis,
158 true /*fSignaller*/, !(fFlags & RTSEMEVENT_FLAGS_NO_LOCK_VAL),
159 pszNameFmt, va);
160 va_end(va);
161 }
162 pThis->fEverHadSignallers = false;
163#else
164 RT_NOREF_PV(hClass); RT_NOREF_PV(pszNameFmt);
165#endif
166
167 *phEventSem = pThis;
168 return VINF_SUCCESS;
169 }
170 pthread_cond_destroy(&pThis->Cond);
171 }
172 pthread_condattr_destroy(&CondAttr);
173 }
174
175 rc = RTErrConvertFromErrno(rc);
176 if (!(fFlags & RTSEMEVENT_FLAGS_BOOTSTRAP_HACK))
177 RTMemFree(pThis);
178 else
179 rtMemBaseFree(pThis);
180 }
181 else
182 rc = VERR_NO_MEMORY;
183
184 return rc;
185}
186
187
188RTDECL(int) RTSemEventDestroy(RTSEMEVENT hEventSem)
189{
190 /*
191 * Validate handle.
192 */
193 struct RTSEMEVENTINTERNAL *pThis = hEventSem;
194 if (pThis == NIL_RTSEMEVENT)
195 return VINF_SUCCESS;
196 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
197 uint32_t u32 = pThis->u32State;
198 AssertReturn(u32 == EVENT_STATE_NOT_SIGNALED || u32 == EVENT_STATE_SIGNALED, VERR_INVALID_HANDLE);
199
200 /*
201 * Abort all waiters forcing them to return failure.
202 */
203 int rc;
204 for (int i = 30; i > 0; i--)
205 {
206 ASMAtomicWriteU32(&pThis->u32State, EVENT_STATE_UNINITIALIZED);
207 rc = pthread_cond_destroy(&pThis->Cond);
208 if (rc != EBUSY)
209 break;
210 pthread_cond_broadcast(&pThis->Cond);
211 usleep(1000);
212 }
213 if (rc)
214 {
215 AssertMsgFailed(("Failed to destroy event sem %p, rc=%d.\n", pThis, rc));
216 return RTErrConvertFromErrno(rc);
217 }
218
219 /*
220 * Destroy the semaphore
221 * If it's busy we'll wait a bit to give the threads a chance to be scheduled.
222 */
223 for (int i = 30; i > 0; i--)
224 {
225 rc = pthread_mutex_destroy(&pThis->Mutex);
226 if (rc != EBUSY)
227 break;
228 usleep(1000);
229 }
230 if (rc)
231 {
232 AssertMsgFailed(("Failed to destroy event sem %p, rc=%d. (mutex)\n", pThis, rc));
233 return RTErrConvertFromErrno(rc);
234 }
235
236 /*
237 * Free the semaphore memory and be gone.
238 */
239#ifdef RTSEMEVENT_STRICT
240 RTLockValidatorRecSharedDelete(&pThis->Signallers);
241#endif
242 if (!(pThis->fFlags & RTSEMEVENT_FLAGS_BOOTSTRAP_HACK))
243 RTMemFree(pThis);
244 else
245 rtMemBaseFree(pThis);
246 return VINF_SUCCESS;
247}
248
249
250RTDECL(int) RTSemEventSignal(RTSEMEVENT hEventSem)
251{
252 /*
253 * Validate input.
254 */
255 struct RTSEMEVENTINTERNAL *pThis = hEventSem;
256 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
257 uint32_t u32 = pThis->u32State;
258 AssertReturn(u32 == EVENT_STATE_NOT_SIGNALED || u32 == EVENT_STATE_SIGNALED, VERR_INVALID_HANDLE);
259
260#ifdef RTSEMEVENT_STRICT
261 if (pThis->fEverHadSignallers)
262 {
263 int rc9 = RTLockValidatorRecSharedCheckSignaller(&pThis->Signallers, NIL_RTTHREAD);
264 if (RT_FAILURE(rc9))
265 return rc9;
266 }
267#endif
268
269 /*
270 * Lock the mutex semaphore.
271 */
272 int rc = pthread_mutex_lock(&pThis->Mutex);
273 if (rc)
274 {
275 AssertMsgFailed(("Failed to lock event sem %p, rc=%d.\n", hEventSem, rc));
276 return RTErrConvertFromErrno(rc);
277 }
278
279 /*
280 * Check the state.
281 */
282 if (pThis->u32State == EVENT_STATE_NOT_SIGNALED)
283 {
284 ASMAtomicWriteU32(&pThis->u32State, EVENT_STATE_SIGNALED);
285 rc = pthread_cond_signal(&pThis->Cond);
286 AssertMsg(!rc, ("Failed to signal event sem %p, rc=%d.\n", hEventSem, rc));
287 }
288 else if (pThis->u32State == EVENT_STATE_SIGNALED)
289 {
290 rc = pthread_cond_signal(&pThis->Cond); /* give'm another kick... */
291 AssertMsg(!rc, ("Failed to signal event sem %p, rc=%d. (2)\n", hEventSem, rc));
292 }
293 else
294 rc = VERR_SEM_DESTROYED;
295
296 /*
297 * Release the mutex and return.
298 */
299 int rc2 = pthread_mutex_unlock(&pThis->Mutex);
300 AssertMsg(!rc2, ("Failed to unlock event sem %p, rc=%d.\n", hEventSem, rc));
301 if (rc)
302 return RTErrConvertFromErrno(rc);
303 if (rc2)
304 return RTErrConvertFromErrno(rc2);
305
306 return VINF_SUCCESS;
307}
308
309
310/**
311 * Handle polling (timeout already expired at the time of the call).
312 *
313 * @returns VINF_SUCCESS, VERR_TIMEOUT, VERR_SEM_DESTROYED.
314 * @param pThis The semaphore.
315 */
316DECLINLINE(int) rtSemEventPosixWaitPoll(struct RTSEMEVENTINTERNAL *pThis)
317{
318 int rc = pthread_mutex_lock(&pThis->Mutex);
319 AssertMsgReturn(!rc, ("Failed to lock event sem %p, rc=%d.\n", pThis, rc), RTErrConvertFromErrno(rc));
320
321 uint32_t u32OldState;
322 bool fSuccess = ASMAtomicCmpXchgExU32(&pThis->u32State, EVENT_STATE_NOT_SIGNALED, EVENT_STATE_SIGNALED, &u32OldState);
323
324 rc = pthread_mutex_unlock(&pThis->Mutex);
325 AssertMsg(!rc, ("Failed to unlock event sem %p, rc=%d.\n", pThis, rc)); NOREF(rc);
326
327 return fSuccess
328 ? VINF_SUCCESS
329 : u32OldState != EVENT_STATE_UNINITIALIZED
330 ? VERR_TIMEOUT
331 : VERR_SEM_DESTROYED;
332}
333
334
335/**
336 * Performs an indefinite wait on the event.
337 */
338static int rtSemEventPosixWaitIndefinite(struct RTSEMEVENTINTERNAL *pThis, uint32_t fFlags, PCRTLOCKVALSRCPOS pSrcPos)
339{
340 RT_NOREF_PV(pSrcPos);
341
342 /* for fairness, yield before going to sleep. */
343 if ( ASMAtomicIncU32(&pThis->cWaiters) > 1
344 && pThis->u32State == EVENT_STATE_SIGNALED)
345 sched_yield();
346
347 /* take mutex */
348 int rc = pthread_mutex_lock(&pThis->Mutex);
349 if (rc)
350 {
351 ASMAtomicDecU32(&pThis->cWaiters);
352 AssertMsgFailed(("Failed to lock event sem %p, rc=%d.\n", pThis, rc));
353 return RTErrConvertFromErrno(rc);
354 }
355
356 for (;;)
357 {
358 /* check state. */
359 if (pThis->u32State == EVENT_STATE_SIGNALED)
360 {
361 ASMAtomicWriteU32(&pThis->u32State, EVENT_STATE_NOT_SIGNALED);
362 ASMAtomicDecU32(&pThis->cWaiters);
363 rc = pthread_mutex_unlock(&pThis->Mutex);
364 AssertMsg(!rc, ("Failed to unlock event sem %p, rc=%d.\n", pThis, rc)); NOREF(rc);
365 return VINF_SUCCESS;
366 }
367 if (pThis->u32State == EVENT_STATE_UNINITIALIZED)
368 {
369 rc = pthread_mutex_unlock(&pThis->Mutex);
370 AssertMsg(!rc, ("Failed to unlock event sem %p, rc=%d.\n", pThis, rc)); NOREF(rc);
371 return VERR_SEM_DESTROYED;
372 }
373
374 /* wait */
375#ifdef RTSEMEVENT_STRICT
376 RTTHREAD hThreadSelf = !(pThis->fFlags & RTSEMEVENT_FLAGS_BOOTSTRAP_HACK)
377 ? RTThreadSelfAutoAdopt()
378 : RTThreadSelf();
379 if (pThis->fEverHadSignallers)
380 {
381 rc = RTLockValidatorRecSharedCheckBlocking(&pThis->Signallers, hThreadSelf, pSrcPos, false,
382 RT_INDEFINITE_WAIT, RTTHREADSTATE_EVENT, true);
383 if (RT_FAILURE(rc))
384 {
385 ASMAtomicDecU32(&pThis->cWaiters);
386 pthread_mutex_unlock(&pThis->Mutex);
387 return rc;
388 }
389 }
390#else
391 RTTHREAD hThreadSelf = RTThreadSelf();
392#endif
393 RTThreadBlocking(hThreadSelf, RTTHREADSTATE_EVENT, true);
394 RT_NOREF_PV(fFlags); /** @todo interruptible wait is not implementable... */
395 rc = pthread_cond_wait(&pThis->Cond, &pThis->Mutex);
396 RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_EVENT);
397 if (rc)
398 {
399 AssertMsgFailed(("Failed to wait on event sem %p, rc=%d.\n", pThis, rc));
400 ASMAtomicDecU32(&pThis->cWaiters);
401 int rc2 = pthread_mutex_unlock(&pThis->Mutex);
402 AssertMsg(!rc2, ("Failed to unlock event sem %p, rc=%d.\n", pThis, rc2)); NOREF(rc2);
403 return RTErrConvertFromErrno(rc);
404 }
405 }
406}
407
408
409/**
410 * Performs an timed wait on the event.
411 */
412static int rtSemEventPosixWaitTimed(struct RTSEMEVENTINTERNAL *pThis, uint32_t fFlags, uint64_t uTimeout,
413 PCRTLOCKVALSRCPOS pSrcPos)
414{
415 /*
416 * Convert the timeout specification to absolute and relative deadlines,
417 * divierting polling and infinite waits to the appropriate workers.
418 */
419 struct timespec AbsDeadline = { 0, 0 };
420 uint64_t const cNsRelativeDeadline = rtSemPosixCalcDeadline(fFlags, uTimeout, pThis->fMonotonicClock, &AbsDeadline);
421 if (cNsRelativeDeadline == 0)
422 return rtSemEventPosixWaitPoll(pThis);
423 if (cNsRelativeDeadline == UINT64_MAX)
424 return rtSemEventPosixWaitIndefinite(pThis, fFlags, pSrcPos);
425
426 /*
427 * Now to the business of waiting...
428 */
429
430 /* for fairness, yield before going to sleep. */
431 if (ASMAtomicIncU32(&pThis->cWaiters) > 1)
432 sched_yield();
433
434 /* take mutex */
435 int rc = pthread_mutex_lock(&pThis->Mutex);
436 if (rc)
437 {
438 ASMAtomicDecU32(&pThis->cWaiters);
439 AssertMsg(rc == ETIMEDOUT, ("Failed to lock event sem %p, rc=%d.\n", pThis, rc));
440 return RTErrConvertFromErrno(rc);
441 }
442
443 for (;;)
444 {
445 /* check state. */
446 uint32_t const u32State = pThis->u32State;
447 if (u32State != EVENT_STATE_NOT_SIGNALED)
448 {
449 if (u32State == EVENT_STATE_SIGNALED)
450 {
451 ASMAtomicWriteU32(&pThis->u32State, EVENT_STATE_NOT_SIGNALED);
452 ASMAtomicDecU32(&pThis->cWaiters);
453 rc = VINF_SUCCESS;
454 }
455 else
456 {
457 Assert(u32State == EVENT_STATE_UNINITIALIZED);
458 rc = VERR_SEM_DESTROYED;
459 }
460 int rc2 = pthread_mutex_unlock(&pThis->Mutex);
461 AssertMsg(!rc2, ("Failed to unlock event sem %p, rc2=%d.\n", pThis, rc2)); RT_NOREF(rc2);
462 return rc;
463 }
464
465 /* wait */
466#ifdef RTSEMEVENT_STRICT
467 RTTHREAD hThreadSelf = !(pThis->fFlags & RTSEMEVENT_FLAGS_BOOTSTRAP_HACK)
468 ? RTThreadSelfAutoAdopt()
469 : RTThreadSelf();
470 if (pThis->fEverHadSignallers)
471 {
472 rc = RTLockValidatorRecSharedCheckBlocking(&pThis->Signallers, hThreadSelf, pSrcPos, false,
473 (cNsRelativeDeadline + RT_NS_1MS - 1) / RT_NS_1MS,
474 RTTHREADSTATE_EVENT, true);
475 if (RT_FAILURE(rc))
476 {
477 ASMAtomicDecU32(&pThis->cWaiters);
478 pthread_mutex_unlock(&pThis->Mutex);
479 return rc;
480 }
481 }
482#else
483 RTTHREAD hThreadSelf = RTThreadSelf();
484#endif
485 RTThreadBlocking(hThreadSelf, RTTHREADSTATE_EVENT, true);
486 rc = pthread_cond_timedwait(&pThis->Cond, &pThis->Mutex, &AbsDeadline);
487 RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_EVENT);
488
489 /* According to SuS this function shall not return EINTR, but linux man page might have said differently at some point... */
490 if ( rc != 0
491 && ( rc != EINTR
492 || !(fFlags & RTSEMWAIT_FLAGS_NORESUME)))
493 {
494 AssertMsg(rc == ETIMEDOUT, ("Failed to wait on event sem %p, rc=%d.\n", pThis, rc));
495 ASMAtomicDecU32(&pThis->cWaiters);
496 int rc2 = pthread_mutex_unlock(&pThis->Mutex);
497 AssertMsg(!rc2, ("Failed to unlock event sem %p, rc2=%d.\n", pThis, rc2)); NOREF(rc2);
498 return RTErrConvertFromErrno(rc);
499 }
500 } /* for (;;) */
501}
502
503
504/**
505 * Internal wait worker function.
506 */
507DECLINLINE(int) rtSemEventPosixWait(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout, PCRTLOCKVALSRCPOS pSrcPos)
508{
509 /*
510 * Validate input.
511 */
512 struct RTSEMEVENTINTERNAL *pThis = hEventSem;
513 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
514 uint32_t u32 = pThis->u32State;
515 AssertReturn(u32 == EVENT_STATE_NOT_SIGNALED || u32 == EVENT_STATE_SIGNALED, VERR_INVALID_HANDLE);
516 AssertReturn(RTSEMWAIT_FLAGS_ARE_VALID(fFlags), VERR_INVALID_PARAMETER);
517
518 /*
519 * Timed or indefinite wait?
520 */
521 if (fFlags & RTSEMWAIT_FLAGS_INDEFINITE)
522 return rtSemEventPosixWaitIndefinite(pThis, fFlags, pSrcPos);
523 return rtSemEventPosixWaitTimed(hEventSem, fFlags, uTimeout, pSrcPos);
524}
525
526
527RTDECL(int) RTSemEventWait(RTSEMEVENT hEventSem, RTMSINTERVAL cMillies)
528{
529 int rc;
530#ifndef RTSEMEVENT_STRICT
531 if (cMillies == RT_INDEFINITE_WAIT)
532 rc = rtSemEventPosixWait(hEventSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_INDEFINITE, 0, NULL);
533 else
534 rc = rtSemEventPosixWait(hEventSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_MILLISECS,
535 cMillies, NULL);
536#else
537 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
538 if (cMillies == RT_INDEFINITE_WAIT)
539 rc = rtSemEventPosixWait(hEventSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_INDEFINITE, 0, &SrcPos);
540 else
541 rc = rtSemEventPosixWait(hEventSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_MILLISECS,
542 cMillies, &SrcPos);
543#endif
544 Assert(rc != VERR_INTERRUPTED);
545 return rc;
546}
547
548
549RTDECL(int) RTSemEventWaitNoResume(RTSEMEVENT hEventSem, RTMSINTERVAL cMillies)
550{
551 int rc;
552#ifndef RTSEMEVENT_STRICT
553 if (cMillies == RT_INDEFINITE_WAIT)
554 rc = rtSemEventPosixWait(hEventSem, RTSEMWAIT_FLAGS_NORESUME | RTSEMWAIT_FLAGS_INDEFINITE, 0, NULL);
555 else
556 rc = rtSemEventPosixWait(hEventSem, RTSEMWAIT_FLAGS_NORESUME | RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_MILLISECS,
557 cMillies, NULL);
558#else
559 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
560 if (cMillies == RT_INDEFINITE_WAIT)
561 rc = rtSemEventPosixWait(hEventSem, RTSEMWAIT_FLAGS_NORESUME | RTSEMWAIT_FLAGS_INDEFINITE, 0, &SrcPos);
562 else
563 rc = rtSemEventPosixWait(hEventSem, RTSEMWAIT_FLAGS_NORESUME | RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_MILLISECS,
564 cMillies, &SrcPos);
565#endif
566 Assert(rc != VERR_INTERRUPTED);
567 return rc;
568}
569
570
571RTDECL(int) RTSemEventWaitEx(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout)
572{
573#ifndef RTSEMEVENT_STRICT
574 return rtSemEventPosixWait(hEventSem, fFlags, uTimeout, NULL);
575#else
576 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
577 return rtSemEventPosixWait(hEventSem, fFlags, uTimeout, &SrcPos);
578#endif
579}
580
581
582RTDECL(int) RTSemEventWaitExDebug(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout,
583 RTHCUINTPTR uId, RT_SRC_POS_DECL)
584{
585 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
586 return rtSemEventPosixWait(hEventSem, fFlags, uTimeout, &SrcPos);
587}
588
589
590RTDECL(uint32_t) RTSemEventGetResolution(void)
591{
592 /** @todo we have 1ns parameter resolution, but we need to check each host
593 * what the actual resolution might be once the parameter makes it to the
594 * kernel and is processed there. */
595 return 1;
596}
597
598
599RTDECL(void) RTSemEventSetSignaller(RTSEMEVENT hEventSem, RTTHREAD hThread)
600{
601#ifdef RTSEMEVENT_STRICT
602 struct RTSEMEVENTINTERNAL *pThis = hEventSem;
603 AssertPtrReturnVoid(pThis);
604 uint32_t u32 = pThis->u32State;
605 AssertReturnVoid(u32 == EVENT_STATE_NOT_SIGNALED || u32 == EVENT_STATE_SIGNALED);
606
607 ASMAtomicWriteBool(&pThis->fEverHadSignallers, true);
608 RTLockValidatorRecSharedResetOwner(&pThis->Signallers, hThread, NULL);
609#else
610 RT_NOREF_PV(hEventSem); RT_NOREF_PV(hThread);
611#endif
612}
613
614
615RTDECL(void) RTSemEventAddSignaller(RTSEMEVENT hEventSem, RTTHREAD hThread)
616{
617#ifdef RTSEMEVENT_STRICT
618 struct RTSEMEVENTINTERNAL *pThis = hEventSem;
619 AssertPtrReturnVoid(pThis);
620 uint32_t u32 = pThis->u32State;
621 AssertReturnVoid(u32 == EVENT_STATE_NOT_SIGNALED || u32 == EVENT_STATE_SIGNALED);
622
623 ASMAtomicWriteBool(&pThis->fEverHadSignallers, true);
624 RTLockValidatorRecSharedAddOwner(&pThis->Signallers, hThread, NULL);
625#else
626 RT_NOREF_PV(hEventSem); RT_NOREF_PV(hThread);
627#endif
628}
629
630
631RTDECL(void) RTSemEventRemoveSignaller(RTSEMEVENT hEventSem, RTTHREAD hThread)
632{
633#ifdef RTSEMEVENT_STRICT
634 struct RTSEMEVENTINTERNAL *pThis = hEventSem;
635 AssertPtrReturnVoid(pThis);
636 uint32_t u32 = pThis->u32State;
637 AssertReturnVoid(u32 == EVENT_STATE_NOT_SIGNALED || u32 == EVENT_STATE_SIGNALED);
638
639 RTLockValidatorRecSharedRemoveOwner(&pThis->Signallers, hThread);
640#else
641 RT_NOREF_PV(hEventSem); RT_NOREF_PV(hThread);
642#endif
643}
644
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