VirtualBox

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

Last change on this file was 98103, checked in by vboxsync, 16 months ago

Copyright year updates by scm.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use