VirtualBox

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

最後變更 在這個檔案從92776是 92776,由 vboxsync 提交於 3 年 前

IPRT/r3/posix: Implemented RTSemEventWaitEx. bugref:10138

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette