VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/linux/semevent-linux.cpp@ 92780

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

IPRT/semevent*-linux: Share some common bits between the single-release and multiple-release linux event sempahore code. Freshened up the latter a bit. bugref:10138

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Id Revision
檔案大小: 21.8 KB
 
1/* $Id: semevent-linux.cpp 92779 2021-12-07 09:45:53Z vboxsync $ */
2/** @file
3 * IPRT - Event Semaphore, Linux (2.6.0 and later).
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#include <features.h>
28#if __GLIBC_PREREQ(2,6) && !defined(IPRT_WITH_FUTEX_BASED_SEMS)
29
30/*
31 * glibc 2.6 fixed a serious bug in the mutex implementation. We wrote this
32 * linux specific event semaphores code in order to work around the bug. We
33 * will fall back on the pthread-based implementation if glibc is known to
34 * contain the bug fix.
35 *
36 * The external reference to epoll_pwait is a hack which prevents that we link
37 * against glibc < 2.6.
38 */
39# include "../posix/semevent-posix.cpp"
40__asm__ (".global epoll_pwait");
41
42#else /* glibc < 2.6 */
43
44
45/*********************************************************************************************************************************
46* Header Files *
47*********************************************************************************************************************************/
48#include <iprt/semaphore.h>
49#include "internal/iprt.h"
50
51#include <iprt/asm.h>
52#include <iprt/assert.h>
53#include <iprt/err.h>
54#include <iprt/lockvalidator.h>
55#include <iprt/mem.h>
56#include <iprt/time.h>
57#include "internal/magics.h"
58#include "internal/mem.h"
59#include "internal/strict.h"
60
61#include <errno.h>
62#include <limits.h>
63#include <pthread.h>
64#include <unistd.h>
65#include <sys/time.h>
66#include <sys/syscall.h>
67
68#include "semwait-linux.h"
69
70
71/*********************************************************************************************************************************
72* Structures and Typedefs *
73*********************************************************************************************************************************/
74/**
75 * Linux (single wakup) event semaphore.
76 */
77struct RTSEMEVENTINTERNAL
78{
79 /** Magic value. */
80 intptr_t volatile iMagic;
81 /** The futex state variable.
82 * 0 means not signalled.
83 1 means signalled. */
84 uint32_t volatile fSignalled;
85 /** The number of waiting threads */
86 int32_t volatile cWaiters;
87#ifdef RTSEMEVENT_STRICT
88 /** Signallers. */
89 RTLOCKVALRECSHRD Signallers;
90 /** Indicates that lock validation should be performed. */
91 bool volatile fEverHadSignallers;
92#endif
93 /** The creation flags. */
94 uint32_t fFlags;
95};
96
97
98/*********************************************************************************************************************************
99* Global Variables *
100*********************************************************************************************************************************/
101/** Whether we can use FUTEX_WAIT_BITSET. */
102static int volatile g_fCanUseWaitBitSet = -1;
103
104
105
106
107RTDECL(int) RTSemEventCreate(PRTSEMEVENT phEventSem)
108{
109 return RTSemEventCreateEx(phEventSem, 0 /*fFlags*/, NIL_RTLOCKVALCLASS, NULL);
110}
111
112
113RTDECL(int) RTSemEventCreateEx(PRTSEMEVENT phEventSem, uint32_t fFlags, RTLOCKVALCLASS hClass, const char *pszNameFmt, ...)
114{
115 AssertReturn(!(fFlags & ~(RTSEMEVENT_FLAGS_NO_LOCK_VAL | RTSEMEVENT_FLAGS_BOOTSTRAP_HACK)), VERR_INVALID_PARAMETER);
116 Assert(!(fFlags & RTSEMEVENT_FLAGS_BOOTSTRAP_HACK) || (fFlags & RTSEMEVENT_FLAGS_NO_LOCK_VAL));
117
118 /*
119 * Make sure we know whether FUTEX_WAIT_BITSET works.
120 */
121 rtSemLinuxCheckForFutexWaitBitSet(&g_fCanUseWaitBitSet);
122#if defined(DEBUG_bird) && !defined(IN_GUEST)
123 Assert(g_fCanUseWaitBitSet == true);
124#endif
125
126 /*
127 * Allocate semaphore handle.
128 */
129 struct RTSEMEVENTINTERNAL *pThis;
130 if (!(fFlags & RTSEMEVENT_FLAGS_BOOTSTRAP_HACK))
131 pThis = (struct RTSEMEVENTINTERNAL *)RTMemAlloc(sizeof(struct RTSEMEVENTINTERNAL));
132 else
133 pThis = (struct RTSEMEVENTINTERNAL *)rtMemBaseAlloc(sizeof(struct RTSEMEVENTINTERNAL));
134 if (pThis)
135 {
136 pThis->iMagic = RTSEMEVENT_MAGIC;
137 pThis->cWaiters = 0;
138 pThis->fSignalled = 0;
139 pThis->fFlags = fFlags;
140#ifdef RTSEMEVENT_STRICT
141 if (!pszNameFmt)
142 {
143 static uint32_t volatile s_iSemEventAnon = 0;
144 RTLockValidatorRecSharedInit(&pThis->Signallers, hClass, RTLOCKVAL_SUB_CLASS_ANY, pThis,
145 true /*fSignaller*/, !(fFlags & RTSEMEVENT_FLAGS_NO_LOCK_VAL),
146 "RTSemEvent-%u", ASMAtomicIncU32(&s_iSemEventAnon) - 1);
147 }
148 else
149 {
150 va_list va;
151 va_start(va, pszNameFmt);
152 RTLockValidatorRecSharedInitV(&pThis->Signallers, hClass, RTLOCKVAL_SUB_CLASS_ANY, pThis,
153 true /*fSignaller*/, !(fFlags & RTSEMEVENT_FLAGS_NO_LOCK_VAL),
154 pszNameFmt, va);
155 va_end(va);
156 }
157 pThis->fEverHadSignallers = false;
158#else
159 RT_NOREF(hClass, pszNameFmt);
160#endif
161
162 *phEventSem = pThis;
163 return VINF_SUCCESS;
164 }
165 return VERR_NO_MEMORY;
166}
167
168
169RTDECL(int) RTSemEventDestroy(RTSEMEVENT hEventSem)
170{
171 /*
172 * Validate input.
173 */
174 struct RTSEMEVENTINTERNAL *pThis = hEventSem;
175 if (pThis == NIL_RTSEMEVENT)
176 return VINF_SUCCESS;
177 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
178 AssertReturn(pThis->iMagic == RTSEMEVENT_MAGIC, VERR_INVALID_HANDLE);
179
180 /*
181 * Invalidate the semaphore and wake up anyone waiting on it.
182 */
183 ASMAtomicXchgSize(&pThis->iMagic, RTSEMEVENT_MAGIC | UINT32_C(0x80000000));
184 if (ASMAtomicXchgS32(&pThis->cWaiters, INT32_MIN / 2) > 0)
185 {
186 sys_futex(&pThis->fSignalled, FUTEX_WAKE, INT_MAX, NULL, NULL, 0);
187 usleep(1000);
188 }
189
190 /*
191 * Free the semaphore memory and be gone.
192 */
193#ifdef RTSEMEVENT_STRICT
194 RTLockValidatorRecSharedDelete(&pThis->Signallers);
195#endif
196 if (!(pThis->fFlags & RTSEMEVENT_FLAGS_BOOTSTRAP_HACK))
197 RTMemFree(pThis);
198 else
199 rtMemBaseFree(pThis);
200 return VINF_SUCCESS;
201}
202
203
204RTDECL(int) RTSemEventSignal(RTSEMEVENT hEventSem)
205{
206 /*
207 * Validate input.
208 */
209 struct RTSEMEVENTINTERNAL *pThis = hEventSem;
210 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
211 AssertReturn(pThis->iMagic == RTSEMEVENT_MAGIC, VERR_INVALID_HANDLE);
212
213#ifdef RTSEMEVENT_STRICT
214 if (pThis->fEverHadSignallers)
215 {
216 int rc9 = RTLockValidatorRecSharedCheckSignaller(&pThis->Signallers, NIL_RTTHREAD);
217 if (RT_FAILURE(rc9))
218 return rc9;
219 }
220#endif
221
222 ASMAtomicWriteU32(&pThis->fSignalled, 1);
223 if (ASMAtomicReadS32(&pThis->cWaiters) < 1)
224 return VINF_SUCCESS;
225
226 /* somebody is waiting, try wake up one of them. */
227 long cWoken = sys_futex(&pThis->fSignalled, FUTEX_WAKE, 1, NULL, NULL, 0);
228 if (RT_LIKELY(cWoken >= 0))
229 return VINF_SUCCESS;
230
231 if (RT_UNLIKELY(pThis->iMagic != RTSEMEVENT_MAGIC))
232 return VERR_SEM_DESTROYED;
233
234 return VERR_INVALID_PARAMETER;
235}
236
237
238/**
239 * Performs an indefinite wait on the event.
240 */
241static int rtSemEventLinuxWaitIndefinite(struct RTSEMEVENTINTERNAL *pThis, uint32_t fFlags, PCRTLOCKVALSRCPOS pSrcPos)
242{
243 RT_NOREF_PV(pSrcPos);
244
245 /*
246 * Quickly check whether it's signaled and there are no other waiters.
247 */
248 uint32_t cWaiters = ASMAtomicIncS32(&pThis->cWaiters);
249 if ( cWaiters == 1
250 && ASMAtomicCmpXchgU32(&pThis->fSignalled, 0, 1))
251 {
252 ASMAtomicDecS32(&pThis->cWaiters);
253 return VINF_SUCCESS;
254 }
255
256 /*
257 * The wait loop.
258 */
259#ifdef RTSEMEVENT_STRICT
260 RTTHREAD hThreadSelf = !(pThis->fFlags & RTSEMEVENT_FLAGS_BOOTSTRAP_HACK)
261 ? RTThreadSelfAutoAdopt()
262 : RTThreadSelf();
263#else
264 RTTHREAD hThreadSelf = RTThreadSelf();
265#endif
266 int rc = VINF_SUCCESS;
267 for (;;)
268 {
269#ifdef RTSEMEVENT_STRICT
270 if (pThis->fEverHadSignallers)
271 {
272 rc = RTLockValidatorRecSharedCheckBlocking(&pThis->Signallers, hThreadSelf, pSrcPos, false,
273 RT_INDEFINITE_WAIT, RTTHREADSTATE_EVENT, true);
274 if (RT_FAILURE(rc))
275 break;
276 }
277#endif
278 RTThreadBlocking(hThreadSelf, RTTHREADSTATE_EVENT, true);
279 long lrc = sys_futex(&pThis->fSignalled, FUTEX_WAIT, 0, NULL /*pTimeout*/, NULL, 0);
280 RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_EVENT);
281 if (RT_UNLIKELY(pThis->iMagic != RTSEMEVENT_MAGIC))
282 {
283 rc = VERR_SEM_DESTROYED;
284 break;
285 }
286
287 if (RT_LIKELY(lrc == 0 || lrc == -EWOULDBLOCK))
288 {
289 /* successful wakeup or fSignalled > 0 in the meantime */
290 if (ASMAtomicCmpXchgU32(&pThis->fSignalled, 0, 1))
291 break;
292 }
293 else if (lrc == -ETIMEDOUT)
294 {
295 rc = VERR_TIMEOUT;
296 break;
297 }
298 else if (lrc == -EINTR)
299 {
300 if (fFlags & RTSEMWAIT_FLAGS_NORESUME)
301 {
302 rc = VERR_INTERRUPTED;
303 break;
304 }
305 }
306 else
307 {
308 /* this shouldn't happen! */
309 AssertMsgFailed(("rc=%ld errno=%d\n", lrc, errno));
310 rc = RTErrConvertFromErrno(lrc);
311 break;
312 }
313 }
314
315 ASMAtomicDecS32(&pThis->cWaiters);
316 return rc;
317}
318
319
320static int rtSemEventLinuxWaitPoll(struct RTSEMEVENTINTERNAL *pThis)
321{
322 /*
323 * What we do here is isn't quite fair to anyone else waiting on it, however
324 * it might not be as bad as all that for callers making repeated poll calls
325 * because they cannot block, as that would be a virtual wait but without the
326 * chance of a permanept queue position. So, I hope we can live with this.
327 */
328 if (ASMAtomicCmpXchgU32(&pThis->fSignalled, 0, 1))
329 return VINF_SUCCESS;
330 return VERR_TIMEOUT;
331}
332
333
334static int rtSemEventLinuxWaitTimed(struct RTSEMEVENTINTERNAL *pThis, uint32_t fFlags,
335 uint64_t uTimeout, PCRTLOCKVALSRCPOS pSrcPos)
336{
337 RT_NOREF_PV(pSrcPos);
338
339 /*
340 * Convert the timeout value.
341 */
342 int iWaitOp;
343 uint32_t uWaitVal3;
344 timespec TsTimeout;
345 uint64_t uAbsTimeout = uTimeout; /* Note! only relevant for relative waits (FUTEX_WAIT). */
346 if (fFlags & RTSEMWAIT_FLAGS_RELATIVE)
347 {
348 if (!uTimeout)
349 return rtSemEventLinuxWaitPoll(pThis);
350
351 if (fFlags & RTSEMWAIT_FLAGS_MILLISECS)
352 {
353 if ( sizeof(TsTimeout.tv_sec) >= sizeof(uint64_t)
354 || uTimeout < (uint64_t)UINT32_MAX * RT_MS_1SEC)
355 {
356 TsTimeout.tv_sec = uTimeout / RT_MS_1SEC;
357 TsTimeout.tv_nsec = (uTimeout % RT_MS_1SEC) & RT_NS_1MS;
358 uAbsTimeout *= RT_NS_1MS;
359 }
360 else
361 return rtSemEventLinuxWaitIndefinite(pThis, fFlags, pSrcPos);
362 }
363 else
364 {
365 Assert(fFlags & RTSEMWAIT_FLAGS_NANOSECS);
366 if ( sizeof(TsTimeout.tv_sec) >= sizeof(uint64_t)
367 || uTimeout < (uint64_t)UINT32_MAX * RT_NS_1SEC)
368 {
369 TsTimeout.tv_sec = uTimeout / RT_NS_1SEC;
370 TsTimeout.tv_nsec = uTimeout % RT_NS_1SEC;
371 }
372 else
373 return rtSemEventLinuxWaitIndefinite(pThis, fFlags, pSrcPos);
374 }
375
376 if (fFlags & RTSEMWAIT_FLAGS_RESUME)
377 uAbsTimeout += RTTimeNanoTS();
378
379 iWaitOp = FUTEX_WAIT;
380 uWaitVal3 = 0;
381 }
382 else
383 {
384 /* Absolute deadline: */
385 Assert(fFlags & RTSEMWAIT_FLAGS_ABSOLUTE);
386 if (g_fCanUseWaitBitSet == true)
387 {
388 if (fFlags & RTSEMWAIT_FLAGS_MILLISECS)
389 {
390 if ( sizeof(TsTimeout.tv_sec) >= sizeof(uint64_t)
391 || uTimeout < (uint64_t)UINT32_MAX * RT_MS_1SEC)
392 {
393 TsTimeout.tv_sec = uTimeout / RT_MS_1SEC;
394 TsTimeout.tv_nsec = (uTimeout % RT_MS_1SEC) & RT_NS_1MS;
395 }
396 else
397 return rtSemEventLinuxWaitIndefinite(pThis, fFlags, pSrcPos);
398 }
399 else
400 {
401 Assert(fFlags & RTSEMWAIT_FLAGS_NANOSECS);
402 if ( sizeof(TsTimeout.tv_sec) >= sizeof(uint64_t)
403 || uTimeout < (uint64_t)UINT32_MAX * RT_NS_1SEC)
404 {
405 TsTimeout.tv_sec = uTimeout / RT_NS_1SEC;
406 TsTimeout.tv_nsec = uTimeout % RT_NS_1SEC;
407 }
408 else
409 return rtSemEventLinuxWaitIndefinite(pThis, fFlags, pSrcPos);
410 }
411 iWaitOp = FUTEX_WAIT_BITSET;
412 uWaitVal3 = UINT32_MAX;
413 }
414 else
415 {
416 /* Recalculate it as an relative timeout: */
417 if (fFlags & RTSEMWAIT_FLAGS_MILLISECS)
418 {
419 if (uTimeout < UINT64_MAX / RT_NS_1MS)
420 uAbsTimeout = uTimeout *= RT_NS_1MS;
421 else
422 return rtSemEventLinuxWaitIndefinite(pThis, fFlags, pSrcPos);
423 }
424
425 uint64_t const u64Now = RTTimeNanoTS();
426 if (u64Now < uTimeout)
427 uTimeout -= u64Now;
428 else
429 return rtSemEventLinuxWaitPoll(pThis);
430
431 if ( sizeof(TsTimeout.tv_sec) >= sizeof(uint64_t)
432 || uTimeout < (uint64_t)UINT32_MAX * RT_NS_1SEC)
433 {
434 TsTimeout.tv_sec = uTimeout / RT_NS_1SEC;
435 TsTimeout.tv_nsec = uTimeout % RT_NS_1SEC;
436 }
437 else
438 return rtSemEventLinuxWaitIndefinite(pThis, fFlags, pSrcPos);
439
440 iWaitOp = FUTEX_WAIT;
441 uWaitVal3 = 0;
442 }
443 }
444
445 /*
446 * Quickly check whether it's signaled and there are no other waiters.
447 */
448 uint32_t cWaiters = ASMAtomicIncS32(&pThis->cWaiters);
449 if ( cWaiters == 1
450 && ASMAtomicCmpXchgU32(&pThis->fSignalled, 0, 1))
451 {
452 ASMAtomicDecS32(&pThis->cWaiters);
453 return VINF_SUCCESS;
454 }
455
456 /*
457 * The wait loop.
458 */
459#ifdef RTSEMEVENT_STRICT
460 RTTHREAD hThreadSelf = !(pThis->fFlags & RTSEMEVENT_FLAGS_BOOTSTRAP_HACK)
461 ? RTThreadSelfAutoAdopt()
462 : RTThreadSelf();
463#else
464 RTTHREAD hThreadSelf = RTThreadSelf();
465#endif
466 int rc = VINF_SUCCESS;
467 for (;;)
468 {
469#ifdef RTSEMEVENT_STRICT
470 if (pThis->fEverHadSignallers)
471 {
472 rc = RTLockValidatorRecSharedCheckBlocking(&pThis->Signallers, hThreadSelf, pSrcPos, false,
473 iWaitOp == FUTEX_WAIT ? uTimeout / RT_NS_1MS : RT_MS_1HOUR /*whatever*/,
474 RTTHREADSTATE_EVENT, true);
475 if (RT_FAILURE(rc))
476 break;
477 }
478#endif
479 RTThreadBlocking(hThreadSelf, RTTHREADSTATE_EVENT, true);
480 long lrc = sys_futex(&pThis->fSignalled, iWaitOp, 0, &TsTimeout, NULL, uWaitVal3);
481 RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_EVENT);
482 if (RT_UNLIKELY(pThis->iMagic != RTSEMEVENT_MAGIC))
483 {
484 rc = VERR_SEM_DESTROYED;
485 break;
486 }
487
488 if (RT_LIKELY(lrc == 0 || lrc == -EWOULDBLOCK))
489 {
490 /* successful wakeup or fSignalled > 0 in the meantime */
491 if (ASMAtomicCmpXchgU32(&pThis->fSignalled, 0, 1))
492 break;
493 }
494 else if (lrc == -ETIMEDOUT)
495 {
496 rc = VERR_TIMEOUT;
497 break;
498 }
499 else if (lrc == -EINTR)
500 {
501 if (fFlags & RTSEMWAIT_FLAGS_NORESUME)
502 {
503 rc = VERR_INTERRUPTED;
504 break;
505 }
506 }
507 else
508 {
509 /* this shouldn't happen! */
510 AssertMsgFailed(("rc=%ld errno=%d\n", lrc, errno));
511 rc = RTErrConvertFromErrno(lrc);
512 break;
513 }
514
515 /* adjust the relative timeout */
516 if (iWaitOp == FUTEX_WAIT)
517 {
518 int64_t i64Diff = uAbsTimeout - RTTimeSystemNanoTS();
519 if (i64Diff < 1000)
520 {
521 rc = VERR_TIMEOUT;
522 break;
523 }
524 TsTimeout.tv_sec = (uint64_t)i64Diff / RT_NS_1SEC;
525 TsTimeout.tv_nsec = (uint64_t)i64Diff % RT_NS_1SEC;
526 }
527 }
528
529 ASMAtomicDecS32(&pThis->cWaiters);
530 return rc;
531}
532
533
534/**
535 * Internal wait worker function.
536 */
537DECLINLINE(int) rtSemEventLinuxWait(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout, PCRTLOCKVALSRCPOS pSrcPos)
538{
539 /*
540 * Validate input.
541 */
542 struct RTSEMEVENTINTERNAL *pThis = hEventSem;
543 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
544 uint32_t fSignalled = pThis->fSignalled;
545 AssertReturn(fSignalled == false || fSignalled == true, VERR_INVALID_HANDLE);
546 AssertReturn(RTSEMWAIT_FLAGS_ARE_VALID(fFlags), VERR_INVALID_PARAMETER);
547
548 /*
549 * Timed or indefinite wait?
550 */
551 if (fFlags & RTSEMWAIT_FLAGS_INDEFINITE)
552 return rtSemEventLinuxWaitIndefinite(pThis, fFlags, pSrcPos);
553 return rtSemEventLinuxWaitTimed(hEventSem, fFlags, uTimeout, pSrcPos);
554}
555
556
557RTDECL(int) RTSemEventWait(RTSEMEVENT hEventSem, RTMSINTERVAL cMillies)
558{
559 int rc;
560#ifndef RTSEMEVENT_STRICT
561 if (cMillies == RT_INDEFINITE_WAIT)
562 rc = rtSemEventLinuxWait(hEventSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_INDEFINITE, 0, NULL);
563 else
564 rc = rtSemEventLinuxWait(hEventSem, RTSEMWAIT_FLAGS_RESUME | 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 = rtSemEventLinuxWait(hEventSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_INDEFINITE, 0, &SrcPos);
570 else
571 rc = rtSemEventLinuxWait(hEventSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_MILLISECS,
572 cMillies, &SrcPos);
573#endif
574 Assert(rc != VERR_INTERRUPTED);
575 return rc;
576}
577
578
579RTDECL(int) RTSemEventWaitNoResume(RTSEMEVENT hEventSem, RTMSINTERVAL cMillies)
580{
581 int rc;
582#ifndef RTSEMEVENT_STRICT
583 if (cMillies == RT_INDEFINITE_WAIT)
584 rc = rtSemEventLinuxWait(hEventSem, RTSEMWAIT_FLAGS_NORESUME | RTSEMWAIT_FLAGS_INDEFINITE, 0, NULL);
585 else
586 rc = rtSemEventLinuxWait(hEventSem, RTSEMWAIT_FLAGS_NORESUME | RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_MILLISECS,
587 cMillies, NULL);
588#else
589 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
590 if (cMillies == RT_INDEFINITE_WAIT)
591 rc = rtSemEventLinuxWait(hEventSem, RTSEMWAIT_FLAGS_NORESUME | RTSEMWAIT_FLAGS_INDEFINITE, 0, &SrcPos);
592 else
593 rc = rtSemEventLinuxWait(hEventSem, RTSEMWAIT_FLAGS_NORESUME | RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_MILLISECS,
594 cMillies, &SrcPos);
595#endif
596 Assert(rc != VERR_INTERRUPTED);
597 return rc;
598}
599
600
601RTDECL(int) RTSemEventWaitEx(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout)
602{
603#ifndef RTSEMEVENT_STRICT
604 return rtSemEventLinuxWait(hEventSem, fFlags, uTimeout, NULL);
605#else
606 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
607 return rtSemEventLinuxWait(hEventSem, fFlags, uTimeout, &SrcPos);
608#endif
609}
610
611
612RTDECL(int) RTSemEventWaitExDebug(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout,
613 RTHCUINTPTR uId, RT_SRC_POS_DECL)
614{
615 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
616 return rtSemEventLinuxWait(hEventSem, fFlags, uTimeout, &SrcPos);
617}
618
619
620RTDECL(uint32_t) RTSemEventGetResolution(void)
621{
622 /** @todo we have 1ns parameter resolution, but need to verify that this is what
623 * the kernel actually will use when setting the timer. Most likely
624 * it's rounded a little, but hopefully not to a multiple of HZ. */
625 return 1;
626}
627
628
629RTDECL(void) RTSemEventSetSignaller(RTSEMEVENT hEventSem, RTTHREAD hThread)
630{
631#ifdef RTSEMEVENT_STRICT
632 struct RTSEMEVENTINTERNAL *pThis = hEventSem;
633 AssertPtrReturnVoid(pThis);
634 AssertReturnVoid(pThis->iMagic == RTSEMEVENT_MAGIC);
635
636 ASMAtomicWriteBool(&pThis->fEverHadSignallers, true);
637 RTLockValidatorRecSharedResetOwner(&pThis->Signallers, hThread, NULL);
638#else
639 RT_NOREF(hEventSem, hThread);
640#endif
641}
642
643
644RTDECL(void) RTSemEventAddSignaller(RTSEMEVENT hEventSem, RTTHREAD hThread)
645{
646#ifdef RTSEMEVENT_STRICT
647 struct RTSEMEVENTINTERNAL *pThis = hEventSem;
648 AssertPtrReturnVoid(pThis);
649 AssertReturnVoid(pThis->iMagic == RTSEMEVENT_MAGIC);
650
651 ASMAtomicWriteBool(&pThis->fEverHadSignallers, true);
652 RTLockValidatorRecSharedAddOwner(&pThis->Signallers, hThread, NULL);
653#else
654 RT_NOREF(hEventSem, hThread);
655#endif
656}
657
658
659RTDECL(void) RTSemEventRemoveSignaller(RTSEMEVENT hEventSem, RTTHREAD hThread)
660{
661#ifdef RTSEMEVENT_STRICT
662 struct RTSEMEVENTINTERNAL *pThis = hEventSem;
663 AssertPtrReturnVoid(pThis);
664 AssertReturnVoid(pThis->iMagic == RTSEMEVENT_MAGIC);
665
666 RTLockValidatorRecSharedRemoveOwner(&pThis->Signallers, hThread);
667#else
668 RT_NOREF(hEventSem, hThread);
669#endif
670}
671
672#endif /* glibc < 2.6 || IPRT_WITH_FUTEX_BASED_SEMS */
673
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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