VirtualBox

Changeset 92792 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Dec 7, 2021 9:49:10 PM (3 years ago)
Author:
vboxsync
Message:

IPRT/semevent-nt: Converted semevent-r0drv-nt.cpp into something that works both in ring-3 and ring-0. Enabled the tstRTSemEvent testcase. bugref:10138

Location:
trunk/src/VBox/Runtime
Files:
4 edited
1 copied
1 moved

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/Makefile.kmk

    r92782 r92792  
    937937        generic/RTRandAdvCreateSystemFaster-generic.cpp \
    938938        generic/RTRandAdvCreateSystemTruer-generic.cpp \
    939         generic/RTSemEventWait-generic.cpp \
    940939        generic/RTSemEventMultiWait-2-ex-generic.cpp \
    941940        generic/RTSemEventMultiWaitNoResume-2-ex-generic.cpp \
     
    964963        r3/nt/RTPathSetMode-r3-nt.cpp \
    965964        r3/nt/RTProcQueryParent-r3-nt.cpp \
     965        nt/semevent-nt.cpp \
    966966        r3/win/env-win.cpp \
    967967        r3/win/RTCrStoreCreateSnapshotById-win.cpp \
     
    995995        r3/win/rtProcInitExePath-win.cpp \
    996996        r3/win/sched-win.cpp \
    997         r3/win/semevent-win.cpp \
     997        generic/RTSemEventWait-2-ex-generic.cpp \
     998        generic/RTSemEventWaitNoResume-2-ex-generic.cpp \
    998999        r3/win/semeventmulti-win.cpp \
    9991000        r3/win/semmutex-win.cpp \
     
    10011002        r3/win/shmem-win.cpp \
    10021003        r3/win/symlink-win.cpp \
     1004        r3/win/system-get-nt-xxx-win.cpp \
    10031005        r3/win/thread-win.cpp \
    10041006        r3/win/thread2-win.cpp \
     
    20502052        nt/fileioutils-nt.cpp \
    20512053        nt/RTErrConvertFromNtStatus.cpp \
     2054        nt/semevent-nt.cpp \
    20522055        r3/nt/direnum-r3-nt.cpp \
    20532056        r3/nt/dirrel-r3-nt.cpp \
     
    20762079        r3/win/RTUuidCreate-win.cpp \
    20772080        r3/win/sched-win.cpp \
    2078         r3/win/semevent-win.cpp \
     2081        generic/RTSemEventWait-2-ex-generic.cpp \
     2082        generic/RTSemEventWaitNoResume-2-ex-generic.cpp \
    20792083        r3/win/semeventmulti-win.cpp \
    20802084        r3/win/semmutex-win.cpp \
    20812085        r3/win/symlink-win.cpp \
     2086        r3/win/system-get-nt-xxx-win.cpp \
    20822087        r3/win/thread-win.cpp \
    20832088        r3/win/thread2-win.cpp \
     
    32123217        nt/RTNtPathExpand8dot3PathA.cpp \
    32133218        nt/RTNtPathFindPossible8dot3Name.cpp \
     3219        nt/semevent-nt.cpp \
    32143220        r0drv/generic/threadctxhooks-r0drv-generic.cpp \
    32153221        r0drv/alloc-ef-r0drv.cpp \
     
    32263232        r0drv/nt/process-r0drv-nt.cpp \
    32273233        r0drv/nt/RTLogWriteDebugger-r0drv-nt.cpp \
    3228         r0drv/nt/semevent-r0drv-nt.cpp \
    32293234        r0drv/nt/semeventmulti-r0drv-nt.cpp \
    32303235        r0drv/nt/semfastmutex-r0drv-nt.cpp \
  • trunk/src/VBox/Runtime/nt/semevent-nt.cpp

    r92791 r92792  
    11/* $Id$ */
    22/** @file
    3  * IPRT -  Single Release Event Semaphores, Ring-0 Driver, NT.
     3 * IPRT -  Single Release Event Semaphores, Ring-0 Driver & Ring-3 Userland, NT.
    44 */
    55
     
    3030*********************************************************************************************************************************/
    3131#define RTSEMEVENT_WITHOUT_REMAPPING
    32 #include "the-nt-kernel.h"
     32#ifdef IN_RING0
     33# include "../r0drv/nt/the-nt-kernel.h"
     34#else
     35# include <iprt/nt/nt.h>
     36#endif
    3337#include <iprt/semaphore.h>
    3438
     
    4044#include <iprt/time.h>
    4145#include <iprt/timer.h>
    42 
     46#ifdef IN_RING3
     47# include <iprt/system.h>
     48#endif
    4349#include "internal/magics.h"
    4450
     
    5662    /** Reference counter. */
    5763    uint32_t volatile   cRefs;
    58     /** The NT Event object. */
     64#ifdef IN_RING0
     65    /** The NT event object. */
    5966    KEVENT              Event;
     67#elif defined(IN_RING3)
     68    /** Handle to the NT event object. */
     69    HANDLE              hEvent;
     70#else
     71# error "Unknown context"
     72#endif
     73#if defined(RTSEMEVENT_STRICT) && defined(IN_RING3)
     74    /** Signallers. */
     75    RTLOCKVALRECSHRD    Signallers;
     76    /** Indicates that lock validation should be performed. */
     77    bool volatile       fEverHadSignallers;
     78#endif
     79
    6080} RTSEMEVENTINTERNAL, *PRTSEMEVENTINTERNAL;
    6181
     
    7292    Assert(!(fFlags & RTSEMEVENT_FLAGS_BOOTSTRAP_HACK) || (fFlags & RTSEMEVENT_FLAGS_NO_LOCK_VAL));
    7393    AssertCompile(sizeof(RTSEMEVENTINTERNAL) > sizeof(void *));
    74     RT_NOREF2(hClass, pszNameFmt);
    7594
    7695    PRTSEMEVENTINTERNAL pThis = (PRTSEMEVENTINTERNAL)RTMemAlloc(sizeof(*pThis));
     
    7998        pThis->u32Magic = RTSEMEVENT_MAGIC;
    8099        pThis->cRefs    = 1;
     100#ifdef IN_RING0
    81101        KeInitializeEvent(&pThis->Event, SynchronizationEvent, FALSE /* not signalled */);
    82 
    83         *phEventSem = pThis;
    84         return VINF_SUCCESS;
     102#else
     103        NTSTATUS rcNt = NtCreateEvent(&pThis->hEvent, EVENT_ALL_ACCESS, NULL /*pObjAttr*/,
     104                                      SynchronizationEvent, FALSE /*not signalled*/);
     105        if (NT_SUCCESS(rcNt))
     106#endif
     107        {
     108#if defined(RTSEMEVENT_STRICT) && defined(IN_RING3)
     109            if (!pszNameFmt)
     110            {
     111                static uint32_t volatile s_iSemEventAnon = 0;
     112                RTLockValidatorRecSharedInit(&pThis->Signallers, hClass, RTLOCKVAL_SUB_CLASS_ANY, pThis,
     113                                             true /*fSignaller*/, !(fFlags & RTSEMEVENT_FLAGS_NO_LOCK_VAL),
     114                                             "RTSemEvent-%u", ASMAtomicIncU32(&s_iSemEventAnon) - 1);
     115            }
     116            else
     117            {
     118                va_list va;
     119                va_start(va, pszNameFmt);
     120                RTLockValidatorRecSharedInitV(&pThis->Signallers, hClass, RTLOCKVAL_SUB_CLASS_ANY, pThis,
     121                                              true /*fSignaller*/, !(fFlags & RTSEMEVENT_FLAGS_NO_LOCK_VAL),
     122                                              pszNameFmt, va);
     123                va_end(va);
     124            }
     125            pThis->fEverHadSignallers = false;
     126#else
     127            RT_NOREF_PV(hClass); RT_NOREF_PV(pszNameFmt);
     128#endif
     129            *phEventSem = pThis;
     130            return VINF_SUCCESS;
     131        }
     132#ifdef IN_RING3
     133        RTMemFree(pThis);
     134        return RTErrConvertFromNtStatus(rcNt);
     135#endif
    85136    }
    86137    return VERR_NO_MEMORY;
     
    108159{
    109160    if (ASMAtomicDecU32(&pThis->cRefs) == 0)
     161    {
     162#ifdef IN_RING3
     163        NTSTATUS rcNt = NtClose(pThis->hEvent);
     164        AssertMsg(NT_SUCCESS(rcNt), ("%#x\n", rcNt)); RT_NOREF(rcNt);
     165        pThis->hEvent = NULL;
     166#endif
     167#if defined(RTSEMEVENT_STRICT) && defined(IN_RING3)
     168        RTLockValidatorRecSharedDelete(&pThis->Signallers);
     169#endif
    110170        RTMemFree(pThis);
     171    }
    111172}
    112173
     
    127188     */
    128189    ASMAtomicIncU32(&pThis->u32Magic);
     190#ifdef IN_RING0
    129191    KeSetEvent(&pThis->Event, 0xfff, FALSE);
     192#else
     193    NtSetEvent(pThis->hEvent, NULL);
     194#endif
     195
    130196    rtR0SemEventNtRelease(pThis);
    131197    return VINF_SUCCESS;
     
    143209    rtR0SemEventNtRetain(pThis);
    144210
     211#if defined(RTSEMEVENT_STRICT) && defined(IN_RING3)
     212    if (pThis->fEverHadSignallers)
     213    {
     214        int rc9 = RTLockValidatorRecSharedCheckSignaller(&pThis->Signallers, NIL_RTTHREAD);
     215        if (RT_FAILURE(rc9))
     216            return rc9;
     217    }
     218#endif
     219
    145220    /*
    146221     * Signal the event object.
    147222     */
     223#ifdef IN_RING0
    148224    KeSetEvent(&pThis->Event, 1, FALSE);
     225#else
     226    NTSTATUS rcNt = NtSetEvent(pThis->hEvent, NULL);
     227#endif
    149228
    150229    rtR0SemEventNtRelease(pThis);
     230#ifdef IN_RING3
     231    AssertMsgReturn(NT_SUCCESS(rcNt), ("Signaling hEventSem %p failed: %#x\n", pThis, rcNt), RTErrConvertFromNtStatus(rcNt));
     232#endif
    151233    return VINF_SUCCESS;
    152234}
     
    171253    if (!pThis)
    172254        return VERR_INVALID_PARAMETER;
    173     AssertPtrReturn(pThis, VERR_INVALID_PARAMETER);
    174     AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER);
    175     AssertReturn(RTSEMWAIT_FLAGS_ARE_VALID(fFlags), VERR_INVALID_PARAMETER);
     255    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     256    AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_HANDLE);
     257    AssertReturn(RTSEMWAIT_FLAGS_ARE_VALID(fFlags), VERR_INVALID_FLAGS);
    176258    NOREF(pSrcPos);
    177259
    178260    rtR0SemEventNtRetain(pThis);
     261
     262    /*
     263     * Lock validation needs to be done only when not polling.
     264     */
     265#if defined(RTSEMEVENT_STRICT) && defined(IN_RING3)
     266    RTTHREAD const hThreadSelf = !(pThis->fFlags & RTSEMEVENT_FLAGS_BOOTSTRAP_HACK) ? RTThreadSelfAutoAdopt() : RTThreadSelf();
     267    if (   pThis->fEverHadSignallers
     268        && (   uTimeout != 0
     269            || (fFlags & (RTSEMWAIT_FLAGS_INDEFINITE | RTSEMWAIT_FLAGS_ABSOLUTE))) )
     270    {
     271        int rc9 = RTLockValidatorRecSharedCheckBlocking(&pThis->Signallers, hThreadSelf, NULL /*pSrcPos*/, false,
     272                                                        fFlags & RTSEMWAIT_FLAGS_INDEFINITE
     273                                                        ? RT_INDEFINITE_WAIT : RT_MS_30SEC /*whatever*/,
     274                                                        RTTHREADSTATE_EVENT, true);
     275        if (RT_FAILURE(rc9))
     276            return rc9;
     277    }
     278#elif defined(IN_RING3)
     279    RTTHREAD const hThreadSelf = RTThreadSelf();
     280#endif
    179281
    180282    /*
     
    185287     * Lazy bird converts uTimeout to relative nanoseconds and then to Nt time.
    186288     */
     289#ifdef IN_RING3
     290    uint64_t nsStartNow = 0;
     291#endif
    187292    if (!(fFlags & RTSEMWAIT_FLAGS_INDEFINITE))
    188293    {
    189294        if (fFlags & RTSEMWAIT_FLAGS_MILLISECS)
    190             uTimeout = uTimeout < UINT64_MAX / UINT32_C(1000000) * UINT32_C(1000000)
    191                      ? uTimeout * UINT32_C(1000000)
     295            uTimeout = uTimeout < UINT64_MAX / RT_NS_1MS
     296                     ? uTimeout * RT_NS_1MS
    192297                     : UINT64_MAX;
    193298        if (uTimeout == UINT64_MAX)
     
    195300        else
    196301        {
     302#ifdef IN_RING3
     303            if (fFlags & (RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_ABSOLUTE))
     304                nsStartNow = RTTimeSystemNanoTS();
     305#endif
    197306            if (fFlags & RTSEMWAIT_FLAGS_ABSOLUTE)
    198307            {
    199                 uint64_t u64Now = RTTimeSystemNanoTS();
    200                 uTimeout = u64Now < uTimeout
    201                          ? uTimeout - u64Now
     308#ifdef IN_RING0
     309                uint64_t const nsStartNow = RTTimeSystemNanoTS();
     310#endif
     311                uTimeout = nsStartNow < uTimeout
     312                         ? uTimeout - nsStartNow
    202313                         : 0;
    203314            }
     
    209320     * We're assuming interruptible waits should happen at UserMode level.
    210321     */
    211     NTSTATUS        rcNt;
    212     BOOLEAN         fInterruptible = !!(fFlags & RTSEMWAIT_FLAGS_INTERRUPTIBLE);
    213     KPROCESSOR_MODE WaitMode   = fInterruptible ? UserMode : KernelMode;
    214     if (fFlags & RTSEMWAIT_FLAGS_INDEFINITE)
    215         rcNt = KeWaitForSingleObject(&pThis->Event, Executive, WaitMode, fInterruptible, NULL);
    216     else
    217     {
    218         LARGE_INTEGER Timeout;
    219         Timeout.QuadPart = -(int64_t)(uTimeout / 100);
    220         rcNt = KeWaitForSingleObject(&pThis->Event, Executive, WaitMode, fInterruptible, &Timeout);
    221     }
    222322    int rc;
    223     if (pThis->u32Magic == RTSEMEVENT_MAGIC)
    224     {
    225         switch (rcNt)
     323#ifdef IN_RING3
     324    for (;;)
     325#endif
     326    {
     327#ifdef IN_RING0
     328        BOOLEAN         fInterruptible = !!(fFlags & RTSEMWAIT_FLAGS_INTERRUPTIBLE);
     329        KPROCESSOR_MODE WaitMode       = fInterruptible ? UserMode : KernelMode;
     330#endif
     331        NTSTATUS        rcNt;
     332#ifdef IN_RING3
     333        RTThreadBlocking(hThreadSelf, RTTHREADSTATE_EVENT, true);
     334#endif
     335        if (fFlags & RTSEMWAIT_FLAGS_INDEFINITE)
     336#ifdef IN_RING0
     337            rcNt = KeWaitForSingleObject(&pThis->Event, Executive, WaitMode, fInterruptible, NULL);
     338#else
     339            rcNt = NtWaitForSingleObject(pThis->hEvent, TRUE /*Alertable*/, NULL);
     340#endif
     341        else
    226342        {
    227             case STATUS_SUCCESS:
    228                 rc = VINF_SUCCESS;
    229                 break;
    230             case STATUS_ALERTED:
    231                 rc = VERR_INTERRUPTED;
    232                 break;
    233             case STATUS_USER_APC:
    234                 rc = VERR_INTERRUPTED;
    235                 break;
    236             case STATUS_TIMEOUT:
    237                 rc = VERR_TIMEOUT;
    238                 break;
    239             default:
    240                 AssertMsgFailed(("pThis->u32Magic=%RX32 pThis=%p: wait returned %lx!\n",
    241                                  pThis->u32Magic, pThis, (long)rcNt));
    242                 rc = VERR_INTERNAL_ERROR_4;
    243                 break;
     343            LARGE_INTEGER Timeout;
     344            Timeout.QuadPart = -(int64_t)(uTimeout / 100);
     345#ifdef IN_RING0
     346            rcNt = KeWaitForSingleObject(&pThis->Event, Executive, WaitMode, fInterruptible, &Timeout);
     347#else
     348            rcNt = NtWaitForSingleObject(pThis->hEvent, TRUE /*Alertable*/, &Timeout);
     349#endif
    244350        }
    245     }
    246     else
    247         rc = VERR_SEM_DESTROYED;
     351#ifdef IN_RING3
     352        RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_EVENT);
     353#endif
     354        if (pThis->u32Magic == RTSEMEVENT_MAGIC)
     355        {
     356            switch (rcNt)
     357            {
     358                case STATUS_SUCCESS:
     359                    rc = VINF_SUCCESS;
     360                    break;
     361
     362                case STATUS_TIMEOUT:
     363                    Assert(!(fFlags & RTSEMWAIT_FLAGS_INDEFINITE));
     364                    rc = VERR_TIMEOUT;
     365                    break;
     366
     367                case STATUS_USER_APC:
     368                case STATUS_ALERTED:
     369                    rc = VERR_INTERRUPTED;
     370#ifdef IN_RING3
     371                    /* Loop if when automatically resuming on interruption, adjusting the timeout. */
     372                    if (fFlags & RTSEMWAIT_FLAGS_RESUME)
     373                    {
     374                        if (!(fFlags & RTSEMWAIT_FLAGS_INDEFINITE) && uTimeout > 0)
     375                        {
     376                            uint64_t const nsNewNow   = RTTimeSystemNanoTS();
     377                            uint64_t const cNsElapsed = nsNewNow - nsStartNow;
     378                            if (cNsElapsed < uTimeout)
     379                                uTimeout -= cNsElapsed;
     380                            else
     381                                uTimeout = 0;
     382                            nsStartNow = nsNewNow;
     383                        }
     384                        continue;
     385                    }
     386#endif
     387                    break;
     388
     389#ifdef IN_RING3
     390                case STATUS_ABANDONED_WAIT_0:
     391                    rc = VERR_SEM_OWNER_DIED;
     392                    break;
     393#endif
     394                default:
     395                    AssertMsgFailed(("pThis->u32Magic=%RX32 pThis=%p: wait returned %x!\n", pThis->u32Magic, pThis, rcNt));
     396                    rc = VERR_INTERNAL_ERROR_4;
     397                    break;
     398            }
     399        }
     400        else
     401            rc = VERR_SEM_DESTROYED;
     402#ifdef IN_RING3
     403        break;
     404#endif
     405    }
    248406
    249407    rtR0SemEventNtRelease(pThis);
     
    273431RTDECL(uint32_t) RTSemEventGetResolution(void)
    274432{
     433    /*
     434     * We need to figure the KeWaitForSingleObject / NtWaitForSingleObject timeout
     435     * resolution, i.e. if we wish to wait for 1000ns how long are we likely to
     436     * actually wait before woken up.
     437     *
     438     * In older versions of NT, these timeout were implemented using KTIMERs and
     439     * have the same resolution as what them.  This should be found using
     440     * ExSetTimerResolution or NtQueryTimerResolution.
     441     *
     442     * Probably since windows 8.1 the value returned by NtQueryTimerResolution (and
     443     * set NtSetTimerResolution) have been virtualized and no longer reflects the
     444     * timer wheel resolution, at least from what I can tell. ExSetTimerResolution
     445     * still works as before, but it accesses variable that I cannot find out how
     446     * to access from user land.  So, kernel will get (and be able to set) the right
     447     * granularity, while in user land we'll be forced to reporting the max value.
     448     *
     449     * (The reason why I suspect it's since 8.1 is because the high resolution
     450     * ExSetTimer APIs were introduced back then.)
     451     */
     452#ifdef IN_RING0
    275453    return RTTimerGetSystemGranularity();
    276 }
    277 
    278 
     454#else
     455    ULONG cNtTicksMin = 0;
     456    ULONG cNtTicksMax = 0;
     457    ULONG cNtTicksCur = 0;
     458    NTSTATUS rcNt = NtQueryTimerResolution(&cNtTicksMin, &cNtTicksMax, &cNtTicksCur);
     459    if (NT_SUCCESS(rcNt))
     460    {
     461        Assert(cNtTicksMin >= cNtTicksMax);
     462        if (RTSystemGetNtVersion() >= RTSYSTEM_MAKE_NT_VERSION(6,3,9600)) /** @todo check when the switch happened, might be much later... */
     463            return cNtTicksMin * 100;
     464        return cNtTicksCur * 100;
     465    }
     466    AssertFailed();
     467    return 16 * RT_NS_1MS; /* the default on 64-bit windows 10 */
     468#endif
     469}
     470
     471
     472#ifdef IN_RING0
    279473RTR0DECL(bool) RTSemEventIsSignalSafe(void)
    280474{
    281475    return KeGetCurrentIrql() <= DISPATCH_LEVEL;
    282476}
    283 
     477#endif
     478
     479#ifdef IN_RING3
     480
     481RTDECL(void) RTSemEventSetSignaller(RTSEMEVENT hEventSem, RTTHREAD hThread)
     482{
     483# ifdef RTSEMEVENT_STRICT
     484    struct RTSEMEVENTINTERNAL *pThis = hEventSem;
     485    AssertPtrReturnVoid(pThis);
     486    AssertReturnVoid(pThis->u32Magic == RTSEMEVENT_MAGIC);
     487
     488    ASMAtomicWriteBool(&pThis->fEverHadSignallers, true);
     489    RTLockValidatorRecSharedResetOwner(&pThis->Signallers, hThread, NULL);
     490# else
     491    RT_NOREF_PV(hEventSem); RT_NOREF_PV(hThread);
     492# endif
     493}
     494
     495
     496RTDECL(void) RTSemEventAddSignaller(RTSEMEVENT hEventSem, RTTHREAD hThread)
     497{
     498# ifdef RTSEMEVENT_STRICT
     499    struct RTSEMEVENTINTERNAL *pThis = hEventSem;
     500    AssertPtrReturnVoid(pThis);
     501    AssertReturnVoid(pThis->u32Magic == RTSEMEVENT_MAGIC);
     502
     503    ASMAtomicWriteBool(&pThis->fEverHadSignallers, true);
     504    RTLockValidatorRecSharedAddOwner(&pThis->Signallers, hThread, NULL);
     505# else
     506    RT_NOREF_PV(hEventSem); RT_NOREF_PV(hThread);
     507# endif
     508}
     509
     510
     511RTDECL(void) RTSemEventRemoveSignaller(RTSEMEVENT hEventSem, RTTHREAD hThread)
     512{
     513# ifdef RTSEMEVENT_STRICT
     514    struct RTSEMEVENTINTERNAL *pThis = hEventSem;
     515    AssertPtrReturnVoid(pThis);
     516    AssertReturnVoid(pThis->u32Magic == RTSEMEVENT_MAGIC);
     517
     518    RTLockValidatorRecSharedRemoveOwner(&pThis->Signallers, hThread);
     519# else
     520    RT_NOREF_PV(hEventSem); RT_NOREF_PV(hThread);
     521# endif
     522}
     523
     524#endif /* IN_RING3 */
  • trunk/src/VBox/Runtime/r3/win/RTSystemQueryOSInfo-win.cpp

    r91605 r92792  
    316316
    317317
    318 
    319318RTDECL(int) RTSystemQueryOSInfo(RTSYSOSINFO enmInfo, char *pszInfo, size_t cchInfo)
    320319{
     
    346345}
    347346
    348 
    349 RTDECL(uint32_t) RTSystemGetNtBuildNo(void)
    350 {
    351     return g_WinOsInfoEx.dwBuildNumber;
    352 }
    353 
    354 
    355 RTDECL(uint64_t) RTSystemGetNtVersion(void)
    356 {
    357     return RTSYSTEM_MAKE_NT_VERSION(g_WinOsInfoEx.dwMajorVersion, g_WinOsInfoEx.dwMinorVersion, g_WinOsInfoEx.dwBuildNumber);
    358 }
    359 
  • trunk/src/VBox/Runtime/r3/win/system-get-nt-xxx-win.cpp

    • Property svn:mergeinfo set to (toggle deleted branches)
      /branches/VBox-3.0/src/VBox/Runtime/r3/win/RTSystemQueryOSInfo-win.cpp58652,​70973
      /branches/VBox-3.2/src/VBox/Runtime/r3/win/RTSystemQueryOSInfo-win.cpp66309,​66318
      /branches/VBox-4.0/src/VBox/Runtime/r3/win/RTSystemQueryOSInfo-win.cpp70873
      /branches/VBox-4.1/src/VBox/Runtime/r3/win/RTSystemQueryOSInfo-win.cpp74233,​78414,​78691,​81841,​82127,​85941,​85944-85947,​85949-85950,​85953,​86701,​86728,​87009
      /branches/VBox-4.2/src/VBox/Runtime/r3/win/RTSystemQueryOSInfo-win.cpp86229-86230,​86234,​86529,​91503-91504,​91506-91508,​91510,​91514-91515,​91521,​108112,​108114,​108127
      /branches/VBox-4.3/src/VBox/Runtime/r3/win/RTSystemQueryOSInfo-win.cpp89714,​91223,​93628-93629,​94066,​94839,​94897,​95154,​95164,​95167,​95295,​95338,​95353-95354,​95356,​95367,​95451,​95475,​95477,​95480,​95507,​95640,​95659,​95661,​95663,​98913-98914
      /branches/VBox-4.3/trunk/src/VBox/Runtime/r3/win/RTSystemQueryOSInfo-win.cpp91223
      /branches/VBox-5.0/src/VBox/Runtime/r3/win/RTSystemQueryOSInfo-win.cpp104938,​104943,​104950,​104987-104988,​104990,​106453
      /branches/VBox-5.1/src/VBox/Runtime/r3/win/RTSystemQueryOSInfo-win.cpp112367,​116543,​116550,​116568,​116573
      /branches/VBox-5.2/src/VBox/Runtime/r3/win/RTSystemQueryOSInfo-win.cpp119536,​120083,​120099,​120213,​120221,​120239,​123597-123598,​123600-123601,​123755,​124263,​124273,​124277-124279,​124284-124286,​124288-124290,​125768,​125779-125780,​125812,​127158-127159,​127162-127167,​127180
      /branches/VBox-6.0/src/VBox/Runtime/r3/win/RTSystemQueryOSInfo-win.cpp130474-130475,​130477,​130479,​131352
      /branches/VBox-6.1/src/VBox/Runtime/r3/win/RTSystemQueryOSInfo-win.cpp141521,​141567-141568,​141588-141590,​141592-141595,​141652,​141920
      /branches/aeichner/vbox-chromium-cleanup/src/VBox/Runtime/r3/win/RTSystemQueryOSInfo-win.cpp129818-129851,​129853-129861,​129871-129872,​129876,​129880,​129882,​130013-130015,​130094-130095
      /branches/andy/draganddrop/src/VBox/Runtime/r3/win/RTSystemQueryOSInfo-win.cpp90781-91268
      /branches/andy/guestctrl20/src/VBox/Runtime/r3/win/RTSystemQueryOSInfo-win.cpp78916,​78930
      /branches/andy/pdmaudio/src/VBox/Runtime/r3/win/RTSystemQueryOSInfo-win.cpp94582,​94641,​94654,​94688,​94778,​94783,​94816,​95197,​95215-95216,​95250,​95279,​95505-95506,​95543,​95694,​96323,​96470-96471,​96582,​96587,​96802-96803,​96817,​96904,​96967,​96999,​97020-97021,​97025,​97050,​97099
      /branches/bird/hardenedwindows/src/VBox/Runtime/r3/win/RTSystemQueryOSInfo-win.cpp92692-94610
      /branches/dsen/gui/src/VBox/Runtime/r3/win/RTSystemQueryOSInfo-win.cpp79076-79078,​79089,​79109-79110,​79112-79113,​79127-79130,​79134,​79141,​79151,​79155,​79157-79159,​79193,​79197
      /branches/dsen/gui2/src/VBox/Runtime/r3/win/RTSystemQueryOSInfo-win.cpp79224,​79228,​79233,​79235,​79258,​79262-79263,​79273,​79341,​79345,​79354,​79357,​79387-79388,​79559-79569,​79572-79573,​79578,​79581-79582,​79590-79591,​79598-79599,​79602-79603,​79605-79606,​79632,​79635,​79637,​79644
      /branches/dsen/gui3/src/VBox/Runtime/r3/win/RTSystemQueryOSInfo-win.cpp79645-79692
    r92789 r92792  
    3131#include "internal/iprt.h"
    3232#include <iprt/win/windows.h>
    33 #include <WinUser.h>
    3433
    3534#include "internal-r3-win.h"
    3635#include <iprt/system.h>
    3736#include <iprt/assert.h>
    38 #include <iprt/ctype.h>
    39 #include <iprt/errcore.h>
    40 #include <iprt/string.h>
    41 #include <iprt/utf16.h>
    42 
    43 
    44 /*********************************************************************************************************************************
    45 *   Structures and Typedefs                                                                                                      *
    46 *********************************************************************************************************************************/
    47 
    48 /**
    49  * These are the PRODUCT_* defines found in the Vista Platform SDK and returned
    50  * by GetProductInfo().
    51  *
    52  * We define them ourselves because we don't necessarily have any Vista PSDK around.
    53  */
    54 typedef enum RTWINPRODTYPE
    55 {
    56     kRTWinProdType_UNDEFINED                    = 0x00000000,  ///< An unknown product
    57     kRTWinProdType_BUSINESS                     = 0x00000006,  ///< Business Edition
    58     kRTWinProdType_BUSINESS_N                   = 0x00000010,  ///< Business Edition
    59     kRTWinProdType_CLUSTER_SERVER               = 0x00000012,  ///< Cluster Server Edition
    60     kRTWinProdType_DATACENTER_SERVER            = 0x00000008,  ///< Server Datacenter Edition (full installation)
    61     kRTWinProdType_DATACENTER_SERVER_CORE       = 0x0000000C,  ///< Server Datacenter Edition (core installation)
    62     kRTWinProdType_ENTERPRISE                   = 0x00000004,  ///< Enterprise Edition
    63     kRTWinProdType_ENTERPRISE_N                 = 0x0000001B,  ///< Enterprise Edition
    64     kRTWinProdType_ENTERPRISE_SERVER            = 0x0000000A,  ///< Server Enterprise Edition (full installation)
    65     kRTWinProdType_ENTERPRISE_SERVER_CORE       = 0x0000000E,  ///< Server Enterprise Edition (core installation)
    66     kRTWinProdType_ENTERPRISE_SERVER_IA64       = 0x0000000F,  ///< Server Enterprise Edition for Itanium-based Systems
    67     kRTWinProdType_HOME_BASIC                   = 0x00000002,  ///< Home Basic Edition
    68     kRTWinProdType_HOME_BASIC_N                 = 0x00000005,  ///< Home Basic Edition
    69     kRTWinProdType_HOME_PREMIUM                 = 0x00000003,  ///< Home Premium Edition
    70     kRTWinProdType_HOME_PREMIUM_N               = 0x0000001A,  ///< Home Premium Edition
    71     kRTWinProdType_HOME_SERVER                  = 0x00000013,  ///< Home Server Edition
    72     kRTWinProdType_SERVER_FOR_SMALLBUSINESS     = 0x00000018,  ///< Server for Small Business Edition
    73     kRTWinProdType_SMALLBUSINESS_SERVER         = 0x00000009,  ///< Small Business Server
    74     kRTWinProdType_SMALLBUSINESS_SERVER_PREMIUM = 0x00000019,  ///< Small Business Server Premium Edition
    75     kRTWinProdType_STANDARD_SERVER              = 0x00000007,  ///< Server Standard Edition (full installation)
    76     kRTWinProdType_STANDARD_SERVER_CORE         = 0x0000000D,  ///< Server Standard Edition (core installation)
    77     kRTWinProdType_STARTER                      = 0x0000000B,  ///< Starter Edition
    78     kRTWinProdType_STORAGE_ENTERPRISE_SERVER    = 0x00000017,  ///< Storage Server Enterprise Edition
    79     kRTWinProdType_STORAGE_EXPRESS_SERVER       = 0x00000014,  ///< Storage Server Express Edition
    80     kRTWinProdType_STORAGE_STANDARD_SERVER      = 0x00000015,  ///< Storage Server Standard Edition
    81     kRTWinProdType_STORAGE_WORKGROUP_SERVER     = 0x00000016,  ///< Storage Server Workgroup Edition
    82     kRTWinProdType_ULTIMATE                     = 0x00000001,  ///< Ultimate Edition
    83     kRTWinProdType_ULTIMATE_N                   = 0x0000001C,  ///< Ultimate Edition
    84     kRTWinProdType_WEB_SERVER                   = 0x00000011,  ///< Web Server Edition (full)
    85     kRTWinProdType_WEB_SERVER_CORE              = 0x0000001D   ///< Web Server Edition (core)
    86 } RTWINPRODTYPE;
    87 
    88 
    89 /**
    90  * Wrapper around the GetProductInfo API.
    91  *
    92  * @returns The vista type.
    93  */
    94 static RTWINPRODTYPE rtSystemWinGetProductInfo(DWORD dwOSMajorVersion, DWORD dwOSMinorVersion, DWORD dwSpMajorVersion, DWORD dwSpMinorVersion)
    95 {
    96     BOOL (WINAPI *pfnGetProductInfo)(DWORD, DWORD, DWORD, DWORD, PDWORD);
    97     pfnGetProductInfo = (BOOL (WINAPI *)(DWORD, DWORD, DWORD, DWORD, PDWORD))GetProcAddress(GetModuleHandle("kernel32.dll"), "GetProductInfo");
    98     if (pfnGetProductInfo)
    99     {
    100         DWORD dwProductType = kRTWinProdType_UNDEFINED;
    101         if (pfnGetProductInfo(dwOSMajorVersion, dwOSMinorVersion, dwSpMajorVersion, dwSpMinorVersion, &dwProductType))
    102             return (RTWINPRODTYPE)dwProductType;
    103     }
    104     return kRTWinProdType_UNDEFINED;
    105 }
    106 
    107 
    108 
    109 /**
    110  * Appends the product type if available.
    111  *
    112  * @param   pszTmp      The buffer. Assumes it's big enough.
    113  */
    114 static void rtSystemWinAppendProductType(char *pszTmp)
    115 {
    116     RTWINPRODTYPE enmVistaType = rtSystemWinGetProductInfo(6, 0, 0, 0);
    117     switch (enmVistaType)
    118     {
    119         case kRTWinProdType_BUSINESS:                        strcat(pszTmp, " Business Edition"); break;
    120         case kRTWinProdType_BUSINESS_N:                      strcat(pszTmp, " Business Edition"); break;
    121         case kRTWinProdType_CLUSTER_SERVER:                  strcat(pszTmp, " Cluster Server Edition"); break;
    122         case kRTWinProdType_DATACENTER_SERVER:               strcat(pszTmp, " Server Datacenter Edition (full installation)"); break;
    123         case kRTWinProdType_DATACENTER_SERVER_CORE:          strcat(pszTmp, " Server Datacenter Edition (core installation)"); break;
    124         case kRTWinProdType_ENTERPRISE:                      strcat(pszTmp, " Enterprise Edition"); break;
    125         case kRTWinProdType_ENTERPRISE_N:                    strcat(pszTmp, " Enterprise Edition"); break;
    126         case kRTWinProdType_ENTERPRISE_SERVER:               strcat(pszTmp, " Server Enterprise Edition (full installation)"); break;
    127         case kRTWinProdType_ENTERPRISE_SERVER_CORE:          strcat(pszTmp, " Server Enterprise Edition (core installation)"); break;
    128         case kRTWinProdType_ENTERPRISE_SERVER_IA64:          strcat(pszTmp, " Server Enterprise Edition for Itanium-based Systems"); break;
    129         case kRTWinProdType_HOME_BASIC:                      strcat(pszTmp, " Home Basic Edition"); break;
    130         case kRTWinProdType_HOME_BASIC_N:                    strcat(pszTmp, " Home Basic Edition"); break;
    131         case kRTWinProdType_HOME_PREMIUM:                    strcat(pszTmp, " Home Premium Edition"); break;
    132         case kRTWinProdType_HOME_PREMIUM_N:                  strcat(pszTmp, " Home Premium Edition"); break;
    133         case kRTWinProdType_HOME_SERVER:                     strcat(pszTmp, " Home Server Edition"); break;
    134         case kRTWinProdType_SERVER_FOR_SMALLBUSINESS:        strcat(pszTmp, " Server for Small Business Edition"); break;
    135         case kRTWinProdType_SMALLBUSINESS_SERVER:            strcat(pszTmp, " Small Business Server"); break;
    136         case kRTWinProdType_SMALLBUSINESS_SERVER_PREMIUM:    strcat(pszTmp, " Small Business Server Premium Edition"); break;
    137         case kRTWinProdType_STANDARD_SERVER:                 strcat(pszTmp, " Server Standard Edition (full installation)"); break;
    138         case kRTWinProdType_STANDARD_SERVER_CORE:            strcat(pszTmp, " Server Standard Edition (core installation)"); break;
    139         case kRTWinProdType_STARTER:                         strcat(pszTmp, " Starter Edition"); break;
    140         case kRTWinProdType_STORAGE_ENTERPRISE_SERVER:       strcat(pszTmp, " Storage Server Enterprise Edition"); break;
    141         case kRTWinProdType_STORAGE_EXPRESS_SERVER:          strcat(pszTmp, " Storage Server Express Edition"); break;
    142         case kRTWinProdType_STORAGE_STANDARD_SERVER:         strcat(pszTmp, " Storage Server Standard Edition"); break;
    143         case kRTWinProdType_STORAGE_WORKGROUP_SERVER:        strcat(pszTmp, " Storage Server Workgroup Edition"); break;
    144         case kRTWinProdType_ULTIMATE:                        strcat(pszTmp, " Ultimate Edition"); break;
    145         case kRTWinProdType_ULTIMATE_N:                      strcat(pszTmp, " Ultimate Edition"); break;
    146         case kRTWinProdType_WEB_SERVER:                      strcat(pszTmp, " Web Server Edition (full installation)"); break;
    147         case kRTWinProdType_WEB_SERVER_CORE:                 strcat(pszTmp, " Web Server Edition (core installation)"); break;
    148         case kRTWinProdType_UNDEFINED:                       break;
    149     }
    150 }
    151 
    152 
    153 /**
    154  * Services the  RTSYSOSINFO_PRODUCT, RTSYSOSINFO_RELEASE
    155  * and RTSYSOSINFO_SERVICE_PACK requests.
    156  *
    157  * @returns See RTSystemQueryOSInfo.
    158  * @param   enmInfo         See RTSystemQueryOSInfo.
    159  * @param   pszInfo         See RTSystemQueryOSInfo.
    160  * @param   cchInfo         See RTSystemQueryOSInfo.
    161  */
    162 static int rtSystemWinQueryOSVersion(RTSYSOSINFO enmInfo, char *pszInfo, size_t cchInfo)
    163 {
    164     /*
    165      * Make sure it's terminated correctly in case of error.
    166      */
    167     *pszInfo = '\0';
    168 
    169     /*
    170      * Check that we got the windows version at init time.
    171      */
    172     AssertReturn(g_WinOsInfoEx.dwOSVersionInfoSize, VERR_WRONG_ORDER);
    173 
    174     /*
    175      * Service the request.
    176      */
    177     char szTmp[512];
    178     szTmp[0] = '\0';
    179     switch (enmInfo)
    180     {
    181         /*
    182          * The product name.
    183          */
    184         case RTSYSOSINFO_PRODUCT:
    185         {
    186             switch (g_enmWinVer)
    187             {
    188                 case kRTWinOSType_95:           strcpy(szTmp, "Windows 95"); break;
    189                 case kRTWinOSType_95SP1:        strcpy(szTmp, "Windows 95 (Service Pack 1)"); break;
    190                 case kRTWinOSType_95OSR2:       strcpy(szTmp, "Windows 95 (OSR 2)"); break;
    191                 case kRTWinOSType_98:           strcpy(szTmp, "Windows 98"); break;
    192                 case kRTWinOSType_98SP1:        strcpy(szTmp, "Windows 98 (Service Pack 1)"); break;
    193                 case kRTWinOSType_98SE:         strcpy(szTmp, "Windows 98 (Second Edition)"); break;
    194                 case kRTWinOSType_ME:           strcpy(szTmp, "Windows Me"); break;
    195                 case kRTWinOSType_NT310:        strcpy(szTmp, "Windows NT 3.10"); break;
    196                 case kRTWinOSType_NT350:        strcpy(szTmp, "Windows NT 3.50"); break;
    197                 case kRTWinOSType_NT351:        strcpy(szTmp, "Windows NT 3.51"); break;
    198                 case kRTWinOSType_NT4:          strcpy(szTmp, "Windows NT 4.0"); break;
    199                 case kRTWinOSType_2K:           strcpy(szTmp, "Windows 2000"); break;
    200                 case kRTWinOSType_XP:
    201                     strcpy(szTmp, "Windows XP");
    202                     if (g_WinOsInfoEx.wSuiteMask & VER_SUITE_PERSONAL)
    203                         strcat(szTmp, " Home");
    204                     if (    g_WinOsInfoEx.wProductType == VER_NT_WORKSTATION
    205                         && !(g_WinOsInfoEx.wSuiteMask & VER_SUITE_PERSONAL))
    206                         strcat(szTmp, " Professional");
    207 #if 0 /** @todo fixme */
    208                     if (GetSystemMetrics(SM_MEDIACENTER))
    209                         strcat(szTmp, " Media Center");
    210 #endif
    211                     break;
    212 
    213                 case kRTWinOSType_2003:         strcpy(szTmp, "Windows 2003"); break;
    214                 case kRTWinOSType_VISTA:
    215                 {
    216                     strcpy(szTmp, "Windows Vista");
    217                     rtSystemWinAppendProductType(szTmp);
    218                     break;
    219                 }
    220                 case kRTWinOSType_2008:         strcpy(szTmp, "Windows 2008"); break;
    221                 case kRTWinOSType_7:            strcpy(szTmp, "Windows 7"); break;
    222                 case kRTWinOSType_2008R2:       strcpy(szTmp, "Windows 2008 R2"); break;
    223                 case kRTWinOSType_8:            strcpy(szTmp, "Windows 8"); break;
    224                 case kRTWinOSType_2012:         strcpy(szTmp, "Windows 2012"); break;
    225                 case kRTWinOSType_81:           strcpy(szTmp, "Windows 8.1"); break;
    226                 case kRTWinOSType_2012R2:       strcpy(szTmp, "Windows 2012 R2"); break;
    227                 case kRTWinOSType_10:           strcpy(szTmp, "Windows 10"); break;
    228                 case kRTWinOSType_2016:         strcpy(szTmp, "Windows 2016"); break;
    229                 case kRTWinOSType_2019:         strcpy(szTmp, "Windows 2019"); break;
    230                 case kRTWinOSType_2022:         strcpy(szTmp, "Windows 2022"); break;
    231                 case kRTWinOSType_11:           strcpy(szTmp, "Windows 11"); break;
    232 
    233                 case kRTWinOSType_NT_UNKNOWN:
    234                     RTStrPrintf(szTmp, sizeof(szTmp), "Unknown NT v%u.%u",
    235                                 g_WinOsInfoEx.dwMajorVersion, g_WinOsInfoEx.dwMinorVersion);
    236                     break;
    237 
    238                 default:
    239                     AssertFailed();
    240                 case kRTWinOSType_UNKNOWN:
    241                     RTStrPrintf(szTmp, sizeof(szTmp), "Unknown %d v%u.%u",
    242                                 g_WinOsInfoEx.dwPlatformId, g_WinOsInfoEx.dwMajorVersion, g_WinOsInfoEx.dwMinorVersion);
    243                     break;
    244             }
    245             break;
    246         }
    247 
    248         /*
    249          * The release.
    250          */
    251         case RTSYSOSINFO_RELEASE:
    252         {
    253             RTStrPrintf(szTmp, sizeof(szTmp), "%u.%u.%u",
    254                         g_WinOsInfoEx.dwMajorVersion, g_WinOsInfoEx.dwMinorVersion, g_WinOsInfoEx.dwBuildNumber);
    255             break;
    256         }
    257 
    258 
    259         /*
    260          * Get the service pack.
    261          */
    262         case RTSYSOSINFO_SERVICE_PACK:
    263         {
    264             if (g_WinOsInfoEx.wServicePackMajor)
    265             {
    266                 if (g_WinOsInfoEx.wServicePackMinor)
    267                     RTStrPrintf(szTmp, sizeof(szTmp), "%u.%u",
    268                                 (unsigned)g_WinOsInfoEx.wServicePackMajor, (unsigned)g_WinOsInfoEx.wServicePackMinor);
    269                 else
    270                     RTStrPrintf(szTmp, sizeof(szTmp), "%u",
    271                                 (unsigned)g_WinOsInfoEx.wServicePackMajor);
    272             }
    273             else if (g_WinOsInfoEx.szCSDVersion[0])
    274             {
    275                 /* just copy the entire string. */
    276                 char *pszTmp = szTmp;
    277                 int rc = RTUtf16ToUtf8Ex(g_WinOsInfoEx.szCSDVersion, RT_ELEMENTS(g_WinOsInfoEx.szCSDVersion),
    278                                          &pszTmp, sizeof(szTmp), NULL);
    279                 if (RT_SUCCESS(rc))
    280                     RTStrStripR(szTmp);
    281                 else
    282                     szTmp[0] = '\0';
    283                 AssertCompile(sizeof(szTmp) > sizeof(g_WinOsInfoEx.szCSDVersion));
    284             }
    285             else
    286             {
    287                 switch (g_enmWinVer)
    288                 {
    289                     case kRTWinOSType_95SP1:    strcpy(szTmp, "1"); break;
    290                     case kRTWinOSType_98SP1:    strcpy(szTmp, "1"); break;
    291                     default:
    292                         break;
    293                 }
    294             }
    295             break;
    296         }
    297 
    298         default:
    299             AssertFatalFailed();
    300     }
    301 
    302     /*
    303      * Copy the result to the return buffer.
    304      */
    305     size_t cchTmp = strlen(szTmp);
    306     Assert(cchTmp < sizeof(szTmp));
    307     if (cchTmp < cchInfo)
    308     {
    309         memcpy(pszInfo, szTmp, cchTmp + 1);
    310         return VINF_SUCCESS;
    311     }
    312     memcpy(pszInfo, szTmp, cchInfo - 1);
    313     pszInfo[cchInfo - 1] = '\0';
    314     return VERR_BUFFER_OVERFLOW;
    315 }
    316 
    317 
    318 
    319 RTDECL(int) RTSystemQueryOSInfo(RTSYSOSINFO enmInfo, char *pszInfo, size_t cchInfo)
    320 {
    321     /*
    322      * Quick validation.
    323      */
    324     AssertReturn(enmInfo > RTSYSOSINFO_INVALID && enmInfo < RTSYSOSINFO_END, VERR_INVALID_PARAMETER);
    325     AssertPtrReturn(pszInfo, VERR_INVALID_POINTER);
    326     if (!cchInfo)
    327         return VERR_BUFFER_OVERFLOW;
    328 
    329 
    330     /*
    331      * Handle the request.
    332      */
    333     switch (enmInfo)
    334     {
    335         case RTSYSOSINFO_PRODUCT:
    336         case RTSYSOSINFO_RELEASE:
    337         case RTSYSOSINFO_SERVICE_PACK:
    338             return rtSystemWinQueryOSVersion(enmInfo, pszInfo, cchInfo);
    339 
    340         case RTSYSOSINFO_VERSION:
    341         default:
    342             *pszInfo = '\0';
    343     }
    344 
    345     return VERR_NOT_SUPPORTED;
    346 }
    34737
    34838
    34939RTDECL(uint32_t) RTSystemGetNtBuildNo(void)
    35040{
     41    Assert(g_WinOsInfoEx.dwOSVersionInfoSize > 0);
    35142    return g_WinOsInfoEx.dwBuildNumber;
    35243}
     
    35546RTDECL(uint64_t) RTSystemGetNtVersion(void)
    35647{
     48    Assert(g_WinOsInfoEx.dwOSVersionInfoSize > 0);
    35749    return RTSYSTEM_MAKE_NT_VERSION(g_WinOsInfoEx.dwMajorVersion, g_WinOsInfoEx.dwMinorVersion, g_WinOsInfoEx.dwBuildNumber);
    35850}
  • trunk/src/VBox/Runtime/testcase/Makefile.kmk

    r91768 r92792  
    112112        tstRand \
    113113        tstRTReqPool \
     114        tstRTSemEvent \
    114115        tstRTSemEventMulti \
    115116        tstSemMutex \
     
    614615tstSemMutex_SOURCES = tstSemMutex.cpp
    615616
     617tstRTSemEvent_TEMPLATE = VBOXR3TSTEXE
     618tstRTSemEvent_SOURCES = tstRTSemEvent.cpp
     619
    616620tstRTSemEventMulti_TEMPLATE = VBOXR3TSTEXE
    617621tstRTSemEventMulti_SOURCES = tstRTSemEventMulti.cpp
  • trunk/src/VBox/Runtime/testcase/tstRTSemEvent.cpp

    r92778 r92792  
    5656*********************************************************************************************************************************/
    5757/** Pair of event semphores for the first benchmark test. */
    58 static RTSEMEVENT   g_ahEvtBench1[2];
    59 static uint64_t     g_cBench1Iterations;
    60 static uint64_t     g_uTimeoutBench1;
    61 static uint64_t     g_fWaitBench1;
     58static RTSEMEVENT           g_ahEvtBench1[2];
     59static uint64_t             g_uTimeoutBench1;
     60static uint64_t             g_fWaitBench1;
     61static uint64_t volatile    g_cBench1Iterations;
    6262
    6363
     
    135135     * Report the result.
    136136     */
    137     RTTestValue(g_hTest, "Throughput", g_cBench1Iterations * RT_NS_1SEC / cNsElapsed, RTTESTUNIT_OCCURRENCES_PER_SEC);
    138     RTTestValue(g_hTest, "Roundtrip", cNsElapsed / g_cBench1Iterations, RTTESTUNIT_NS_PER_OCCURRENCE);
    139 
     137    uint64_t cIterations = g_cBench1Iterations;
     138    RTTestValue(g_hTest, "Throughput", cIterations * RT_NS_1SEC / cNsElapsed, RTTESTUNIT_OCCURRENCES_PER_SEC);
     139    RTTestValue(g_hTest, "Roundtrip", cNsElapsed / RT_MAX(cIterations, 1), RTTESTUNIT_NS_PER_OCCURRENCE);
    140140}
    141141
     
    190190*   Basic tests                                                                                                                  *
    191191*********************************************************************************************************************************/
     192
     193/**
     194 * Just do a number of short waits and calculate min, max and average.
     195 */
     196static void resolution(void)
     197{
     198    RTTestISub("Timeout resolution");
     199
     200    RTSEMEVENT hSem;
     201    RTTESTI_CHECK_RC_RETV(RTSemEventCreate(&hSem), VINF_SUCCESS);
     202
     203    uint64_t cNsMin   = UINT64_MAX;
     204    uint64_t cNsMax   = 0;
     205    uint64_t cNsTotal = 0;
     206    uint32_t cLoops;
     207    for (cLoops = 0; cLoops < 256; cLoops++)
     208    {
     209        uint64_t const nsStart    = RTTimeNanoTS();
     210        int rc = RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_NORESUME | RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_NANOSECS, RT_NS_1US);
     211        uint64_t const cNsElapsed = RTTimeNanoTS() - nsStart;
     212        RTTESTI_CHECK_RC(rc, VERR_TIMEOUT);
     213        cNsTotal += cNsElapsed;
     214        if (cNsElapsed < cNsMin)
     215            cNsMin = cNsElapsed;
     216        if (cNsElapsed > cNsMax)
     217            cNsMax = cNsElapsed;
     218    }
     219
     220    RTTestIValue("min", cNsMin, RTTESTUNIT_NS);
     221    RTTestIValue("max", cNsMax, RTTESTUNIT_NS);
     222    RTTestIValue("average", cNsTotal / cLoops, RTTESTUNIT_NS);
     223    RTTestIValue("RTSemEventGetResolution", RTSemEventGetResolution(), RTTESTUNIT_NS);
     224
     225    RTTESTI_CHECK_RC_RETV(RTSemEventDestroy(hSem), VINF_SUCCESS);
     226}
     227
    192228
    193229
     
    341377    {
    342378        test1();
     379        resolution();
    343380    }
    344381    if (!RTTestErrorCount(g_hTest))
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