VirtualBox

Changeset 33038 in vbox for trunk/src/VBox/Runtime/r0drv/nt


Ignore:
Timestamp:
Oct 11, 2010 11:55:01 AM (14 years ago)
Author:
vboxsync
Message:

IPRT: Implemented the RTSemEvent*WaitEx* APIs for ring-0 NT.

Location:
trunk/src/VBox/Runtime/r0drv/nt
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r0drv/nt/semevent-r0drv-nt.cpp

    r28800 r33038  
    55
    66/*
    7  * Copyright (C) 2006-2007 Oracle Corporation
     7 * Copyright (C) 2006-2010 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2626
    2727
    28 
    2928/*******************************************************************************
    3029*   Header Files                                                               *
     
    3231#include "the-nt-kernel.h"
    3332#include <iprt/semaphore.h>
    34 #include <iprt/alloc.h>
     33
     34#include <iprt/asm.h>
    3535#include <iprt/assert.h>
    36 #include <iprt/asm.h>
    3736#include <iprt/err.h>
     37#include <iprt/lockvalidator.h>
     38#include <iprt/mem.h>
     39#include <iprt/time.h>
    3840
    3941#include "internal/magics.h"
     
    5052    /** Magic value (RTSEMEVENT_MAGIC). */
    5153    uint32_t volatile   u32Magic;
     54    /** Reference counter. */
     55    uint32_t volatile   cRefs;
    5256    /** The NT Event object. */
    5357    KEVENT              Event;
     
    6771
    6872    PRTSEMEVENTINTERNAL pThis = (PRTSEMEVENTINTERNAL)RTMemAlloc(sizeof(*pThis));
    69     if (!pThis)
    70         return VERR_NO_MEMORY;
    71 
    72     pThis->u32Magic = RTSEMEVENT_MAGIC;
    73     KeInitializeEvent(&pThis->Event, SynchronizationEvent, FALSE);
    74 
    75     *phEventSem = pThis;
    76     return VINF_SUCCESS;
     73    if (pThis)
     74    {
     75        pThis->u32Magic = RTSEMEVENT_MAGIC;
     76        pThis->cRefs    = 1;
     77        KeInitializeEvent(&pThis->Event, SynchronizationEvent, FALSE);
     78
     79        *phEventSem = pThis;
     80        return VINF_SUCCESS;
     81    }
     82    return VERR_NO_MEMORY;
     83}
     84
     85
     86/**
     87 * Retains a reference to the semaphore.
     88 *
     89 * @param   pThis       The semaphore to retain.
     90 */
     91DECLINLINE(void) rtR0SemEventNtRetain(PRTSEMEVENTINTERNAL pThis)
     92{
     93    uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
     94    Assert(cRefs < 100000); NOREF(cRefs);
     95}
     96
     97
     98/**
     99 * Releases a reference to the semaphore.
     100 *
     101 * @param   pThis       The semaphore to release
     102 */
     103DECLINLINE(void) rtR0SemEventNtRelease(PRTSEMEVENTINTERNAL pThis)
     104{
     105    if (ASMAtomicDecU32(&pThis->cRefs) == 0)
     106        RTMemFree(pThis);
    77107}
    78108
     
    94124    ASMAtomicIncU32(&pThis->u32Magic);
    95125    KeSetEvent(&pThis->Event, 0xfff, FALSE);
    96     RTMemFree(pThis);
     126    rtR0SemEventNtRelease(pThis);
    97127    return VINF_SUCCESS;
    98128}
    99129
    100130
    101 RTDECL(int)  RTSemEventSignal(RTSEMEVENT hEventSem)
     131RTDECL(int) RTSemEventSignal(RTSEMEVENT hEventSem)
    102132{
    103133    /*
     
    107137    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
    108138    AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), VERR_INVALID_HANDLE);
     139    rtR0SemEventNtRetain(pThis);
    109140
    110141    /*
     
    112143     */
    113144    KeSetEvent(&pThis->Event, 1, FALSE);
     145
     146    rtR0SemEventNtRelease(pThis);
    114147    return VINF_SUCCESS;
    115148}
    116149
    117150
    118 static int rtSemEventWait(RTSEMEVENT hEventSem, RTMSINTERVAL cMillies, bool fInterruptible)
     151
     152/**
     153 * Worker for RTSemEventWaitEx and RTSemEventWaitExDebug.
     154 *
     155 * @returns VBox status code.
     156 * @param   pThis           The event semaphore.
     157 * @param   fFlags          See RTSemEventWaitEx.
     158 * @param   uTimeout        See RTSemEventWaitEx.
     159 * @param   pSrcPos         The source code position of the wait.
     160 */
     161DECLINLINE(int) rtR0SemEventNtWait(PRTSEMEVENTINTERNAL pThis, uint32_t fFlags, uint64_t uTimeout,
     162                                   PCRTLOCKVALSRCPOS pSrcPos)
    119163{
    120164    /*
    121165     * Validate input.
    122166     */
    123     PRTSEMEVENTINTERNAL pThis = (PRTSEMEVENTINTERNAL)hEventSem;
    124     AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
    125     AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), VERR_INVALID_HANDLE);
     167    if (!pThis)
     168        return VERR_INVALID_PARAMETER;
     169    AssertPtrReturn(pThis, VERR_INVALID_PARAMETER);
     170    AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER);
     171    rtR0SemEventNtRetain(pThis);
     172
     173    /*
     174     * Convert the timeout to a relative one because KeWaitForSingleObject
     175     * takes system time instead of interrupt time as input for absolute
     176     * timeout specifications.  So, we're best of by giving it relative time.
     177     *
     178     * Lazy bird converts uTimeout to relative nanoseconds and then to Nt time.
     179     */
     180    if (!(fFlags & RTSEMWAIT_FLAGS_INDEFINITE))
     181    {
     182        if (fFlags & RTSEMWAIT_FLAGS_MILLISECS)
     183            uTimeout = uTimeout < UINT64_MAX / UINT32_C(1000000) * UINT32_C(1000000)
     184                     ? uTimeout * UINT32_C(1000000)
     185                     : UINT64_MAX;
     186        if (uTimeout == UINT64_MAX)
     187            fFlags |= RTSEMWAIT_FLAGS_INDEFINITE;
     188        else
     189        {
     190            if (fFlags & RTSEMWAIT_FLAGS_ABSOLUTE)
     191            {
     192                uint64_t u64Now = RTTimeSystemNanoTS();
     193                uTimeout = u64Now < uTimeout
     194                         ? uTimeout - u64Now
     195                         : 0;
     196            }
     197        }
     198    }
     199
    126200
    127201    /*
     
    130204     */
    131205    NTSTATUS        rcNt;
     206    BOOLEAN         fInterruptible = !!(fFlags & RTSEMWAIT_FLAGS_INTERRUPTIBLE);
    132207    KPROCESSOR_MODE WaitMode   = fInterruptible ? UserMode : KernelMode;
    133     if (cMillies == RT_INDEFINITE_WAIT)
     208    if (fFlags & RTSEMWAIT_FLAGS_INDEFINITE)
    134209        rcNt = KeWaitForSingleObject(&pThis->Event, Executive, WaitMode, fInterruptible, NULL);
    135210    else
    136211    {
    137212        LARGE_INTEGER Timeout;
    138         Timeout.QuadPart = -(int64_t)cMillies * 10000;
     213        Timeout.QuadPart = -(int64_t)(uTimeout / 100);
    139214        rcNt = KeWaitForSingleObject(&pThis->Event, Executive, WaitMode, fInterruptible, &Timeout);
    140215    }
    141     switch (rcNt)
    142     {
    143         case STATUS_SUCCESS:
    144             if (pThis->u32Magic == RTSEMEVENT_MAGIC)
    145                 return VINF_SUCCESS;
    146             return VERR_SEM_DESTROYED;
    147         case STATUS_ALERTED:
    148             return VERR_INTERRUPTED;
    149         case STATUS_USER_APC:
    150             return VERR_INTERRUPTED;
    151         case STATUS_TIMEOUT:
    152             return VERR_TIMEOUT;
    153         default:
    154             AssertMsgFailed(("pThis->u32Magic=%RX32 pThis=%p: wait returned %lx!\n",
    155                              pThis->u32Magic, pThis, (long)rcNt));
    156             return VERR_INTERNAL_ERROR;
    157     }
    158 }
    159 
    160 
    161 RTDECL(int)  RTSemEventWait(RTSEMEVENT hEventSem, RTMSINTERVAL cMillies)
    162 {
    163     return rtSemEventWait(hEventSem, cMillies, false /* fInterruptible */);
    164 }
    165 
    166 
    167 RTDECL(int)  RTSemEventWaitNoResume(RTSEMEVENT hEventSem, RTMSINTERVAL cMillies)
    168 {
    169     return rtSemEventWait(hEventSem, cMillies, true /* fInterruptible */);
    170 }
    171 
     216    int rc;
     217    if (pThis->u32Magic == RTSEMEVENT_MAGIC)
     218    {
     219        switch (rcNt)
     220        {
     221            case STATUS_SUCCESS:
     222                rc = VINF_SUCCESS;
     223                break;
     224            case STATUS_ALERTED:
     225                rc = VERR_INTERRUPTED;
     226                break;
     227            case STATUS_USER_APC:
     228                rc = VERR_INTERRUPTED;
     229                break;
     230            case STATUS_TIMEOUT:
     231                rc = VERR_TIMEOUT;
     232                break;
     233            default:
     234                AssertMsgFailed(("pThis->u32Magic=%RX32 pThis=%p: wait returned %lx!\n",
     235                                 pThis->u32Magic, pThis, (long)rcNt));
     236                rc = VERR_INTERNAL_ERROR_4;
     237                break;
     238        }
     239    }
     240    else
     241        rc = VERR_SEM_DESTROYED;
     242
     243    rtR0SemEventNtRelease(pThis);
     244    return rc;
     245}
     246
     247
     248#undef RTSemEventWaitEx
     249RTDECL(int)  RTSemEventWaitEx(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout)
     250{
     251#ifndef RTSEMEVENT_STRICT
     252    return rtR0SemEventNtWait(hEventSem, fFlags, uTimeout, NULL);
     253#else
     254    RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
     255    return rtR0SemEventNtWait(hEventSem, fFlags, uTimeout, &SrcPos);
     256#endif
     257}
     258
     259
     260RTDECL(int)  RTSemEventWaitExDebug(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout,
     261                                   RTHCUINTPTR uId, RT_SRC_POS_DECL)
     262{
     263    RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
     264    return rtR0SemEventNtWait(hEventSem, fFlags, uTimeout, &SrcPos);
     265}
     266
  • trunk/src/VBox/Runtime/r0drv/nt/semeventmulti-r0drv-nt.cpp

    r28800 r33038  
    55
    66/*
    7  * Copyright (C) 2006-2007 Oracle Corporation
     7 * Copyright (C) 2006-2010 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    3131#include "the-nt-kernel.h"
    3232#include <iprt/semaphore.h>
    33 #include <iprt/alloc.h>
     33
     34#include <iprt/asm.h>
    3435#include <iprt/assert.h>
    35 #include <iprt/asm.h>
    3636#include <iprt/err.h>
     37#include <iprt/lockvalidator.h>
     38#include <iprt/mem.h>
     39#include <iprt/time.h>
    3740
    3841#include "internal/magics.h"
     
    4952    /** Magic value (RTSEMEVENTMULTI_MAGIC). */
    5053    uint32_t volatile   u32Magic;
     54    /** Reference counter. */
     55    uint32_t volatile   cRefs;
    5156    /** The NT Event object. */
    5257    KEVENT              Event;
     
    7075    {
    7176        pThis->u32Magic = RTSEMEVENTMULTI_MAGIC;
     77        pThis->cRefs    = 1;
    7278        KeInitializeEvent(&pThis->Event, NotificationEvent, FALSE /* not signalled */);
    7379
     
    7682    }
    7783    return VERR_NO_MEMORY;
     84}
     85
     86
     87/**
     88 * Retains a reference to the semaphore.
     89 *
     90 * @param   pThis       The semaphore to retain.
     91 */
     92DECLINLINE(void) rtR0SemEventMultiNtRetain(PRTSEMEVENTMULTIINTERNAL pThis)
     93{
     94    uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
     95    Assert(cRefs < 100000); NOREF(cRefs);
     96}
     97
     98
     99/**
     100 * Releases a reference to the semaphore.
     101 *
     102 * @param   pThis       The semaphore to release
     103 */
     104DECLINLINE(void) rtR0SemEventMultiNtRelease(PRTSEMEVENTMULTIINTERNAL pThis)
     105{
     106    if (ASMAtomicDecU32(&pThis->cRefs) == 0)
     107        RTMemFree(pThis);
    78108}
    79109
     
    95125    ASMAtomicIncU32(&pThis->u32Magic);
    96126    KeSetEvent(&pThis->Event, 0xfff, FALSE);
    97     RTMemFree(pThis);
     127    rtR0SemEventMultiNtRelease(pThis);
    98128    return VINF_SUCCESS;
    99129}
     
    110140    AssertPtrReturn(pThis, VERR_INVALID_PARAMETER);
    111141    AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER);
     142    rtR0SemEventMultiNtRetain(pThis);
    112143
    113144    /*
     
    115146     */
    116147    KeSetEvent(&pThis->Event, 1, FALSE);
     148
     149    rtR0SemEventMultiNtRelease(pThis);
    117150    return VINF_SUCCESS;
    118151}
     
    129162    AssertPtrReturn(pThis, VERR_INVALID_PARAMETER);
    130163    AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER);
     164    rtR0SemEventMultiNtRetain(pThis);
    131165
    132166    /*
     
    134168     */
    135169    KeResetEvent(&pThis->Event);
     170
     171    rtR0SemEventMultiNtRelease(pThis);
    136172    return VINF_SUCCESS;
    137173}
    138174
    139175
    140 static int rtSemEventMultiWait(RTSEMEVENTMULTI hEventMultiSem, RTMSINTERVAL cMillies, bool fInterruptible)
    141 {
    142     /*
    143      * Validate input.
    144      */
    145     PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem;
     176/**
     177 * Worker for RTSemEventMultiWaitEx and RTSemEventMultiWaitExDebug.
     178 *
     179 * @returns VBox status code.
     180 * @param   pThis           The event semaphore.
     181 * @param   fFlags          See RTSemEventMultiWaitEx.
     182 * @param   uTimeout        See RTSemEventMultiWaitEx.
     183 * @param   pSrcPos         The source code position of the wait.
     184 */
     185DECLINLINE(int) rtR0SemEventMultiNtWait(PRTSEMEVENTMULTIINTERNAL pThis, uint32_t fFlags, uint64_t uTimeout,
     186                                        PCRTLOCKVALSRCPOS pSrcPos)
     187{
     188    /*
     189     * Validate input.
     190     */
    146191    if (!pThis)
    147192        return VERR_INVALID_PARAMETER;
    148193    AssertPtrReturn(pThis, VERR_INVALID_PARAMETER);
    149194    AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER);
     195    rtR0SemEventMultiNtRetain(pThis);
     196
     197    /*
     198     * Convert the timeout to a relative one because KeWaitForSingleObject
     199     * takes system time instead of interrupt time as input for absolute
     200     * timeout specifications.  So, we're best of by giving it relative time.
     201     *
     202     * Lazy bird converts uTimeout to relative nanoseconds and then to Nt time.
     203     */
     204    if (!(fFlags & RTSEMWAIT_FLAGS_INDEFINITE))
     205    {
     206        if (fFlags & RTSEMWAIT_FLAGS_MILLISECS)
     207            uTimeout = uTimeout < UINT64_MAX / UINT32_C(1000000) * UINT32_C(1000000)
     208                     ? uTimeout * UINT32_C(1000000)
     209                     : UINT64_MAX;
     210        if (uTimeout == UINT64_MAX)
     211            fFlags |= RTSEMWAIT_FLAGS_INDEFINITE;
     212        else
     213        {
     214            if (fFlags & RTSEMWAIT_FLAGS_ABSOLUTE)
     215            {
     216                uint64_t u64Now = RTTimeSystemNanoTS();
     217                uTimeout = u64Now < uTimeout
     218                         ? uTimeout - u64Now
     219                         : 0;
     220            }
     221        }
     222    }
     223
    150224
    151225    /*
     
    154228     */
    155229    NTSTATUS        rcNt;
     230    BOOLEAN         fInterruptible = !!(fFlags & RTSEMWAIT_FLAGS_INTERRUPTIBLE);
    156231    KPROCESSOR_MODE WaitMode   = fInterruptible ? UserMode : KernelMode;
    157     if (cMillies == RT_INDEFINITE_WAIT)
     232    if (fFlags & RTSEMWAIT_FLAGS_INDEFINITE)
    158233        rcNt = KeWaitForSingleObject(&pThis->Event, Executive, WaitMode, fInterruptible, NULL);
    159234    else
    160235    {
    161236        LARGE_INTEGER Timeout;
    162         Timeout.QuadPart = -(int64_t)cMillies * 10000;
     237        Timeout.QuadPart = -(int64_t)(uTimeout / 100);
    163238        rcNt = KeWaitForSingleObject(&pThis->Event, Executive, WaitMode, fInterruptible, &Timeout);
    164239    }
    165     switch (rcNt)
    166     {
    167         case STATUS_SUCCESS:
    168             if (pThis->u32Magic == RTSEMEVENTMULTI_MAGIC)
    169                 return VINF_SUCCESS;
    170             return VERR_SEM_DESTROYED;
    171         case STATUS_ALERTED:
    172             return VERR_INTERRUPTED;
    173         case STATUS_USER_APC:
    174             return VERR_INTERRUPTED;
    175         case STATUS_TIMEOUT:
    176             return VERR_TIMEOUT;
    177         default:
    178             AssertMsgFailed(("pThis->u32Magic=%RX32 pThis=%p: wait returned %lx!\n",
    179                              pThis->u32Magic, pThis, (long)rcNt));
    180             return VERR_INTERNAL_ERROR;
    181     }
    182 }
    183 
    184 
    185 RTDECL(int) RTSemEventMultiWait(RTSEMEVENTMULTI hEventMultiSem, RTMSINTERVAL cMillies)
    186 {
    187     return rtSemEventMultiWait(hEventMultiSem, cMillies, false /* fInterruptible */);
    188 }
    189 
    190 
    191 RTDECL(int) RTSemEventMultiWaitNoResume(RTSEMEVENTMULTI hEventMultiSem, RTMSINTERVAL cMillies)
    192 {
    193     return rtSemEventMultiWait(hEventMultiSem, cMillies, true /* fInterruptible */);
    194 }
    195 
     240    int rc;
     241    if (pThis->u32Magic == RTSEMEVENTMULTI_MAGIC)
     242    {
     243        switch (rcNt)
     244        {
     245            case STATUS_SUCCESS:
     246                rc = VINF_SUCCESS;
     247                break;
     248            case STATUS_ALERTED:
     249                rc = VERR_INTERRUPTED;
     250                break;
     251            case STATUS_USER_APC:
     252                rc = VERR_INTERRUPTED;
     253                break;
     254            case STATUS_TIMEOUT:
     255                rc = VERR_TIMEOUT;
     256                break;
     257            default:
     258                AssertMsgFailed(("pThis->u32Magic=%RX32 pThis=%p: wait returned %lx!\n",
     259                                 pThis->u32Magic, pThis, (long)rcNt));
     260                rc = VERR_INTERNAL_ERROR_4;
     261                break;
     262        }
     263    }
     264    else
     265        rc = VERR_SEM_DESTROYED;
     266
     267    rtR0SemEventMultiNtRelease(pThis);
     268    return rc;
     269}
     270
     271
     272#undef RTSemEventMultiWaitEx
     273RTDECL(int)  RTSemEventMultiWaitEx(RTSEMEVENTMULTI hEventMultiSem, uint32_t fFlags, uint64_t uTimeout)
     274{
     275#ifndef RTSEMEVENT_STRICT
     276    return rtR0SemEventMultiNtWait(hEventMultiSem, fFlags, uTimeout, NULL);
     277#else
     278    RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
     279    return rtR0SemEventMultiNtWait(hEventMultiSem, fFlags, uTimeout, &SrcPos);
     280#endif
     281}
     282
     283
     284RTDECL(int)  RTSemEventMultiWaitExDebug(RTSEMEVENTMULTI hEventMultiSem, uint32_t fFlags, uint64_t uTimeout,
     285                                        RTHCUINTPTR uId, RT_SRC_POS_DECL)
     286{
     287    RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
     288    return rtR0SemEventMultiNtWait(hEventMultiSem, fFlags, uTimeout, &SrcPos);
     289}
     290
Note: See TracChangeset for help on using the changeset viewer.

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