RTDECL(int) RTSemXRoadsDestroy(RTSEMXROADS hXRoads)
{
    /*
     * Validate input.
     */
    RTSEMXROADSINTERNAL *pThis = hXRoads;
    if (pThis == NIL_RTSEMXROADS)
        return VINF_SUCCESS;
    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
    AssertReturn(pThis->u32Magic == RTSEMXROADS_MAGIC, VERR_INVALID_HANDLE);
    Assert(!(ASMAtomicReadU64(&pThis->u64State) & (RTSEMXROADS_CNT_NS_MASK | RTSEMXROADS_CNT_EW_MASK)));

    /*
     * Invalidate the object and free up the resources.
     */
    AssertReturn(ASMAtomicCmpXchgU32(&pThis->u32Magic, RTSEMXROADS_MAGIC_DEAD, RTSEMXROADS_MAGIC), VERR_INVALID_HANDLE);

    RTSEMEVENTMULTI hEvt;
    ASMAtomicXchgHandle(&pThis->aDirs[0].hEvt, NIL_RTSEMEVENTMULTI, &hEvt);
    int rc = RTSemEventMultiDestroy(hEvt);
    AssertRC(rc);

    ASMAtomicXchgHandle(&pThis->aDirs[1].hEvt, NIL_RTSEMEVENTMULTI, &hEvt);
    rc = RTSemEventMultiDestroy(hEvt);
    AssertRC(rc);

    RTMemFree(pThis);
    return VINF_SUCCESS;
}
Exemplo n.º 2
0
/**
 * Free an mbox.
 */
void sys_mbox_free(sys_mbox_t mbox)
{
    Assert(mbox != NULL);
    LWIPMutexDestroy(mbox->mutex);
    RTSemEventMultiDestroy(mbox->nonempty);
    RTSemEventMultiDestroy(mbox->nonfull);
    RTMemFree(mbox);
}
static void testBasics(void)
{
    RTTestISub("Basics");

    RTSEMEVENTMULTI hSem;
    RTTESTI_CHECK_RC_RETV(RTSemEventMultiCreate(&hSem), VINF_SUCCESS);

    /* The semaphore is created in a reset state, calling reset explicitly
       shouldn't make any difference. */
    testBasicsWaitTimeout(hSem, 0);
    RTTESTI_CHECK_RC_RETV(RTSemEventMultiReset(hSem), VINF_SUCCESS);
    testBasicsWaitTimeout(hSem, 1);
    if (RTTestIErrorCount())
        return;

    /* When signalling the semaphore all successive wait calls shall
       succeed, signalling it again should make no difference. */
    RTTESTI_CHECK_RC_RETV(RTSemEventMultiSignal(hSem), VINF_SUCCESS);
    testBasicsWaitSuccess(hSem, 2);
    if (RTTestIErrorCount())
        return;

    /* After resetting it we should time out again. */
    RTTESTI_CHECK_RC_RETV(RTSemEventMultiReset(hSem), VINF_SUCCESS);
    testBasicsWaitTimeout(hSem, 3);
    if (RTTestIErrorCount())
        return;

    /* The number of resets or signal calls shouldn't matter. */
    RTTESTI_CHECK_RC_RETV(RTSemEventMultiReset(hSem), VINF_SUCCESS);
    RTTESTI_CHECK_RC_RETV(RTSemEventMultiReset(hSem), VINF_SUCCESS);
    RTTESTI_CHECK_RC_RETV(RTSemEventMultiReset(hSem), VINF_SUCCESS);
    testBasicsWaitTimeout(hSem, 4);

    RTTESTI_CHECK_RC_RETV(RTSemEventMultiSignal(hSem), VINF_SUCCESS);
    RTTESTI_CHECK_RC_RETV(RTSemEventMultiSignal(hSem), VINF_SUCCESS);
    RTTESTI_CHECK_RC_RETV(RTSemEventMultiSignal(hSem), VINF_SUCCESS);
    RTTESTI_CHECK_RC_RETV(RTSemEventMultiSignal(hSem), VINF_SUCCESS);
    RTTESTI_CHECK_RC_RETV(RTSemEventMultiSignal(hSem), VINF_SUCCESS);
    testBasicsWaitSuccess(hSem, 5);

    RTTESTI_CHECK_RC_RETV(RTSemEventMultiReset(hSem), VINF_SUCCESS);
    testBasicsWaitTimeout(hSem, 6);

    /* Destroy it. */
    RTTESTI_CHECK_RC_RETV(RTSemEventMultiDestroy(hSem), VINF_SUCCESS);
    RTTESTI_CHECK_RC_RETV(RTSemEventMultiDestroy(NIL_RTSEMEVENTMULTI), VINF_SUCCESS);

    /* Whether it is reset (above), signalled or not used shouldn't matter.  */
    RTTESTI_CHECK_RC_RETV(RTSemEventMultiCreate(&hSem), VINF_SUCCESS);
    RTTESTI_CHECK_RC_RETV(RTSemEventMultiSignal(hSem), VINF_SUCCESS);
    RTTESTI_CHECK_RC_RETV(RTSemEventMultiDestroy(hSem), VINF_SUCCESS);

    RTTESTI_CHECK_RC_RETV(RTSemEventMultiCreate(&hSem), VINF_SUCCESS);
    RTTESTI_CHECK_RC_RETV(RTSemEventMultiDestroy(hSem), VINF_SUCCESS);

    RTTestISubDone();
}
Exemplo n.º 4
0
/**
 * Free an mbox.
 */
void sys_mbox_free(sys_mbox_t *pvMbox)
{
    struct sys_mbox *mbox = NULL;
    Assert(pvMbox && *pvMbox);
    mbox = (struct sys_mbox*)*pvMbox;
    LWIPMutexDestroy((mbox)->mutex);
    RTSemEventMultiDestroy((mbox)->nonempty);
    RTSemEventMultiDestroy((mbox)->nonfull);
    RTMemFree(mbox);
    *pvMbox = NULL;
}
Exemplo n.º 5
0
/**
 * Destroys the per thread data.
 *
 * @param   pThread     The thread to destroy.
 */
static void rtThreadDestroy(PRTTHREADINT pThread)
{
    RTSEMEVENTMULTI hEvt1, hEvt2;
    /*
     * Remove it from the tree and mark it as dead.
     *
     * Threads that has seen rtThreadTerminate and should already have been
     * removed from the tree. There is probably no thread that  should
     * require removing here. However, be careful making sure that cRefs
     * isn't 0 if we do or we'll blow up because the strict locking code
     * will be calling us back.
     */
    if (ASMBitTest(&pThread->fIntFlags, RTTHREADINT_FLAG_IN_TREE_BIT))
    {
        ASMAtomicIncU32(&pThread->cRefs);
        rtThreadRemove(pThread);
        ASMAtomicDecU32(&pThread->cRefs);
    }

    /*
     * Invalidate the thread structure.
     */
#ifdef IN_RING3
    rtLockValidatorSerializeDestructEnter();

    rtLockValidatorDeletePerThread(&pThread->LockValidator);
#endif
#ifdef RT_WITH_ICONV_CACHE
    rtStrIconvCacheDestroy(pThread);
#endif
    ASMAtomicXchgU32(&pThread->u32Magic, RTTHREADINT_MAGIC_DEAD);
    ASMAtomicWritePtr(&pThread->Core.Key, (void *)NIL_RTTHREAD);
    pThread->enmType         = RTTHREADTYPE_INVALID;
    hEvt1    = pThread->EventUser;
    pThread->EventUser       = NIL_RTSEMEVENTMULTI;
    hEvt2    = pThread->EventTerminated;
    pThread->EventTerminated = NIL_RTSEMEVENTMULTI;

#ifdef IN_RING3
    rtLockValidatorSerializeDestructLeave();
#endif

    /*
     * Destroy semaphore resources and free the bugger.
     */
    RTSemEventMultiDestroy(hEvt1);
    if (hEvt2 != NIL_RTSEMEVENTMULTI)
        RTSemEventMultiDestroy(hEvt2);

    rtThreadNativeDestroy(pThread);
    RTMemFree(pThread);
}
static void test1(void)
{
    RTTestISub("Three threads");

    /*
     * Create the threads and let them block on the event multi semaphore.
     */
    RTSEMEVENTMULTI hSem;
    RTTESTI_CHECK_RC_RETV(RTSemEventMultiCreate(&hSem), VINF_SUCCESS);

    RTTHREAD hThread2;
    RTTESTI_CHECK_RC_RETV(RTThreadCreate(&hThread2, test1Thread2, &hSem, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "test2"), VINF_SUCCESS);
    RTThreadSleep(100);

    RTTHREAD hThread1;
    RTTESTI_CHECK_RC_RETV(RTThreadCreate(&hThread1, test1Thread1, &hSem, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "test1"), VINF_SUCCESS);

    /* Force first thread (which has a timeout of 1 second) to timeout in the
     * first wait, and the second wait will succeed. */
    RTTESTI_CHECK_RC(RTThreadSleep(1500), VINF_SUCCESS);
    RTTESTI_CHECK_RC(RTSemEventMultiSignal(hSem), VINF_SUCCESS);
    RTTESTI_CHECK_RC(RTThreadWait(hThread1, 5000, NULL), VINF_SUCCESS);
    RTTESTI_CHECK_RC(RTThreadWait(hThread2, 5000, NULL), VINF_SUCCESS);
    RTTESTI_CHECK_RC(RTSemEventMultiDestroy(hSem), VINF_SUCCESS);
}
/** @copydoc VBOXSERVICE::pfnInit */
static DECLCALLBACK(int) VBoxServiceAutoMountInit(void)
{
    VBoxServiceVerbose(3, "VBoxServiceAutoMountInit\n");

    int rc = RTSemEventMultiCreate(&g_AutoMountEvent);
    AssertRCReturn(rc, rc);

    rc = VbglR3SharedFolderConnect(&g_SharedFoldersSvcClientID);
    if (RT_SUCCESS(rc))
    {
        VBoxServiceVerbose(3, "VBoxServiceAutoMountInit: Service Client ID: %#x\n", g_SharedFoldersSvcClientID);
    }
    else
    {
        /* If the service was not found, we disable this service without
           causing VBoxService to fail. */
        if (rc == VERR_HGCM_SERVICE_NOT_FOUND) /* Host service is not available. */
        {
            VBoxServiceVerbose(0, "VBoxServiceAutoMountInit: Shared Folders service is not available\n");
            rc = VERR_SERVICE_DISABLED;
        }
        else
            VBoxServiceError("Control: Failed to connect to the Shared Folders service! Error: %Rrc\n", rc);
        RTSemEventMultiDestroy(g_AutoMountEvent);
        g_AutoMountEvent = NIL_RTSEMEVENTMULTI;
    }

    return rc;
}
Exemplo n.º 8
0
RTDECL(int) RTSemRWDestroy(RTSEMRW hRWSem)
{
    /*
     * Validate input.
     */
    RTSEMRWINTERNAL *pThis = hRWSem;
    if (pThis == NIL_RTSEMRW)
        return VINF_SUCCESS;
    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
    AssertReturn(pThis->u32Magic == RTSEMRW_MAGIC, VERR_INVALID_HANDLE);
    Assert(!(ASMAtomicReadU64(&pThis->u64State) & (RTSEMRW_CNT_RD_MASK | RTSEMRW_CNT_WR_MASK)));

    /*
     * Invalidate the object and free up the resources.
     */
    AssertReturn(ASMAtomicCmpXchgU32(&pThis->u32Magic, ~RTSEMRW_MAGIC, RTSEMRW_MAGIC), VERR_INVALID_HANDLE);

    RTSEMEVENTMULTI hEvtRead;
    ASMAtomicXchgHandle(&pThis->hEvtRead, NIL_RTSEMEVENTMULTI, &hEvtRead);
    int rc = RTSemEventMultiDestroy(hEvtRead);
    AssertRC(rc);

    RTSEMEVENT hEvtWrite;
    ASMAtomicXchgHandle(&pThis->hEvtWrite, NIL_RTSEMEVENT, &hEvtWrite);
    rc = RTSemEventDestroy(hEvtWrite);
    AssertRC(rc);

#ifdef RTSEMRW_STRICT
    RTLockValidatorRecSharedDelete(&pThis->ValidatorRead);
    RTLockValidatorRecExclDelete(&pThis->ValidatorWrite);
#endif
    RTMemFree(pThis);
    return VINF_SUCCESS;
}
Exemplo n.º 9
0
/**
 * Uninitializes the instance and sets the ready flag to FALSE.
 *
 * Called either from FinalRelease() or by the parent when it gets destroyed.
 */
void Progress::uninit()
{
    LogFlowThisFunc(("\n"));

    /* Enclose the state transition Ready->InUninit->NotReady */
    AutoUninitSpan autoUninitSpan(this);
    if (autoUninitSpan.uninitDone())
        return;

    /* wake up all threads still waiting on occasion */
    if (mWaitersCount > 0)
    {
        LogFlow(("WARNING: There are still %d threads waiting for '%s' completion!\n",
                 mWaitersCount, mDescription.c_str()));
        RTSemEventMultiSignal(mCompletedSem);
    }

    RTSemEventMultiDestroy(mCompletedSem);

    /* release initiator (effective only if mInitiator has been assigned in
 *      * init()) */
    unconst(mInitiator).setNull();

#if !defined(VBOX_COM_INPROC)
    if (mParent)
    {
        /* remove the added progress on failure to complete the initialization */
        if (autoUninitSpan.initFailed() && mId.isValid() && !mId.isZero())
            mParent->i_removeProgress(mId.ref());

        unconst(mParent) = NULL;
    }
#endif
}
Exemplo n.º 10
0
/** @copydoc VBOXSERVICE::pfnTerm */
static DECLCALLBACK(void) VBoxServiceVMInfoTerm(void)
{
    if (g_hVMInfoEvent != NIL_RTSEMEVENTMULTI)
    {
        /** @todo temporary solution: Zap all values which are not valid
         *        anymore when VM goes down (reboot/shutdown ). Needs to
         *        be replaced with "temporary properties" later.
         *
         *        One idea is to introduce a (HGCM-)session guest property
         *        flag meaning that a guest property is only valid as long
         *        as the HGCM session isn't closed (e.g. guest application
         *        terminates). [don't remove till implemented]
         */
        /** @todo r=bird: Drop the VbglR3GuestPropDelSet call here and use the cache
         *        since it remembers what we've written. */
        /* Delete the "../Net" branch. */
        const char *apszPat[1] = { "/VirtualBox/GuestInfo/Net/*" };
        int rc = VbglR3GuestPropDelSet(g_uVMInfoGuestPropSvcClientID, &apszPat[0], RT_ELEMENTS(apszPat));

        /* Destroy property cache. */
        VBoxServicePropCacheDestroy(&g_VMInfoPropCache);

        /* Disconnect from guest properties service. */
        rc = VbglR3GuestPropDisconnect(g_uVMInfoGuestPropSvcClientID);
        if (RT_FAILURE(rc))
            VBoxServiceError("VMInfo: Failed to disconnect from guest property service! Error: %Rrc\n", rc);
        g_uVMInfoGuestPropSvcClientID = 0;

        RTSemEventMultiDestroy(g_hVMInfoEvent);
        g_hVMInfoEvent = NIL_RTSEMEVENTMULTI;
    }
}
Exemplo n.º 11
0
SUPDECL(int) SUPSemEventMultiCreate(PSUPDRVSESSION pSession, PSUPSEMEVENTMULTI phEventMulti)
{
    int             rc;
    RTSEMEVENTMULTI hEventMultReal;

    /*
     * Input validation.
     */
    AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
    AssertPtrReturn(phEventMulti, VERR_INVALID_POINTER);

    /*
     * Create the event semaphore object.
     */
    rc = RTSemEventMultiCreate(&hEventMultReal);
    if (RT_SUCCESS(rc))
    {
        void *pvObj = SUPR0ObjRegister(pSession, SUPDRVOBJTYPE_SEM_EVENT_MULTI, supR0SemEventMultiDestructor, hEventMultReal, NULL);
        if (pvObj)
        {
            uint32_t h32;
            rc = RTHandleTableAllocWithCtx(pSession->hHandleTable, pvObj, SUPDRV_HANDLE_CTX_EVENT_MULTI, &h32);
            if (RT_SUCCESS(rc))
            {
                *phEventMulti = (SUPSEMEVENTMULTI)(uintptr_t)h32;
                return VINF_SUCCESS;
            }
            SUPR0ObjRelease(pvObj, pSession);
        }
        else
            RTSemEventMultiDestroy(hEventMultReal);
    }
    return rc;
}
Exemplo n.º 12
0
/**
 * @interface_method_impl{VBOXSERVICE,pfnTerm}
 */
static DECLCALLBACK(void) vgsvcVMStatsTerm(void)
{
    if (g_VMStatEvent != NIL_RTSEMEVENTMULTI)
    {
        RTSemEventMultiDestroy(g_VMStatEvent);
        g_VMStatEvent = NIL_RTSEMEVENTMULTI;
    }
}
Exemplo n.º 13
0
/**
 * Time constrained test with and unlimited  N threads.
 */
static void tst3(uint32_t cThreads, uint32_t cbObject, int iMethod, uint32_t cSecs)
{
    RTTestISubF("Benchmark - %u threads, %u bytes, %u secs, %s", cThreads, cbObject, cSecs,
                iMethod == 0 ? "RTMemCache"
                : "RTMemAlloc");

    /*
     * Create a cache with unlimited space, a start semaphore and line up
     * the threads.
     */
    RTTESTI_CHECK_RC_RETV(RTMemCacheCreate(&g_hMemCache, cbObject, 0 /*cbAlignment*/, UINT32_MAX, NULL, NULL, NULL, 0 /*fFlags*/), VINF_SUCCESS);

    RTSEMEVENTMULTI hEvt;
    RTTESTI_CHECK_RC_OK_RETV(RTSemEventMultiCreate(&hEvt));

    TST3THREAD aThreads[64];
    RTTESTI_CHECK_RETV(cThreads < RT_ELEMENTS(aThreads));

    ASMAtomicWriteBool(&g_fTst3Stop, false);
    for (uint32_t i = 0; i < cThreads; i++)
    {
        aThreads[i].hThread     = NIL_RTTHREAD;
        aThreads[i].cIterations = 0;
        aThreads[i].fUseCache   = iMethod == 0;
        aThreads[i].cbObject    = cbObject;
        aThreads[i].hEvt        = hEvt;
        RTTESTI_CHECK_RC_OK_RETV(RTThreadCreateF(&aThreads[i].hThread, tst3Thread, &aThreads[i], 0,
                                                 RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "tst3-%u", i));
    }

    /*
     * Start the race.
     */
    RTTimeNanoTS(); /* warmup */

    uint64_t uStartTS = RTTimeNanoTS();
    RTTESTI_CHECK_RC_OK_RETV(RTSemEventMultiSignal(hEvt));
    RTThreadSleep(cSecs * 1000);
    ASMAtomicWriteBool(&g_fTst3Stop, true);
    for (uint32_t i = 0; i < cThreads; i++)
        RTTESTI_CHECK_RC_OK_RETV(RTThreadWait(aThreads[i].hThread, 60*1000, NULL));
    uint64_t cElapsedNS = RTTimeNanoTS() - uStartTS;

    /*
     * Sum up the counts.
     */
    uint64_t cIterations = 0;
    for (uint32_t i = 0; i < cThreads; i++)
        cIterations += aThreads[i].cIterations;

    RTTestIPrintf(RTTESTLVL_ALWAYS, "%'8u iterations per second, %'llu ns on avg\n",
                  (unsigned)((long double)cIterations * 1000000000.0 / cElapsedNS),
                  cElapsedNS / cIterations);

    /* clean up */
    RTTESTI_CHECK_RC(RTMemCacheDestroy(g_hMemCache), VINF_SUCCESS);
    RTTESTI_CHECK_RC_OK(RTSemEventMultiDestroy(hEvt));
}
Exemplo n.º 14
0
RTDECL(int) RTSemRWCreateEx(PRTSEMRW phRWSem, uint32_t fFlags,
                            RTLOCKVALCLASS hClass, uint32_t uSubClass, const char *pszNameFmt, ...)
{
    AssertReturn(!(fFlags & ~RTSEMRW_FLAGS_NO_LOCK_VAL), VERR_INVALID_PARAMETER);

    RTSEMRWINTERNAL *pThis = (RTSEMRWINTERNAL *)RTMemAlloc(sizeof(*pThis));
    if (!pThis)
        return VERR_NO_MEMORY;

    int rc = RTSemEventMultiCreate(&pThis->hEvtRead);
    if (RT_SUCCESS(rc))
    {
        rc = RTSemEventCreate(&pThis->hEvtWrite);
        if (RT_SUCCESS(rc))
        {
            pThis->u32Magic             = RTSEMRW_MAGIC;
            pThis->u32Padding           = 0;
            pThis->u64State             = 0;
            pThis->hNativeWriter        = NIL_RTNATIVETHREAD;
            pThis->cWriterReads         = 0;
            pThis->cWriteRecursions     = 0;
            pThis->fNeedReset           = false;
#ifdef RTSEMRW_STRICT
            bool const fLVEnabled = !(fFlags & RTSEMRW_FLAGS_NO_LOCK_VAL);
            if (!pszNameFmt)
            {
                static uint32_t volatile s_iSemRWAnon = 0;
                uint32_t i = ASMAtomicIncU32(&s_iSemRWAnon) - 1;
                RTLockValidatorRecExclInit(&pThis->ValidatorWrite, hClass, uSubClass, pThis,
                                           fLVEnabled, "RTSemRW-%u", i);
                RTLockValidatorRecSharedInit(&pThis->ValidatorRead, hClass, uSubClass, pThis,
                                             false /*fSignaller*/, fLVEnabled, "RTSemRW-%u", i);
            }
            else
            {
                va_list va;
                va_start(va, pszNameFmt);
                RTLockValidatorRecExclInitV(&pThis->ValidatorWrite, hClass, uSubClass, pThis,
                                            fLVEnabled, pszNameFmt, va);
                va_end(va);
                va_start(va, pszNameFmt);
                RTLockValidatorRecSharedInitV(&pThis->ValidatorRead, hClass, uSubClass, pThis,
                                              false /*fSignaller*/, fLVEnabled, pszNameFmt, va);
                va_end(va);
            }
            RTLockValidatorRecMakeSiblings(&pThis->ValidatorWrite.Core, &pThis->ValidatorRead.Core);
#endif

            *phRWSem = pThis;
            return VINF_SUCCESS;
        }
        RTSemEventMultiDestroy(pThis->hEvtRead);
    }
    return rc;
}
Exemplo n.º 15
0
/** @copydoc VBOXSERVICE::pfnInit */
static DECLCALLBACK(int) VBoxServiceVMInfoInit(void)
{
    /*
     * If not specified, find the right interval default.
     * Then create the event sem to block on.
     */
    if (!g_cMsVMInfoInterval)
        g_cMsVMInfoInterval = g_DefaultInterval * 1000;
    if (!g_cMsVMInfoInterval)
        g_cMsVMInfoInterval = 10 * 1000;

    int rc = RTSemEventMultiCreate(&g_hVMInfoEvent);
    AssertRCReturn(rc, rc);

    VbglR3GetSessionId(&g_idVMInfoSession);
    /* The status code is ignored as this information is not available with VBox < 3.2.10. */

    rc = VbglR3GuestPropConnect(&g_uVMInfoGuestPropSvcClientID);
    if (RT_SUCCESS(rc))
        VBoxServiceVerbose(3, "VMInfo: Property Service Client ID: %#x\n", g_uVMInfoGuestPropSvcClientID);
    else
    {
        /* If the service was not found, we disable this service without
           causing VBoxService to fail. */
        if (rc == VERR_HGCM_SERVICE_NOT_FOUND) /* Host service is not available. */
        {
            VBoxServiceVerbose(0, "VMInfo: Guest property service is not available, disabling the service\n");
            rc = VERR_SERVICE_DISABLED;
        }
        else
            VBoxServiceError("VMInfo: Failed to connect to the guest property service! Error: %Rrc\n", rc);
        RTSemEventMultiDestroy(g_hVMInfoEvent);
        g_hVMInfoEvent = NIL_RTSEMEVENTMULTI;
    }

    if (RT_SUCCESS(rc))
    {
        VBoxServicePropCacheCreate(&g_VMInfoPropCache, g_uVMInfoGuestPropSvcClientID);

        /*
         * Declare some guest properties with flags and reset values.
         */
        VBoxServicePropCacheUpdateEntry(&g_VMInfoPropCache, "/VirtualBox/GuestInfo/OS/LoggedInUsersList",
                                        VBOXSERVICEPROPCACHEFLAG_TEMPORARY | VBOXSERVICEPROPCACHEFLAG_TRANSIENT, NULL /* Delete on exit */);
        VBoxServicePropCacheUpdateEntry(&g_VMInfoPropCache, "/VirtualBox/GuestInfo/OS/LoggedInUsers",
                                        VBOXSERVICEPROPCACHEFLAG_TEMPORARY | VBOXSERVICEPROPCACHEFLAG_TRANSIENT, "0");
        VBoxServicePropCacheUpdateEntry(&g_VMInfoPropCache, "/VirtualBox/GuestInfo/OS/NoLoggedInUsers",
                                        VBOXSERVICEPROPCACHEFLAG_TEMPORARY | VBOXSERVICEPROPCACHEFLAG_TRANSIENT, "true");
        VBoxServicePropCacheUpdateEntry(&g_VMInfoPropCache, "/VirtualBox/GuestInfo/Net/Count",
                                        VBOXSERVICEPROPCACHEFLAG_TEMPORARY | VBOXSERVICEPROPCACHEFLAG_ALWAYS_UPDATE, NULL /* Delete on exit */);
    }
    return rc;
}
Exemplo n.º 16
0
/**
 * Frees a request.
 *
 * @param   pReq                The request.
 */
DECLHIDDEN(void) rtReqFreeIt(PRTREQINT pReq)
{
    Assert(pReq->u32Magic == RTREQ_MAGIC);
    Assert(pReq->cRefs == 0);

    pReq->u32Magic     = RTREQ_MAGIC_DEAD;
    RTSemEventDestroy(pReq->EventSem);
    pReq->EventSem     = NIL_RTSEMEVENT;
    RTSemEventMultiDestroy(pReq->hPushBackEvt);
    pReq->hPushBackEvt = NIL_RTSEMEVENTMULTI;
    RTMemFree(pReq);
}
/** @copydoc VBOXSERVICE::pfnTerm */
static DECLCALLBACK(void) VBoxServiceAutoMountTerm(void)
{
    VBoxServiceVerbose(3, "VBoxServiceAutoMountTerm\n");

    VbglR3SharedFolderDisconnect(g_SharedFoldersSvcClientID);
    g_SharedFoldersSvcClientID = 0;

    if (g_AutoMountEvent != NIL_RTSEMEVENTMULTI)
    {
        RTSemEventMultiDestroy(g_AutoMountEvent);
        g_AutoMountEvent = NIL_RTSEMEVENTMULTI;
    }
    return;
}
/**
 * @interface_method_impl{PDMDEVREG,pfnDestruct}
 */
static DECLCALLBACK(int) gimdevR3Destruct(PPDMDEVINS pDevIns)
{
    PGIMDEV  pThis    = PDMINS_2_DATA(pDevIns, PGIMDEV);
    PVM      pVM      = PDMDevHlpGetVM(pDevIns);
    uint32_t cRegions = 0;

    PGIMMMIO2REGION pCur = GIMR3GetMmio2Regions(pVM, &cRegions);
    for (uint32_t i = 0; i < cRegions; i++, pCur++)
    {
        int rc = PDMDevHlpMMIOExDeregister(pDevIns, NULL, pCur->iRegion);
        if (RT_FAILURE(rc))
            return rc;
    }

    /*
     * Signal and wait for the debug thread to terminate.
     */
    if (pThis->hDbgRecvThread != NIL_RTTHREAD)
    {
        pThis->fDbgRecvThreadShutdown = true;
        if (pThis->Dbg.hDbgRecvThreadSem != NIL_RTSEMEVENT)
            RTSemEventMultiSignal(pThis->Dbg.hDbgRecvThreadSem);

        int rc = RTThreadWait(pThis->hDbgRecvThread, 20000, NULL /*prc*/);
        if (RT_SUCCESS(rc))
            pThis->hDbgRecvThread = NIL_RTTHREAD;
        else
        {
            LogRel(("GIMDev: Debug thread did not terminate, rc=%Rrc!\n", rc));
            return VERR_RESOURCE_BUSY;
        }
    }

    /*
     * Now clean up the semaphore & buffer now that the thread is gone.
     */
    if (pThis->Dbg.hDbgRecvThreadSem != NIL_RTSEMEVENT)
    {
        RTSemEventMultiDestroy(pThis->Dbg.hDbgRecvThreadSem);
        pThis->Dbg.hDbgRecvThreadSem = NIL_RTSEMEVENTMULTI;
    }
    if (pThis->Dbg.pvDbgRecvBuf)
    {
        RTMemFree(pThis->Dbg.pvDbgRecvBuf);
        pThis->Dbg.pvDbgRecvBuf = NULL;
    }

    return VINF_SUCCESS;
}
Exemplo n.º 19
0
/**
 * Create new mbox.
 */
err_t sys_mbox_new(sys_mbox_t *pvMbox, int size)
{
    int rc;
    struct sys_mbox *mbox = NULL;

    if (pvMbox == NULL)
        return ERR_ARG;
    mbox = RTMemAllocZ(sizeof(struct sys_mbox));
    Assert(mbox != NULL);
    if (!mbox)
        return ERR_MEM;
    rc = LWIPMutexCreate(&mbox->mutex);
    AssertRC(rc);
    if (RT_FAILURE(rc))
    {
        RTMemFree(mbox);
        return ERR_VAL;
    }
    rc = RTSemEventMultiCreate(&mbox->nonempty);
    AssertRC(rc);
    if (RT_FAILURE(rc))
    {
        rc = LWIPMutexDestroy(mbox->mutex);
        AssertRC(rc);
        RTMemFree(mbox);
        return ERR_VAL;
    }
    rc = RTSemEventMultiCreate(&mbox->nonfull);
    AssertRC(rc);
    if (RT_FAILURE(rc))
    {
        rc = RTSemEventMultiDestroy(mbox->nonempty);
        AssertRC(rc);
        rc = LWIPMutexDestroy(mbox->mutex);
        AssertRC(rc);
        RTMemFree(mbox);
        return ERR_VAL;
    }
    mbox->valid = 1;
    *pvMbox = mbox;
    return ERR_OK;
}
Exemplo n.º 20
0
/**
 * Allocates a per thread data structure and initializes the basic fields.
 *
 * @returns Pointer to per thread data structure.
 *          This is reference once.
 * @returns NULL on failure.
 * @param   enmType     The thread type.
 * @param   fFlags      The thread flags.
 * @param   fIntFlags   The internal thread flags.
 * @param   pszName     Pointer to the thread name.
 */
PRTTHREADINT rtThreadAlloc(RTTHREADTYPE enmType, unsigned fFlags, uint32_t fIntFlags, const char *pszName)
{
    PRTTHREADINT pThread = (PRTTHREADINT)RTMemAllocZ(sizeof(RTTHREADINT));
    if (pThread)
    {
        size_t cchName;
        int rc;

        pThread->Core.Key   = (void*)NIL_RTTHREAD;
        pThread->u32Magic   = RTTHREADINT_MAGIC;
        cchName = strlen(pszName);
        if (cchName >= RTTHREAD_NAME_LEN)
            cchName = RTTHREAD_NAME_LEN - 1;
        memcpy(pThread->szName, pszName, cchName);
        pThread->szName[cchName] = '\0';
        pThread->cRefs           = 2 + !!(fFlags & RTTHREADFLAGS_WAITABLE); /* And extra reference if waitable. */
        pThread->rc              = VERR_PROCESS_RUNNING; /** @todo get a better error code! */
        pThread->enmType         = enmType;
        pThread->fFlags          = fFlags;
        pThread->fIntFlags       = fIntFlags;
        pThread->enmState        = RTTHREADSTATE_INITIALIZING;
        pThread->fReallySleeping = false;
#ifdef IN_RING3
        rtLockValidatorInitPerThread(&pThread->LockValidator);
#endif
#ifdef RT_WITH_ICONV_CACHE
        rtStrIconvCacheInit(pThread);
#endif
        rc = RTSemEventMultiCreate(&pThread->EventUser);
        if (RT_SUCCESS(rc))
        {
            rc = RTSemEventMultiCreate(&pThread->EventTerminated);
            if (RT_SUCCESS(rc))
                return pThread;
            RTSemEventMultiDestroy(pThread->EventUser);
        }
        RTMemFree(pThread);
    }
    return NULL;
}
Exemplo n.º 21
0
/**
 * Create new mbox.
 */
sys_mbox_t sys_mbox_new(void)
{
    int rc;
    struct sys_mbox *mbox;

    mbox = RTMemAllocZ(sizeof(*mbox));
    Assert(mbox != NULL);
    if (!mbox)
        return mbox;
    rc = LWIPMutexCreate(&mbox->mutex);
    AssertRC(rc);
    if (RT_FAILURE(rc))
    {
        RTMemFree(mbox);
        return NULL;
    }
    rc = RTSemEventMultiCreate(&mbox->nonempty);
    AssertRC(rc);
    if (RT_FAILURE(rc))
    {
        rc = LWIPMutexDestroy(mbox->mutex);
        AssertRC(rc);
        RTMemFree(mbox);
        return NULL;
    }
    rc = RTSemEventMultiCreate(&mbox->nonfull);
    AssertRC(rc);
    if (RT_FAILURE(rc))
    {
        rc = RTSemEventMultiDestroy(mbox->nonempty);
        AssertRC(rc);
        rc = LWIPMutexDestroy(mbox->mutex);
        AssertRC(rc);
        RTMemFree(mbox);
        return NULL;
    }
    return mbox;
}
RTDECL(int) RTSemXRoadsCreate(PRTSEMXROADS phXRoads)
{
    RTSEMXROADSINTERNAL *pThis = (RTSEMXROADSINTERNAL *)RTMemAlloc(sizeof(*pThis));
    if (!pThis)
        return VERR_NO_MEMORY;

    int rc = RTSemEventMultiCreate(&pThis->aDirs[0].hEvt);
    if (RT_SUCCESS(rc))
    {
        rc = RTSemEventMultiCreate(&pThis->aDirs[1].hEvt);
        if (RT_SUCCESS(rc))
        {
            pThis->u32Magic            = RTSEMXROADS_MAGIC;
            pThis->u32Padding          = 0;
            pThis->u64State            = 0;
            pThis->aDirs[0].fNeedReset = false;
            pThis->aDirs[1].fNeedReset = false;
            *phXRoads = pThis;
            return VINF_SUCCESS;
        }
        RTSemEventMultiDestroy(pThis->aDirs[0].hEvt);
    }
    return rc;
}
Exemplo n.º 23
0
/**
 * @interface_method_impl{VBOXSERVICE,pfnTerm}
 */
static DECLCALLBACK(void) vgsvcTimeSyncTerm(void)
{
#ifdef RT_OS_WINDOWS
    /*
     * Restore the SE_SYSTEMTIME_NAME token privileges (if init succeeded).
     */
    if (g_hTokenProcess)
    {
        if (!AdjustTokenPrivileges(g_hTokenProcess, FALSE, &g_TkOldPrivileges, sizeof(TOKEN_PRIVILEGES), NULL, NULL))
        {
            DWORD dwErr = GetLastError();
            VGSvcError("vgsvcTimeSyncTerm: Restoring token privileges (SE_SYSTEMTIME_NAME) failed with code %u!\n", dwErr);
        }
        CloseHandle(g_hTokenProcess);
        g_hTokenProcess = NULL;
    }
#endif /* !RT_OS_WINDOWS */

    if (g_TimeSyncEvent != NIL_RTSEMEVENTMULTI)
    {
        RTSemEventMultiDestroy(g_TimeSyncEvent);
        g_TimeSyncEvent = NIL_RTSEMEVENTMULTI;
    }
}
/** @copydoc VBOXSERVICE::pfnWorker */
DECLCALLBACK(int) VBoxServiceVMStatsWorker(bool volatile *pfShutdown)
{
    int rc = VINF_SUCCESS;

    /* Start monitoring of the stat event change event. */
    rc = VbglR3CtlFilterMask(VMMDEV_EVENT_STATISTICS_INTERVAL_CHANGE_REQUEST, 0);
    if (RT_FAILURE(rc))
    {
        VBoxServiceVerbose(3, "VBoxServiceVMStatsWorker: VbglR3CtlFilterMask failed with %d\n", rc);
        return rc;
    }

    /*
     * Tell the control thread that it can continue
     * spawning services.
     */
    RTThreadUserSignal(RTThreadSelf());

    /*
     * Now enter the loop retrieving runtime data continuously.
     */
    for (;;)
    {
        uint32_t fEvents = 0;
        RTMSINTERVAL cWaitMillies;

        /* Check if an update interval change is pending. */
        rc = VbglR3WaitEvent(VMMDEV_EVENT_STATISTICS_INTERVAL_CHANGE_REQUEST, 0 /* no wait */, &fEvents);
        if (    RT_SUCCESS(rc)
            &&  (fEvents & VMMDEV_EVENT_STATISTICS_INTERVAL_CHANGE_REQUEST))
        {
            VbglR3StatQueryInterval(&gCtx.cMsStatInterval);
        }

        if (gCtx.cMsStatInterval)
        {
            VBoxServiceVMStatsReport();
            cWaitMillies = gCtx.cMsStatInterval;
        }
        else
            cWaitMillies = 3000;

        /*
         * Block for a while.
         *
         * The event semaphore takes care of ignoring interruptions and it
         * allows us to implement service wakeup later.
         */
        if (*pfShutdown)
            break;
        int rc2 = RTSemEventMultiWait(g_VMStatEvent, cWaitMillies);
        if (*pfShutdown)
            break;
        if (rc2 != VERR_TIMEOUT && RT_FAILURE(rc2))
        {
            VBoxServiceError("VBoxServiceVMStatsWorker: RTSemEventMultiWait failed; rc2=%Rrc\n", rc2);
            rc = rc2;
            break;
        }
    }

    /* Cancel monitoring of the stat event change event. */
    rc = VbglR3CtlFilterMask(0, VMMDEV_EVENT_STATISTICS_INTERVAL_CHANGE_REQUEST);
    if (RT_FAILURE(rc))
        VBoxServiceVerbose(3, "VBoxServiceVMStatsWorker: VbglR3CtlFilterMask failed with %d\n", rc);

    RTSemEventMultiDestroy(g_VMStatEvent);
    g_VMStatEvent = NIL_RTSEMEVENTMULTI;

    VBoxServiceVerbose(3, "VBoxStatsThread: finished statistics change request thread\n");
    return 0;
}
Exemplo n.º 25
0
/**
 * Destructor for objects created by SUPSemEventMultiCreate.
 *
 * @param   pvObj               The object handle.
 * @param   pvUser1             The IPRT event handle.
 * @param   pvUser2             NULL.
 */
static DECLCALLBACK(void) supR0SemEventMultiDestructor(void *pvObj, void *pvUser1, void *pvUser2)
{
    Assert(pvUser2 == NULL);
    NOREF(pvObj);
    RTSemEventMultiDestroy((RTSEMEVENTMULTI)pvUser1);
}
Exemplo n.º 26
0
/**
 * Windows Service Main.
 *
 * This is invoked when the service is started and should not return until
 * the service has been stopped.
 *
 * @param   cArgs           Argument count.
 * @param   papszArgs       Argument vector.
 */
static VOID WINAPI supSvcWinServiceMain(DWORD cArgs, LPSTR *papszArgs)
{
    LogFlowFuncEnter();

    /*
     * Register the control handler function for the service and report to SCM.
     */
    Assert(g_u32SupSvcWinStatus == SERVICE_STOPPED);
    g_hSupSvcWinCtrlHandler = RegisterServiceCtrlHandlerEx(SUPSVC_SERVICE_NAME, supSvcWinServiceCtrlHandlerEx, NULL);
    if (g_hSupSvcWinCtrlHandler)
    {
        DWORD err = ERROR_GEN_FAILURE;
        if (supSvcWinSetServiceStatus(SERVICE_START_PENDING, 3000, NO_ERROR))
        {
            /*
             * Parse arguments.
             */
            static const RTOPTIONDEF s_aOptions[] =
            {
                { "--dummy", 'd', RTGETOPT_REQ_NOTHING }
            };
            int iArg = 1; /* the first arg is the service name */
            int ch;
            int rc = 0;
            RTGETOPTUNION Value;
            while (   !rc
                   && (ch = RTGetOpt(cArgs, papszArgs, s_aOptions, RT_ELEMENTS(s_aOptions), &iArg, &Value)))
                switch (ch)
                {
                    default:    rc = supSvcLogGetOptError("main", ch, cArgs, papszArgs, iArg, &Value); break;
                }
            if (iArg != cArgs)
                rc = supSvcLogTooManyArgsError("main", cArgs, papszArgs, iArg);
            if (!rc)
            {
                /*
                 * Create the event semaphore we'll be waiting on and
                 * then instantiate the actual services.
                 */
                int rc = RTSemEventMultiCreate(&g_hSupSvcWinEvent);
                if (RT_SUCCESS(rc))
                {
                    rc = supSvcCreateAndStartServices();
                    if (RT_SUCCESS(rc))
                    {
                        /*
                         * Update the status and enter the work loop.
                         *
                         * The work loop is just a dummy wait here as the services run
                         * in independent threads.
                         */
                        if (supSvcWinSetServiceStatus(SERVICE_RUNNING, 0, 0))
                        {
                            LogFlow(("supSvcWinServiceMain: calling RTSemEventMultiWait\n"));
                            rc = RTSemEventMultiWait(g_hSupSvcWinEvent, RT_INDEFINITE_WAIT);
                            if (RT_SUCCESS(rc))
                            {
                                LogFlow(("supSvcWinServiceMain: woke up\n"));
                                err = NO_ERROR;
                            }
                            else
                                supSvcLogError("RTSemEventWait failed, rc=%Rrc", rc);
                        }
                        else
                        {
                            err = GetLastError();
                            supSvcLogError("SetServiceStatus failed, err=%d", err);
                        }

                        /*
                         * Destroy the service instances, stopping them if
                         * they're still running (weird failure cause).
                         */
                        supSvcStopAndDestroyServices();
                    }

                    RTSemEventMultiDestroy(g_hSupSvcWinEvent);
                    g_hSupSvcWinEvent = NIL_RTSEMEVENTMULTI;
                }
                else
                    supSvcLogError("RTSemEventMultiCreate failed, rc=%Rrc", rc);
            }
            /* else: bad args */
        }
        else
        {
            err = GetLastError();
            supSvcLogError("SetServiceStatus failed, err=%d", err);
        }
        supSvcWinSetServiceStatus(SERVICE_STOPPED, 0, err);
    }
    else
        supSvcLogError("RegisterServiceCtrlHandlerEx failed, err=%d", GetLastError());
    LogFlowFuncLeave();
}
Exemplo n.º 27
0
RTDECL(int) RTSemRWCreateEx(PRTSEMRW phRWSem, uint32_t fFlags,
                            RTLOCKVALCLASS hClass, uint32_t uSubClass, const char *pszNameFmt, ...)
{
    AssertReturn(!(fFlags & ~RTSEMRW_FLAGS_NO_LOCK_VAL), VERR_INVALID_PARAMETER);

    /*
     * Allocate memory.
     */
    int rc;
    struct RTSEMRWINTERNAL *pThis = (struct RTSEMRWINTERNAL *)RTMemAlloc(sizeof(struct RTSEMRWINTERNAL));
    if (pThis)
    {
        /*
         * Create the semaphores.
         */
        rc = RTSemEventCreateEx(&pThis->WriteEvent, RTSEMEVENT_FLAGS_NO_LOCK_VAL, NIL_RTLOCKVALCLASS, NULL);
        if (RT_SUCCESS(rc))
        {
            rc = RTSemEventMultiCreateEx(&pThis->ReadEvent, RTSEMEVENT_FLAGS_NO_LOCK_VAL, NIL_RTLOCKVALCLASS, NULL);
            if (RT_SUCCESS(rc))
            {
                rc = RTCritSectInitEx(&pThis->CritSect, RTCRITSECT_FLAGS_NO_LOCK_VAL,
                                      NIL_RTLOCKVALCLASS, RTLOCKVAL_SUB_CLASS_NONE, NULL);
                if (RT_SUCCESS(rc))
                {
                    /*
                     * Signal the read semaphore and initialize other variables.
                     */
                    rc = RTSemEventMultiSignal(pThis->ReadEvent);
                    if (RT_SUCCESS(rc))
                    {
                        pThis->u32Padding           = UINT32_C(0xa5a55a5a);
                        pThis->cReads               = 0;
                        pThis->cWrites              = 0;
                        pThis->cWriterReads         = 0;
                        pThis->cWritesWaiting       = 0;
                        pThis->hWriter              = NIL_RTNATIVETHREAD;
                        pThis->fNeedResetReadEvent  = true;
                        pThis->u32Magic             = RTSEMRW_MAGIC;
#ifdef RTSEMRW_STRICT
                        bool const fLVEnabled = !(fFlags & RTSEMRW_FLAGS_NO_LOCK_VAL);
                        if (!pszNameFmt)
                        {
                            static uint32_t volatile s_iSemRWAnon = 0;
                            uint32_t i = ASMAtomicIncU32(&s_iSemRWAnon) - 1;
                            RTLockValidatorRecExclInit(&pThis->ValidatorWrite, hClass, uSubClass, pThis,
                                                       fLVEnabled, "RTSemRW-%u", i);
                            RTLockValidatorRecSharedInit(&pThis->ValidatorRead, hClass, uSubClass, pThis,
                                                         false /*fSignaller*/, fLVEnabled, "RTSemRW-%u", i);
                        }
                        else
                        {
                            va_list va;
                            va_start(va, pszNameFmt);
                            RTLockValidatorRecExclInitV(&pThis->ValidatorWrite, hClass, uSubClass, pThis,
                                                        fLVEnabled, pszNameFmt, va);
                            va_end(va);
                            va_start(va, pszNameFmt);
                            RTLockValidatorRecSharedInitV(&pThis->ValidatorRead, hClass, uSubClass, pThis,
                                                          false /*fSignaller*/, fLVEnabled, pszNameFmt, va);
                            va_end(va);
                        }
                        RTLockValidatorRecMakeSiblings(&pThis->ValidatorWrite.Core, &pThis->ValidatorRead.Core);
#endif
                        *phRWSem = pThis;
                        return VINF_SUCCESS;
                    }
                    RTCritSectDelete(&pThis->CritSect);
                }
                RTSemEventMultiDestroy(pThis->ReadEvent);
            }
            RTSemEventDestroy(pThis->WriteEvent);
        }
        RTMemFree(pThis);
    }
    else
        rc = VERR_NO_MEMORY;

    return rc;
}
Exemplo n.º 28
0
RTDECL(int) RTCritSectRwInitEx(PRTCRITSECTRW pThis, uint32_t fFlags,
                               RTLOCKVALCLASS hClass, uint32_t uSubClass, const char *pszNameFmt, ...)
{
    int rc;
    AssertReturn(!(fFlags & ~( RTCRITSECT_FLAGS_NO_NESTING | RTCRITSECT_FLAGS_NO_LOCK_VAL | RTCRITSECT_FLAGS_BOOTSTRAP_HACK
                              | RTCRITSECT_FLAGS_NOP )),
                 VERR_INVALID_PARAMETER);

    /*
     * Initialize the structure, allocate the lock validator stuff and sems.
     */
    pThis->u32Magic         = RTCRITSECTRW_MAGIC_DEAD;
    pThis->fNeedReset       = false;
#ifdef IN_RING0
    pThis->fFlags           = (uint16_t)(fFlags | RTCRITSECT_FLAGS_RING0);
#else
    pThis->fFlags           = (uint16_t)(fFlags & ~RTCRITSECT_FLAGS_RING0);
#endif
    pThis->u64State         = 0;
    pThis->hNativeWriter    = NIL_RTNATIVETHREAD;
    pThis->cWriterReads     = 0;
    pThis->cWriteRecursions = 0;
    pThis->hEvtWrite        = NIL_RTSEMEVENT;
    pThis->hEvtRead         = NIL_RTSEMEVENTMULTI;
    pThis->pValidatorWrite  = NULL;
    pThis->pValidatorRead   = NULL;
#if HC_ARCH_BITS == 32
    pThis->HCPtrPadding     = NIL_RTHCPTR;
#endif

#ifdef RTCRITSECTRW_STRICT
    bool const fLVEnabled = !(fFlags & RTCRITSECT_FLAGS_NO_LOCK_VAL);
    if (!pszNameFmt)
    {
        static uint32_t volatile s_iAnon = 0;
        uint32_t i = ASMAtomicIncU32(&s_iAnon) - 1;
        rc = RTLockValidatorRecExclCreate(&pThis->pValidatorWrite, hClass, uSubClass, pThis,
                                          fLVEnabled, "RTCritSectRw-%u", i);
        if (RT_SUCCESS(rc))
            rc = RTLockValidatorRecSharedCreate(&pThis->pValidatorRead, hClass, uSubClass, pThis,
                                                false /*fSignaller*/, fLVEnabled, "RTCritSectRw-%u", i);
    }
    else
    {
        va_list va;
        va_start(va, pszNameFmt);
        rc = RTLockValidatorRecExclCreateV(&pThis->pValidatorWrite, hClass, uSubClass, pThis,
                                           fLVEnabled, pszNameFmt, va);
        va_end(va);
        if (RT_SUCCESS(rc))
        {
            va_start(va, pszNameFmt);
            RTLockValidatorRecSharedCreateV(&pThis->pValidatorRead, hClass, uSubClass, pThis,
                                            false /*fSignaller*/, fLVEnabled, pszNameFmt, va);
            va_end(va);
        }
    }
    if (RT_SUCCESS(rc))
        rc = RTLockValidatorRecMakeSiblings(&pThis->pValidatorWrite->Core, &pThis->pValidatorRead->Core);

    if (RT_SUCCESS(rc))
#endif
    {
        rc = RTSemEventMultiCreate(&pThis->hEvtRead);
        if (RT_SUCCESS(rc))
        {
            rc = RTSemEventCreate(&pThis->hEvtWrite);
            if (RT_SUCCESS(rc))
            {
                pThis->u32Magic = RTCRITSECTRW_MAGIC;
                return VINF_SUCCESS;
            }
            RTSemEventMultiDestroy(pThis->hEvtRead);
        }
    }

#ifdef RTCRITSECTRW_STRICT
    RTLockValidatorRecSharedDestroy(&pThis->pValidatorRead);
    RTLockValidatorRecExclDestroy(&pThis->pValidatorWrite);
#endif
    return rc;
}
/**
 * @interface_method_impl{PDMDEVREG,pfnConstruct}
 */
static DECLCALLBACK(int) gimdevR3Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
{
    PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
    RT_NOREF2(iInstance, pCfg);
    Assert(iInstance == 0);
    PGIMDEV pThis = PDMINS_2_DATA(pDevIns, PGIMDEV);

    /*
     * Initialize relevant state bits.
     */
    pThis->pDevInsR3  = pDevIns;
    pThis->pDevInsR0  = PDMDEVINS_2_R0PTR(pDevIns);
    pThis->pDevInsRC  = PDMDEVINS_2_RCPTR(pDevIns);

    /*
     * Get debug setup requirements from GIM.
     */
    PVM pVM = PDMDevHlpGetVM(pDevIns);
    int rc = GIMR3GetDebugSetup(pVM, &pThis->DbgSetup);
    if (   RT_SUCCESS(rc)
        && pThis->DbgSetup.cbDbgRecvBuf > 0)
    {
        /*
         * Attach the stream driver for the debug connection.
         */
        PPDMISTREAM pDbgDrvStream = NULL;
        pThis->IDbgBase.pfnQueryInterface = gimdevR3QueryInterface;
        rc = PDMDevHlpDriverAttach(pDevIns, GIMDEV_DEBUG_LUN, &pThis->IDbgBase, &pThis->pDbgDrvBase, "GIM Debug Port");
        if (RT_SUCCESS(rc))
        {
            pDbgDrvStream = PDMIBASE_QUERY_INTERFACE(pThis->pDbgDrvBase, PDMISTREAM);
            if (pDbgDrvStream)
                LogRel(("GIMDev: LUN#%u: Debug port configured\n", GIMDEV_DEBUG_LUN));
            else
            {
                LogRel(("GIMDev: LUN#%u: No unit\n", GIMDEV_DEBUG_LUN));
                rc = VERR_INTERNAL_ERROR_2;
            }
        }
        else
        {
            pThis->pDbgDrvBase = NULL;
            LogRel(("GIMDev: LUN#%u: No debug port configured! rc=%Rrc\n", GIMDEV_DEBUG_LUN, rc));
        }

        if (!pDbgDrvStream)
        {
            Assert(rc != VINF_SUCCESS);
            return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
                                       N_("Debug port configuration expected when GIM configured with debugging support"));
        }

        void *pvDbgRecvBuf = RTMemAllocZ(pThis->DbgSetup.cbDbgRecvBuf);
        if (RT_UNLIKELY(!pvDbgRecvBuf))
        {
            LogRel(("GIMDev: Failed to alloc %u bytes for debug receive buffer\n", pThis->DbgSetup.cbDbgRecvBuf));
            return VERR_NO_MEMORY;
        }

        /*
         * Update the shared debug struct.
         */
        pThis->Dbg.pDbgDrvStream    = pDbgDrvStream;
        pThis->Dbg.pvDbgRecvBuf     = pvDbgRecvBuf;
        pThis->Dbg.cbDbgRecvBufRead = 0;
        pThis->Dbg.fDbgRecvBufRead  = false;

        /*
         * Create the sempahore and the debug receive thread itself.
         */
        rc = RTSemEventMultiCreate(&pThis->Dbg.hDbgRecvThreadSem);
        if (RT_SUCCESS(rc))
        {
            rc = RTThreadCreate(&pThis->hDbgRecvThread, gimDevR3DbgRecvThread, pDevIns, 0 /*cbStack*/, RTTHREADTYPE_IO,
                                RTTHREADFLAGS_WAITABLE, "GIMDebugRecv");
            if (RT_FAILURE(rc))
            {
                RTSemEventMultiDestroy(pThis->Dbg.hDbgRecvThreadSem);
                pThis->Dbg.hDbgRecvThreadSem = NIL_RTSEMEVENTMULTI;

                RTMemFree(pThis->Dbg.pvDbgRecvBuf);
                pThis->Dbg.pvDbgRecvBuf = NULL;
                return rc;
            }
        }
        else
            return rc;
    }

    /*
     * Register this device with the GIM component.
     */
    GIMR3GimDeviceRegister(pVM, pDevIns, pThis->DbgSetup.cbDbgRecvBuf ? &pThis->Dbg : NULL);

    /*
     * Get the MMIO2 regions from the GIM provider.
     */
    uint32_t cRegions = 0;
    PGIMMMIO2REGION pRegionsR3 = GIMR3GetMmio2Regions(pVM, &cRegions);
    if (   cRegions
        && pRegionsR3)
    {
        /*
         * Register the MMIO2 regions.
         */
        PGIMMMIO2REGION pCur = pRegionsR3;
        for (uint32_t i = 0; i < cRegions; i++, pCur++)
        {
            Assert(!pCur->fRegistered);
            rc = PDMDevHlpMMIO2Register(pDevIns, NULL, pCur->iRegion, pCur->cbRegion, 0 /* fFlags */, &pCur->pvPageR3,
                                        pCur->szDescription);
            if (RT_FAILURE(rc))
                return rc;

            pCur->fRegistered = true;

#if defined(VBOX_WITH_2X_4GB_ADDR_SPACE)
            RTR0PTR pR0Mapping = 0;
            rc = PDMDevHlpMMIO2MapKernel(pDevIns, NULL, pCur->iRegion, 0 /* off */, pCur->cbRegion, pCur->szDescription,
                                         &pR0Mapping);
            AssertLogRelMsgRCReturn(rc, ("PDMDevHlpMapMMIO2IntoR0(%#x,) -> %Rrc\n", pCur->cbRegion, rc), rc);
            pCur->pvPageR0 = pR0Mapping;
#else
            pCur->pvPageR0 = (RTR0PTR)pCur->pvPageR3;
#endif

            /*
             * Map into RC if required.
             */
            if (pCur->fRCMapping)
            {
                RTRCPTR pRCMapping = 0;
                rc = PDMDevHlpMMHyperMapMMIO2(pDevIns, NULL, pCur->iRegion, 0 /* off */, pCur->cbRegion, pCur->szDescription,
                                              &pRCMapping);
                AssertLogRelMsgRCReturn(rc, ("PDMDevHlpMMHyperMapMMIO2(%#x,) -> %Rrc\n", pCur->cbRegion, rc), rc);
                pCur->pvPageRC = pRCMapping;
            }
            else
                pCur->pvPageRC = NIL_RTRCPTR;

            LogRel(("GIMDev: Registered %s\n", pCur->szDescription));
        }
    }

    /** @todo Register SSM: PDMDevHlpSSMRegister(). */
    /** @todo Register statistics: STAM_REG(). */
    /** @todo Register DBGFInfo: PDMDevHlpDBGFInfoRegister(). */

    return VINF_SUCCESS;
}
Exemplo n.º 30
0
/**
 * @interface_method_impl{VBOXSERVICE,pfnWorker}
 */
DECLCALLBACK(int) vgsvcTimeSyncWorker(bool volatile *pfShutdown)
{
    RTTIME Time;
    char sz[64];
    int rc = VINF_SUCCESS;

    /*
     * Tell the control thread that it can continue spawning services.
     */
    RTThreadUserSignal(RTThreadSelf());

    /*
     * The Work Loop.
     */
    for (;;)
    {
        /*
         * Try get a reliable time reading.
         */
        int cTries = 3;
        do
        {
            /* query it. */
            RTTIMESPEC GuestNow0, GuestNow, HostNow;
            RTTimeNow(&GuestNow0);
            int rc2 = VbglR3GetHostTime(&HostNow);
            if (RT_FAILURE(rc2))
            {
                if (g_cTimeSyncErrors++ < 10)
                    VGSvcError("vgsvcTimeSyncWorker: VbglR3GetHostTime failed; rc2=%Rrc\n", rc2);
                break;
            }
            RTTimeNow(&GuestNow);

            /* calc latency and check if it's ok. */
            RTTIMESPEC GuestElapsed = GuestNow;
            RTTimeSpecSub(&GuestElapsed, &GuestNow0);
            if ((uint32_t)RTTimeSpecGetMilli(&GuestElapsed) < g_TimeSyncMaxLatency)
            {
                /*
                 * Set the time once after we were restored.
                 * (Of course only if the drift is bigger than MinAdjust)
                 */
                uint32_t TimeSyncSetThreshold = g_TimeSyncSetThreshold;
                if (g_fTimeSyncSetOnRestore)
                {
                    uint64_t idNewSession = g_idTimeSyncSession;
                    VbglR3GetSessionId(&idNewSession);
                    if (idNewSession != g_idTimeSyncSession)
                    {
                        VGSvcVerbose(3, "vgsvcTimeSyncWorker: The VM session ID changed, forcing resync.\n");
                        TimeSyncSetThreshold = 0;
                        g_idTimeSyncSession  = idNewSession;
                    }
                }

                /*
                 * Calculate the adjustment threshold and the current drift.
                 */
                uint32_t MinAdjust = RTTimeSpecGetMilli(&GuestElapsed) * g_TimeSyncLatencyFactor;
                if (MinAdjust < g_TimeSyncMinAdjust)
                    MinAdjust = g_TimeSyncMinAdjust;

                RTTIMESPEC Drift = HostNow;
                RTTimeSpecSub(&Drift, &GuestNow);
                if (RTTimeSpecGetMilli(&Drift) < 0)
                    MinAdjust += g_TimeSyncMinAdjust; /* extra buffer against moving time backwards. */

                RTTIMESPEC AbsDrift = Drift;
                RTTimeSpecAbsolute(&AbsDrift);
                if (g_cVerbosity >= 3)
                {
                    VGSvcVerbose(3, "vgsvcTimeSyncWorker: Host:    %s    (MinAdjust: %RU32 ms)\n",
                                 RTTimeToString(RTTimeExplode(&Time, &HostNow), sz, sizeof(sz)), MinAdjust);
                    VGSvcVerbose(3, "vgsvcTimeSyncWorker: Guest: - %s => %RDtimespec drift\n",
                                 RTTimeToString(RTTimeExplode(&Time, &GuestNow), sz, sizeof(sz)), &Drift);
                }

                uint32_t AbsDriftMilli = RTTimeSpecGetMilli(&AbsDrift);
                if (AbsDriftMilli > MinAdjust)
                {
                    /*
                     * Ok, the drift is above the threshold.
                     *
                     * Try a gradual adjustment first, if that fails or the drift is
                     * too big, fall back on just setting the time.
                     */

                    if (    AbsDriftMilli > TimeSyncSetThreshold
                        ||  g_fTimeSyncSetNext
                        ||  !vgsvcTimeSyncAdjust(&Drift))
                    {
                        vgsvcTimeSyncCancelAdjust();
                        vgsvcTimeSyncSet(&Drift);
                    }
                }
                else
                    vgsvcTimeSyncCancelAdjust();
                break;
            }
            VGSvcVerbose(3, "vgsvcTimeSyncWorker: %RDtimespec: latency too high (%RDtimespec) sleeping 1s\n", GuestElapsed);
            RTThreadSleep(1000);
        } while (--cTries > 0);

        /* Clear the set-next/set-start flag. */
        g_fTimeSyncSetNext = false;

        /*
         * Block for a while.
         *
         * The event semaphore takes care of ignoring interruptions and it
         * allows us to implement service wakeup later.
         */
        if (*pfShutdown)
            break;
        int rc2 = RTSemEventMultiWait(g_TimeSyncEvent, g_TimeSyncInterval);
        if (*pfShutdown)
            break;
        if (rc2 != VERR_TIMEOUT && RT_FAILURE(rc2))
        {
            VGSvcError("vgsvcTimeSyncWorker: RTSemEventMultiWait failed; rc2=%Rrc\n", rc2);
            rc = rc2;
            break;
        }
    }

    vgsvcTimeSyncCancelAdjust();
    RTSemEventMultiDestroy(g_TimeSyncEvent);
    g_TimeSyncEvent = NIL_RTSEMEVENTMULTI;
    return rc;
}