~ubuntu-branches/ubuntu/raring/virtualbox-ose/raring

« back to all changes in this revision

Viewing changes to src/VBox/Runtime/r0drv/solaris/semeventmulti-r0drv-solaris.c

  • Committer: Bazaar Package Importer
  • Author(s): Felix Geyer
  • Date: 2011-01-30 23:27:25 UTC
  • mfrom: (0.3.12 upstream)
  • Revision ID: james.westby@ubuntu.com-20110130232725-2ouajjd2ggdet0zd
Tags: 4.0.2-dfsg-1ubuntu1
* Merge from Debian unstable, remaining changes:
  - Add Apport hook.
    - debian/virtualbox-ose.files/source_virtualbox-ose.py
    - debian/virtualbox-ose.install
  - Drop *-source packages.
* Drop ubuntu-01-fix-build-gcc45.patch, fixed upstream.
* Drop ubuntu-02-as-needed.patch, added to the Debian package.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* $Id: semeventmulti-r0drv-solaris.c $ */
 
1
/* $Id: semeventmulti-r0drv-solaris.c 33155 2010-10-15 12:07:44Z vboxsync $ */
2
2
/** @file
3
3
 * IPRT - Multiple Release Event Semaphores, Ring-0 Driver, Solaris.
4
4
 */
5
5
 
6
6
/*
7
 
 * Copyright (C) 2006-2007 Oracle Corporation
 
7
 * Copyright (C) 2006-2010 Oracle Corporation
8
8
 *
9
9
 * This file is part of VirtualBox Open Source Edition (OSE), as
10
10
 * available from http://www.virtualbox.org. This file is free software;
38
38
# include <iprt/asm-amd64-x86.h>
39
39
#endif
40
40
#include <iprt/err.h>
 
41
#include <iprt/lockvalidator.h>
41
42
#include <iprt/mem.h>
42
43
#include <iprt/mp.h>
43
44
#include <iprt/thread.h>
 
45
#include <iprt/time.h>
44
46
#include "internal/magics.h"
 
47
#include "semeventwait-r0drv-solaris.h"
 
48
 
 
49
 
 
50
/*******************************************************************************
 
51
*   Defined Constants And Macros                                               *
 
52
*******************************************************************************/
 
53
/** @name fStateAndGen values
 
54
 * @{ */
 
55
/** The state bit number. */
 
56
#define RTSEMEVENTMULTISOL_STATE_BIT        0
 
57
/** The state mask. */
 
58
#define RTSEMEVENTMULTISOL_STATE_MASK       RT_BIT_32(RTSEMEVENTMULTISOL_STATE_BIT)
 
59
/** The generation mask. */
 
60
#define RTSEMEVENTMULTISOL_GEN_MASK         ~RTSEMEVENTMULTISOL_STATE_MASK
 
61
/** The generation shift. */
 
62
#define RTSEMEVENTMULTISOL_GEN_SHIFT        1
 
63
/** The initial variable value. */
 
64
#define RTSEMEVENTMULTISOL_STATE_GEN_INIT   UINT32_C(0xfffffffc)
 
65
/** @}  */
45
66
 
46
67
 
47
68
/*******************************************************************************
48
69
*   Structures and Typedefs                                                    *
49
70
*******************************************************************************/
50
71
/**
51
 
 * FreeBSD multiple release event semaphore.
 
72
 * Solaris multiple release event semaphore.
52
73
 */
53
74
typedef struct RTSEMEVENTMULTIINTERNAL
54
75
{
55
76
    /** Magic value (RTSEMEVENTMULTI_MAGIC). */
56
77
    uint32_t volatile   u32Magic;
57
 
    /** The number of waiting threads. */
58
 
    uint32_t volatile   cWaiters;
59
 
    /** Set if the event object is signaled. */
60
 
    uint8_t volatile    fSignaled;
61
 
    /** The number of threads in the process of waking up. */
62
 
    uint32_t volatile   cWaking;
 
78
    /** The number of references. */
 
79
    uint32_t volatile   cRefs;
 
80
    /** The object state bit and generation counter.
 
81
     * The generation counter is incremented every time the object is
 
82
     * signalled. */
 
83
    uint32_t volatile   fStateAndGen;
63
84
    /** The Solaris mutex protecting this structure and pairing up the with the cv. */
64
85
    kmutex_t            Mtx;
65
86
    /** The Solaris condition variable. */
85
106
    PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)RTMemAlloc(sizeof(*pThis));
86
107
    if (pThis)
87
108
    {
88
 
        pThis->u32Magic = RTSEMEVENTMULTI_MAGIC;
89
 
        pThis->cWaiters = 0;
90
 
        pThis->cWaking = 0;
91
 
        pThis->fSignaled = 0;
 
109
        pThis->u32Magic     = RTSEMEVENTMULTI_MAGIC;
 
110
        pThis->cRefs        = 1;
 
111
        pThis->fStateAndGen = RTSEMEVENTMULTISOL_STATE_GEN_INIT;
92
112
        mutex_init(&pThis->Mtx, "IPRT Multiple Release Event Semaphore", MUTEX_DRIVER, (void *)ipltospl(DISP_LEVEL));
93
113
        cv_init(&pThis->Cnd, "IPRT CV", CV_DRIVER, NULL);
94
114
 
99
119
}
100
120
 
101
121
 
 
122
/**
 
123
 * Retain a reference to the semaphore.
 
124
 *
 
125
 * @param   pThis       The semaphore.
 
126
 */
 
127
DECLINLINE(void) rtR0SemEventMultiSolRetain(PRTSEMEVENTMULTIINTERNAL pThis)
 
128
{
 
129
    uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
 
130
    Assert(cRefs && cRefs < 100000);
 
131
}
 
132
 
 
133
 
 
134
/**
 
135
 * Destructor that is called when cRefs == 0.
 
136
 *
 
137
 * @param   pThis       The instance to destroy.
 
138
 */
 
139
static void rtSemEventMultiDtor(PRTSEMEVENTMULTIINTERNAL pThis)
 
140
{
 
141
    Assert(pThis->u32Magic != RTSEMEVENTMULTI_MAGIC);
 
142
    cv_destroy(&pThis->Cnd);
 
143
    mutex_destroy(&pThis->Mtx);
 
144
    RTMemFree(pThis);
 
145
}
 
146
 
 
147
 
 
148
/**
 
149
 * Release a reference, destroy the thing if necessary.
 
150
 *
 
151
 * @param   pThis       The semaphore.
 
152
 */
 
153
DECLINLINE(void) rtR0SemEventMultiSolRelease(PRTSEMEVENTMULTIINTERNAL pThis)
 
154
{
 
155
    if (RT_UNLIKELY(ASMAtomicDecU32(&pThis->cRefs) == 0))
 
156
        rtSemEventMultiDtor(pThis);
 
157
}
 
158
 
 
159
 
 
160
 
102
161
RTDECL(int)  RTSemEventMultiDestroy(RTSEMEVENTMULTI hEventMultiSem)
103
162
{
104
163
    PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem;
106
165
        return VINF_SUCCESS;
107
166
    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
108
167
    AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic), VERR_INVALID_HANDLE);
109
 
    RT_ASSERT_INTS_ON();
110
 
 
111
 
    mutex_enter(&pThis->Mtx);
112
 
    ASMAtomicIncU32(&pThis->u32Magic); /* make the handle invalid */
113
 
    if (pThis->cWaiters > 0)
114
 
    {
115
 
        /* abort waiting thread, last man cleans up. */
116
 
        ASMAtomicXchgU32(&pThis->cWaking, pThis->cWaking + pThis->cWaiters);
117
 
        cv_broadcast(&pThis->Cnd);
118
 
        mutex_exit(&pThis->Mtx);
119
 
    }
120
 
    else if (pThis->cWaking)
121
 
        /* the last waking thread is gonna do the cleanup */
122
 
        mutex_exit(&pThis->Mtx);
123
 
    else
124
 
    {
125
 
        mutex_exit(&pThis->Mtx);
126
 
        cv_destroy(&pThis->Cnd);
127
 
        mutex_destroy(&pThis->Mtx);
128
 
        RTMemFree(pThis);
129
 
    }
130
 
 
131
 
    return VINF_SUCCESS;
132
 
}
133
 
 
134
 
 
135
 
RTDECL(int)  RTSemEventMultiSignal(RTSEMEVENTMULTI hEventMultiSem)
136
 
{
137
 
    PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem;
138
 
    RT_ASSERT_PREEMPT_CPUID_VAR();
139
 
 
140
 
    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
141
 
    AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC,
142
 
                    ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
143
 
                    VERR_INVALID_HANDLE);
144
 
    RT_ASSERT_INTS_ON();
145
 
 
146
 
    /*
147
 
     * If we're in interrupt context we need to unpin the underlying current
148
 
     * thread as this could lead to a deadlock (see #4259 for the full explanation)
149
 
     *
150
 
     * Note! See remarks about preemption in RTSemEventSignal.
151
 
     */
152
 
    int fAcquired = mutex_tryenter(&pThis->Mtx);
153
 
    if (!fAcquired)
154
 
    {
155
 
        if (curthread->t_intr && getpil() < DISP_LEVEL)
156
 
        {
157
 
            RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER;
158
 
            RTThreadPreemptDisable(&PreemptState);
159
 
            preempt();
160
 
            RTThreadPreemptRestore(&PreemptState);
161
 
        }
162
 
        mutex_enter(&pThis->Mtx);
163
 
    }
164
 
 
165
 
    ASMAtomicXchgU8(&pThis->fSignaled, true);
166
 
    if (pThis->cWaiters > 0)
167
 
    {
168
 
        ASMAtomicXchgU32(&pThis->cWaking, pThis->cWaking + pThis->cWaiters);
169
 
        ASMAtomicXchgU32(&pThis->cWaiters, 0);
170
 
        cv_broadcast(&pThis->Cnd);
171
 
    }
172
 
 
173
 
    mutex_exit(&pThis->Mtx);
174
 
 
175
 
    RT_ASSERT_PREEMPT_CPUID();
176
 
    return VINF_SUCCESS;
177
 
}
178
 
 
179
 
 
180
 
RTDECL(int)  RTSemEventMultiReset(RTSEMEVENTMULTI hEventMultiSem)
181
 
{
182
 
    PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem;
183
 
    RT_ASSERT_PREEMPT_CPUID_VAR();
184
 
 
185
 
    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
186
 
    AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC,
187
 
                    ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
188
 
                    VERR_INVALID_HANDLE);
189
 
    RT_ASSERT_INTS_ON();
190
 
 
191
 
    /*
192
 
     * If we're in interrupt context we need to unpin the underlying current
193
 
     * thread as this could lead to a deadlock (see #4259 for the full explanation)
194
 
     *
195
 
     * Note! See remarks about preemption in RTSemEventSignal.
196
 
     */
197
 
    int fAcquired = mutex_tryenter(&pThis->Mtx);
198
 
    if (!fAcquired)
199
 
    {
200
 
        if (curthread->t_intr && getpil() < DISP_LEVEL)
201
 
        {
202
 
            RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER;
203
 
            RTThreadPreemptDisable(&PreemptState);
204
 
            preempt();
205
 
            RTThreadPreemptRestore(&PreemptState);
206
 
        }
207
 
        mutex_enter(&pThis->Mtx);
208
 
    }
209
 
 
210
 
    ASMAtomicXchgU8(&pThis->fSignaled, false);
211
 
    mutex_exit(&pThis->Mtx);
212
 
 
213
 
    RT_ASSERT_PREEMPT_CPUID();
214
 
    return VINF_SUCCESS;
215
 
}
216
 
 
217
 
 
218
 
static int rtSemEventMultiWait(RTSEMEVENTMULTI hEventMultiSem, RTMSINTERVAL cMillies, bool fInterruptible)
219
 
{
220
 
    int rc;
221
 
    PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem;
222
 
    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
223
 
    AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC,
224
 
                    ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
225
 
                    VERR_INVALID_HANDLE);
226
 
    if (cMillies)
227
 
        RT_ASSERT_PREEMPTIBLE();
228
 
 
229
 
    mutex_enter(&pThis->Mtx);
230
 
 
231
 
    if (pThis->fSignaled)
 
168
    AssertMsgReturn(pThis->cRefs > 0, ("pThis=%p cRefs=%d\n", pThis, pThis->cRefs), VERR_INVALID_HANDLE);
 
169
    RT_ASSERT_INTS_ON();
 
170
 
 
171
    mutex_enter(&pThis->Mtx);
 
172
 
 
173
    /* Invalidate the handle and wake up all threads that might be waiting on the semaphore. */
 
174
    Assert(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC);
 
175
    ASMAtomicWriteU32(&pThis->u32Magic, RTSEMEVENTMULTI_MAGIC_DEAD);
 
176
    ASMAtomicAndU32(&pThis->fStateAndGen, RTSEMEVENTMULTISOL_GEN_MASK);
 
177
    cv_broadcast(&pThis->Cnd);
 
178
 
 
179
    /* Drop the reference from RTSemEventMultiCreateEx. */
 
180
    mutex_exit(&pThis->Mtx);
 
181
    rtR0SemEventMultiSolRelease(pThis);
 
182
 
 
183
    return VINF_SUCCESS;
 
184
}
 
185
 
 
186
 
 
187
RTDECL(int) RTSemEventMultiSignal(RTSEMEVENTMULTI hEventMultiSem)
 
188
{
 
189
    PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem;
 
190
    RT_ASSERT_PREEMPT_CPUID_VAR();
 
191
 
 
192
    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
 
193
    AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC,
 
194
                    ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
 
195
                    VERR_INVALID_HANDLE);
 
196
    RT_ASSERT_INTS_ON();
 
197
    rtR0SemEventMultiSolRetain(pThis);
 
198
    rtR0SemSolWaitEnterMutexWithUnpinningHack(&pThis->Mtx);
 
199
    Assert(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC);
 
200
 
 
201
    /*
 
202
     * Do the job.
 
203
     */
 
204
    uint32_t fNew = ASMAtomicUoReadU32(&pThis->fStateAndGen);
 
205
    fNew += 1 << RTSEMEVENTMULTISOL_GEN_SHIFT;
 
206
    fNew |= RTSEMEVENTMULTISOL_STATE_MASK;
 
207
    ASMAtomicWriteU32(&pThis->fStateAndGen, fNew);
 
208
 
 
209
    cv_broadcast(&pThis->Cnd);
 
210
 
 
211
    mutex_exit(&pThis->Mtx);
 
212
 
 
213
    rtR0SemEventMultiSolRelease(pThis);
 
214
    RT_ASSERT_PREEMPT_CPUID();
 
215
    return VINF_SUCCESS;
 
216
}
 
217
 
 
218
 
 
219
RTDECL(int) RTSemEventMultiReset(RTSEMEVENTMULTI hEventMultiSem)
 
220
{
 
221
    PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem;
 
222
    RT_ASSERT_PREEMPT_CPUID_VAR();
 
223
 
 
224
    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
 
225
    AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC,
 
226
                    ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
 
227
                    VERR_INVALID_HANDLE);
 
228
    RT_ASSERT_INTS_ON();
 
229
 
 
230
    rtR0SemEventMultiSolRetain(pThis);
 
231
    rtR0SemSolWaitEnterMutexWithUnpinningHack(&pThis->Mtx);
 
232
    Assert(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC);
 
233
 
 
234
    /*
 
235
     * Do the job (could be done without the lock, but play safe).
 
236
     */
 
237
    ASMAtomicAndU32(&pThis->fStateAndGen, ~RTSEMEVENTMULTISOL_STATE_MASK);
 
238
 
 
239
    mutex_exit(&pThis->Mtx);
 
240
    rtR0SemEventMultiSolRelease(pThis);
 
241
 
 
242
    RT_ASSERT_PREEMPT_CPUID();
 
243
    return VINF_SUCCESS;
 
244
}
 
245
 
 
246
 
 
247
/**
 
248
 * Worker for RTSemEventMultiWaitEx and RTSemEventMultiWaitExDebug.
 
249
 *
 
250
 * @returns VBox status code.
 
251
 * @param   pThis           The event semaphore.
 
252
 * @param   fFlags          See RTSemEventMultiWaitEx.
 
253
 * @param   uTimeout        See RTSemEventMultiWaitEx.
 
254
 * @param   pSrcPos         The source code position of the wait.
 
255
 */
 
256
static int rtR0SemEventMultiSolWait(PRTSEMEVENTMULTIINTERNAL pThis, uint32_t fFlags, uint64_t uTimeout,
 
257
                                    PCRTLOCKVALSRCPOS pSrcPos)
 
258
{
 
259
    uint32_t    fOrgStateAndGen;
 
260
    int         rc;
 
261
 
 
262
    /*
 
263
     * Validate the input.
 
264
     */
 
265
    AssertPtrReturn(pThis, VERR_INVALID_PARAMETER);
 
266
    AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER);
 
267
    AssertReturn(RTSEMWAIT_FLAGS_ARE_VALID(fFlags), VERR_INVALID_PARAMETER);
 
268
    rtR0SemEventMultiSolRetain(pThis);
 
269
    mutex_enter(&pThis->Mtx); /* this could be moved down to the else, but play safe for now. */
 
270
 
 
271
    /*
 
272
     * Is the event already signalled or do we have to wait?
 
273
     */
 
274
    fOrgStateAndGen = ASMAtomicUoReadU32(&pThis->fStateAndGen);
 
275
    if (fOrgStateAndGen & RTSEMEVENTMULTISOL_STATE_MASK)
232
276
        rc = VINF_SUCCESS;
233
 
    else if (!cMillies)
234
 
        rc = VERR_TIMEOUT;
235
277
    else
236
278
    {
237
 
        ASMAtomicIncU32(&pThis->cWaiters);
238
 
 
239
279
        /*
240
 
         * Translate milliseconds into ticks and go to sleep.
 
280
         * We have to wait.
241
281
         */
242
 
        if (cMillies != RT_INDEFINITE_WAIT)
243
 
        {
244
 
            clock_t cTicks = drv_usectohz((clock_t)(cMillies * 1000L));
245
 
            clock_t cTimeout = ddi_get_lbolt();
246
 
            cTimeout += cTicks;
247
 
            if (fInterruptible)
248
 
                rc = cv_timedwait_sig(&pThis->Cnd, &pThis->Mtx, cTimeout);
249
 
            else
250
 
                rc = cv_timedwait(&pThis->Cnd, &pThis->Mtx, cTimeout);
251
 
        }
252
 
        else
253
 
        {
254
 
            if (fInterruptible)
255
 
                rc = cv_wait_sig(&pThis->Cnd, &pThis->Mtx);
256
 
            else
257
 
            {
258
 
                cv_wait(&pThis->Cnd, &pThis->Mtx);
259
 
                rc = 1;
260
 
            }
261
 
        }
262
 
        if (rc > 0)
263
 
        {
264
 
            /* Retured due to call to cv_signal() or cv_broadcast() */
265
 
            if (RT_LIKELY(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC))
266
 
            {
267
 
                rc = VINF_SUCCESS;
268
 
                ASMAtomicDecU32(&pThis->cWaking);
269
 
            }
270
 
            else
271
 
            {
272
 
                rc = VERR_SEM_DESTROYED;
273
 
                if (!ASMAtomicDecU32(&pThis->cWaking))
 
282
        RTR0SEMSOLWAIT Wait;
 
283
        rc = rtR0SemSolWaitInit(&Wait, fFlags, uTimeout);
 
284
        if (RT_SUCCESS(rc))
 
285
        {
 
286
            for (;;)
 
287
            {
 
288
                /* The destruction test. */
 
289
                if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENTMULTI_MAGIC))
 
290
                    rc = VERR_SEM_DESTROYED;
 
291
                else
274
292
                {
275
 
                    mutex_exit(&pThis->Mtx);
276
 
                    cv_destroy(&pThis->Cnd);
277
 
                    mutex_destroy(&pThis->Mtx);
278
 
                    RTMemFree(pThis);
279
 
                    return rc;
 
293
                    /* Check the exit conditions. */
 
294
                    if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENTMULTI_MAGIC))
 
295
                        rc = VERR_SEM_DESTROYED;
 
296
                    else if (ASMAtomicUoReadU32(&pThis->fStateAndGen) != fOrgStateAndGen)
 
297
                        rc = VINF_SUCCESS;
 
298
                    else if (rtR0SemSolWaitHasTimedOut(&Wait))
 
299
                        rc = VERR_TIMEOUT;
 
300
                    else if (rtR0SemSolWaitWasInterrupted(&Wait))
 
301
                        rc = VERR_INTERRUPTED;
 
302
                    else
 
303
                    {
 
304
                        /* Do the wait and then recheck the conditions. */
 
305
                        rtR0SemSolWaitDoIt(&Wait, &pThis->Cnd, &pThis->Mtx);
 
306
                        continue;
 
307
                    }
280
308
                }
 
309
                break;
281
310
            }
282
 
        }
283
 
        else if (rc == -1)
284
 
        {
285
 
            /* Returned due to timeout being reached */
286
 
            if (pThis->cWaiters > 0)
287
 
                ASMAtomicDecU32(&pThis->cWaiters);
288
 
            rc = VERR_TIMEOUT;
289
 
        }
290
 
        else
291
 
        {
292
 
            /* Returned due to pending signal */
293
 
            if (pThis->cWaiters > 0)
294
 
                ASMAtomicDecU32(&pThis->cWaiters);
295
 
            rc = VERR_INTERRUPTED;
 
311
            rtR0SemSolWaitDelete(&Wait);
296
312
        }
297
313
    }
298
314
 
299
315
    mutex_exit(&pThis->Mtx);
 
316
    rtR0SemEventMultiSolRelease(pThis);
300
317
    return rc;
301
318
}
302
319
 
303
320
 
304
 
RTDECL(int)  RTSemEventMultiWait(RTSEMEVENTMULTI hEventMultiSem, RTMSINTERVAL cMillies)
305
 
{
306
 
    return rtSemEventMultiWait(hEventMultiSem, cMillies, false /* not interruptible */);
307
 
}
308
 
 
309
 
 
310
 
RTDECL(int)  RTSemEventMultiWaitNoResume(RTSEMEVENTMULTI hEventMultiSem, RTMSINTERVAL cMillies)
311
 
{
312
 
    return rtSemEventMultiWait(hEventMultiSem, cMillies, true /* interruptible */);
 
321
 
 
322
#undef RTSemEventMultiWaitEx
 
323
RTDECL(int)  RTSemEventMultiWaitEx(RTSEMEVENTMULTI hEventMultiSem, uint32_t fFlags, uint64_t uTimeout)
 
324
{
 
325
#ifndef RTSEMEVENT_STRICT
 
326
    return rtR0SemEventMultiSolWait(hEventMultiSem, fFlags, uTimeout, NULL);
 
327
#else
 
328
    RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
 
329
    return rtR0SemEventMultiSolWait(hEventMultiSem, fFlags, uTimeout, &SrcPos);
 
330
#endif
 
331
}
 
332
 
 
333
 
 
334
RTDECL(int)  RTSemEventMultiWaitExDebug(RTSEMEVENTMULTI hEventMultiSem, uint32_t fFlags, uint64_t uTimeout,
 
335
                                        RTHCUINTPTR uId, RT_SRC_POS_DECL)
 
336
{
 
337
    RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
 
338
    return rtR0SemEventMultiSolWait(hEventMultiSem, fFlags, uTimeout, &SrcPos);
 
339
}
 
340
 
 
341
 
 
342
RTDECL(uint32_t) RTSemEventMultiGetResolution(void)
 
343
{
 
344
    return rtR0SemSolWaitGetResolution();
313
345
}
314
346