示例#1
0
文件: sys_arch.c 项目: bayasist/vbox
/**
 * Try to get an entry from an mbox.
 */
u32_t sys_arch_mbox_tryfetch(sys_mbox_t *pvMbox, void **msg)
{
    int rc;
    struct sys_mbox *mbox = NULL;
    if (!pvMbox || !*pvMbox) return SYS_MBOX_EMPTY;
    mbox = (struct sys_mbox*)*pvMbox;

    rc = LWIPMutexRequest((mbox)->mutex);
    AssertRC(rc);
    if ((mbox)->head == (mbox)->tail)
    {
        /* (mbox) is empty, don't wait */
        rc = LWIPMutexRelease((mbox)->mutex);
        AssertRC(rc);
	return SYS_MBOX_EMPTY;
    }
    if (((mbox)->head + 1) % MBOX_ENTRIES_MAX == (mbox)->tail)
    {
        rc = RTSemEventMultiSignal((mbox)->nonfull);
        AssertRC(rc);
    }
    if (msg != NULL)
        *msg = (mbox)->apvEntries[(mbox)->tail];
    (mbox)->tail++;
    (mbox)->tail %= MBOX_ENTRIES_MAX;
    rc = RTSemEventMultiSignal((mbox)->nonfull);
    if ((mbox)->head == (mbox)->tail)
    {
        rc = RTSemEventMultiReset((mbox)->nonempty);
        AssertRC(rc);
    }
    rc = LWIPMutexRelease((mbox)->mutex);
    AssertRC(rc);
    return 0;
}
示例#2
0
文件: sys_arch.c 项目: bayasist/vbox
/**
 * Try to place an entry in an mbox if there is a free slot.
 */
err_t sys_mbox_trypost(sys_mbox_t *pvMbox, void *msg)
{
    int rc;
    struct sys_mbox *mbox = NULL;
    AssertReturn(pvMbox && *pvMbox, ERR_ARG);
    mbox = (struct sys_mbox*)*pvMbox;

    rc = LWIPMutexRequest((mbox)->mutex);
    AssertRC(rc);

    if (((mbox)->head + 1) % MBOX_ENTRIES_MAX == (mbox)->tail)
    {
        /* (mbox) is full */
        rc = LWIPMutexRelease((mbox)->mutex);
        AssertRC(rc);
        return ERR_MEM;
    }

    if ((mbox)->head == (mbox)->tail)
    {
        rc = RTSemEventMultiSignal((mbox)->nonempty);
        AssertRC(rc);
    }
    (mbox)->apvEntries[(mbox)->head] = msg;
    (mbox)->head++;
    (mbox)->head %= MBOX_ENTRIES_MAX;
    if (((mbox)->head + 1) % MBOX_ENTRIES_MAX == (mbox)->tail)
    {
        rc = RTSemEventMultiReset((mbox)->nonfull);
        AssertRC(rc);
    }
    rc = LWIPMutexRelease((mbox)->mutex);
    AssertRC(rc);
    return ERR_OK;
}
示例#3
0
SUPDECL(int) SUPSemEventMultiSignal(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti)
{
    int         rc;
    uint32_t    h32;
    PSUPDRVOBJ  pObj;

    /*
     * Input validation.
     */
    AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
    h32 = (uint32_t)(uintptr_t)hEventMulti;
    if (h32 != (uintptr_t)hEventMulti)
        return VERR_INVALID_HANDLE;
    pObj = (PSUPDRVOBJ)RTHandleTableLookupWithCtx(pSession->hHandleTable, h32, SUPDRV_HANDLE_CTX_EVENT_MULTI);
    if (!pObj)
        return VERR_INVALID_HANDLE;

    /*
     * Do the job.
     */
    rc = RTSemEventMultiSignal((RTSEMEVENTMULTI)pObj->pvUser1);

    SUPR0ObjRelease(pObj, pSession);
    return rc;
}
示例#4
0
/**
 * Signals that the current operation is successfully completed and advances to
 * the next operation. The operation percentage is reset to 0.
 *
 * @param aOperationDescription     Description of the next operation.
 *
 * @note The current operation must not be the last one.
 */
HRESULT Progress::setNextOperation(const com::Utf8Str &aNextOperationDescription, ULONG aNextOperationsWeight)

{
    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);

    if (mCanceled)
        return E_FAIL;
    AssertReturn(!mCompleted, E_FAIL);
    AssertReturn(m_ulCurrentOperation + 1 < m_cOperations, E_FAIL);

    ++m_ulCurrentOperation;
    m_ulOperationsCompletedWeight += m_ulCurrentOperationWeight;

    m_operationDescription = aNextOperationDescription;
    m_ulCurrentOperationWeight = aNextOperationsWeight;
    m_ulOperationPercent = 0;

    Log(("Progress::setNextOperation(%s): aNextOperationsWeight = %d; m_ulCurrentOperation is now %d, m_ulOperationsCompletedWeight is now %d\n",
         m_operationDescription.c_str(), aNextOperationsWeight, m_ulCurrentOperation, m_ulOperationsCompletedWeight));

    /* wake up all waiting threads */
    if (mWaitersCount > 0)
        RTSemEventMultiSignal(mCompletedSem);

    return S_OK;
}
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);
}
示例#6
0
/**
 * Signals that the current operation is successfully completed and advances to
 * the next operation. The operation percentage is reset to 0.
 *
 * @param aOperationDescription     Description of the next operation.
 *
 * @note The current operation must not be the last one.
 */
STDMETHODIMP Progress::SetNextOperation(IN_BSTR bstrNextOperationDescription, ULONG ulNextOperationsWeight)
{
    AssertReturn(bstrNextOperationDescription, E_INVALIDARG);

    AutoCaller autoCaller(this);
    AssertComRCReturnRC(autoCaller.rc());

    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);

    if (mCanceled)
        return E_FAIL;
    AssertReturn(!mCompleted, E_FAIL);
    AssertReturn(m_ulCurrentOperation + 1 < m_cOperations, E_FAIL);

    ++m_ulCurrentOperation;
    m_ulOperationsCompletedWeight += m_ulCurrentOperationWeight;

    m_bstrOperationDescription = bstrNextOperationDescription;
    m_ulCurrentOperationWeight = ulNextOperationsWeight;
    m_ulOperationPercent = 0;

    Log(("Progress::setNextOperation(%ls): ulNextOperationsWeight = %d; m_ulCurrentOperation is now %d, m_ulOperationsCompletedWeight is now %d\n",
         m_bstrOperationDescription.raw(), ulNextOperationsWeight, m_ulCurrentOperation, m_ulOperationsCompletedWeight));

    /* wake up all waiting threads */
    if (mWaitersCount > 0)
        RTSemEventMultiSignal(mCompletedSem);

    return S_OK;
}
示例#7
0
/**
 * Terminates the thread.
 * Called by the thread wrapper function when the thread terminates.
 *
 * @param   pThread     The thread structure.
 * @param   rc          The thread result code.
 */
DECLHIDDEN(void) rtThreadTerminate(PRTTHREADINT pThread, int rc)
{
    Assert(pThread->cRefs >= 1);

#ifdef IPRT_WITH_GENERIC_TLS
    /*
     * Destroy TLS entries.
     */
    rtThreadTlsDestruction(pThread);
#endif /* IPRT_WITH_GENERIC_TLS */

    /*
     * Set the rc, mark it terminated and signal anyone waiting.
     */
    pThread->rc = rc;
    rtThreadSetState(pThread, RTTHREADSTATE_TERMINATED);
    ASMAtomicOrU32(&pThread->fIntFlags, RTTHREADINT_FLAGS_TERMINATED);
    if (pThread->EventTerminated != NIL_RTSEMEVENTMULTI)
        RTSemEventMultiSignal(pThread->EventTerminated);

    /*
     * Remove the thread from the tree so that there will be no
     * key clashes in the AVL tree and release our reference to ourself.
     */
    rtThreadRemove(pThread);
    rtThreadRelease(pThread);
}
/**
 * Does the wakeup call.
 *
 * @returns VBox status code. Already asserted on failure.
 * @param   pThread     The PDM thread.
 */
static DECLCALLBACK(int) pdmR3ThreadWakeUp(PPDMTHREAD pThread)
{
    RTSemEventMultiSignal(pThread->Internal.s.SleepEvent);

    int rc;
    switch (pThread->Internal.s.enmType)
    {
        case PDMTHREADTYPE_DEVICE:
            rc = pThread->u.Dev.pfnWakeUp(pThread->u.Dev.pDevIns, pThread);
            break;

        case PDMTHREADTYPE_USB:
            rc = pThread->u.Usb.pfnWakeUp(pThread->u.Usb.pUsbIns, pThread);
            break;

        case PDMTHREADTYPE_DRIVER:
            rc = pThread->u.Drv.pfnWakeUp(pThread->u.Drv.pDrvIns, pThread);
            break;

        case PDMTHREADTYPE_INTERNAL:
            rc = pThread->u.Int.pfnWakeUp(pThread->Internal.s.pVM, pThread);
            break;

        case PDMTHREADTYPE_EXTERNAL:
            rc = pThread->u.Ext.pfnWakeUp(pThread);
            break;

        default:
            AssertMsgFailed(("%d\n", pThread->Internal.s.enmType));
            rc = VERR_PDM_THREAD_IPE_1;
            break;
    }
    AssertRC(rc);
    return rc;
}
示例#9
0
/**
 * Place an entry in an mbox.
 */
void sys_mbox_post(sys_mbox_t mbox, void *msg)
{
    int rc;

    Assert(mbox != NULL);
    rc = LWIPMutexRequest(mbox->mutex, RT_INDEFINITE_WAIT);
    AssertRC(rc);
    while ((mbox->head + 1) % MBOX_ENTRIES_MAX == mbox->tail)
    {
        /* mbox is full, have to wait until a slot becomes available. */
        rc = LWIPMutexRelease(mbox->mutex);
        AssertRC(rc);
        rc = RTSemEventMultiWait(mbox->nonfull, RT_INDEFINITE_WAIT);
        AssertRC(rc);
        rc = LWIPMutexRequest(mbox->mutex, RT_INDEFINITE_WAIT);
        AssertRC(rc);
    }
    if (mbox->head == mbox->tail)
    {
        rc = RTSemEventMultiSignal(mbox->nonempty);
        AssertRC(rc);
    }
    mbox->apvEntries[mbox->head] = msg;
    mbox->head++;
    mbox->head %= MBOX_ENTRIES_MAX;
    if ((mbox->head + 1) % MBOX_ENTRIES_MAX == mbox->tail)
    {
        rc = RTSemEventMultiReset(mbox->nonfull);
        AssertRC(rc);
    }
    rc = LWIPMutexRelease(mbox->mutex);
    AssertRC(rc);
}
示例#10
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
}
示例#11
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));
}
/**
 * Signals the event so that a re-enumeration of VM-specific
 * information (like logged in users) can happen.
 *
 * @return  IPRT status code.
 */
int VBoxServiceVMInfoSignal(void)
{
    /* Trigger a re-enumeration of all logged-in users by unblocking
     * the multi event semaphore of the VMInfo thread. */
    if (g_hVMInfoEvent)
        return RTSemEventMultiSignal(g_hVMInfoEvent);

    return VINF_SUCCESS;
}
/** @copydoc VBOXSERVICE::pfnStop */
static DECLCALLBACK(void) VBoxServiceAutoMountStop(void)
{
    /*
     * We need this check because at the moment our auto-mount
     * thread really is a one-timer which destroys the event itself
     * after running.
     */
    if (g_AutoMountEvent != NIL_RTSEMEVENTMULTI)
        RTSemEventMultiSignal(g_AutoMountEvent);
}
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();
}
示例#15
0
/**
 * Signal the user event.
 *
 * @returns     iprt status code.
 */
RTDECL(int) RTThreadUserSignal(RTTHREAD Thread)
{
    int             rc;
    PRTTHREADINT    pThread = rtThreadGet(Thread);
    if (pThread)
    {
        rc = RTSemEventMultiSignal(pThread->EventUser);
        rtThreadRelease(pThread);
    }
    else
        rc = VERR_INVALID_HANDLE;
    return rc;
}
/**
 * @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;
}
示例#17
0
/**
 * Marks the operation as complete and attaches full error info.
 *
 * See VirtualBoxBase::setError(HRESULT, const GUID &, const wchar_t
 * *, const char *, ...) for more info.
 *
 * @param aResultCode   Operation result (error) code, must not be S_OK.
 * @param aIID          IID of the interface that defines the error.
 * @param aComponent    Name of the component that generates the error.
 * @param aText         Error message (must not be null), an RTStrPrintf-like
 *                      format string in UTF-8 encoding.
 * @param va            List of arguments for the format string.
 */
HRESULT Progress::i_notifyCompleteV(HRESULT aResultCode,
                                    const GUID &aIID,
                                    const char *pcszComponent,
                                    const char *aText,
                                    va_list va)
{
    Utf8Str text(aText, va);

    AutoCaller autoCaller(this);
    AssertComRCReturnRC(autoCaller.rc());

    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);

    AssertReturn(mCompleted == FALSE, E_FAIL);

    if (mCanceled && SUCCEEDED(aResultCode))
        aResultCode = E_FAIL;

    mCompleted = TRUE;
    mResultCode = aResultCode;

    AssertReturn(FAILED(aResultCode), E_FAIL);

    ComObjPtr<VirtualBoxErrorInfo> errorInfo;
    HRESULT rc = errorInfo.createObject();
    AssertComRC(rc);
    if (SUCCEEDED(rc))
    {
        errorInfo->init(aResultCode, aIID, pcszComponent, text);
        errorInfo.queryInterfaceTo(mErrorInfo.asOutParam());
    }

#if !defined VBOX_COM_INPROC
    /* remove from the global collection of pending progress operations */
    if (mParent)
        mParent->i_removeProgress(mId.ref());
#endif

    /* wake up all waiting threads */
    if (mWaitersCount > 0)
        RTSemEventMultiSignal(mCompletedSem);

    return rc;
}
示例#18
0
/**
 * Resumes the thread.
 *
 * This can be called the power on / resume notifications to resume the
 * PDM thread a bit early. The thread will be automatically resumed upon
 * return from these two notification callbacks (devices/drivers).
 *
 * The caller is responsible for serializing the control operations on the
 * thread. That basically means, always do these calls from the EMT.
 *
 * @returns VBox status code.
 * @param   pThread     The PDM thread.
 */
VMMR3DECL(int) PDMR3ThreadResume(PPDMTHREAD pThread)
{
    /*
     * Assert sanity.
     */
    AssertPtrReturn(pThread, VERR_INVALID_POINTER);
    AssertReturn(pThread->u32Version == PDMTHREAD_VERSION, VERR_INVALID_MAGIC);
    Assert(pThread->Thread != RTThreadSelf());

    /*
     * Change the state to resuming and kick the thread.
     */
    int rc = RTThreadUserReset(pThread->Thread);
    if (RT_SUCCESS(rc))
    {
        rc = VERR_WRONG_ORDER;
        if (pdmR3AtomicCmpXchgState(pThread, PDMTHREADSTATE_RESUMING, PDMTHREADSTATE_SUSPENDED))
        {
            rc = RTSemEventMultiSignal(pThread->Internal.s.BlockEvent);
            if (RT_SUCCESS(rc))
            {
                /*
                 * Wait for the thread to reach the running state.
                 */
                rc = RTThreadUserWait(pThread->Thread, 60*1000);
                if (    RT_SUCCESS(rc)
                    &&  pThread->enmState != PDMTHREADSTATE_RUNNING)
                    rc = VERR_PDM_THREAD_IPE_2;
                if (RT_SUCCESS(rc))
                    return rc;
            }
        }
    }

    /*
     * Something failed, initialize termination.
     */
    AssertMsgFailed(("PDMR3ThreadResume -> rc=%Rrc enmState=%d\n", rc, pThread->enmState));
    pdmR3ThreadBailOut(pThread);
    return rc;
}
示例#19
0
文件: sys_arch.c 项目: bayasist/vbox
/**
 * Place an entry in an mbox, waiting for a free slot if necessary.
 */
void sys_mbox_post(sys_mbox_t *pvMbox, void *msg)
{
    int rc;
    struct sys_mbox *mbox = NULL;
    Assert(pvMbox && *pvMbox);
    mbox = (struct sys_mbox*)*pvMbox;

    rc = LWIPMutexRequest((mbox)->mutex);
    AssertRC(rc);

    while (((mbox)->head + 1) % MBOX_ENTRIES_MAX == (mbox)->tail)
    {
        /* (mbox) is full, have to wait until a slot becomes available. */
        rc = LWIPMutexRelease((mbox)->mutex);
        AssertRC(rc);

        rc = RTSemEventMultiWait((mbox)->nonfull, RT_INDEFINITE_WAIT);
        AssertRC(rc);

        rc = LWIPMutexRequest((mbox)->mutex);
        AssertRC(rc);
    }

    if ((mbox)->head == (mbox)->tail)
    {
        rc = RTSemEventMultiSignal((mbox)->nonempty);
        AssertRC(rc);
    }
    (mbox)->apvEntries[(mbox)->head] = msg;
    (mbox)->head++;
    (mbox)->head %= MBOX_ENTRIES_MAX;
    if (((mbox)->head + 1) % MBOX_ENTRIES_MAX == (mbox)->tail)
    {
        rc = RTSemEventMultiReset((mbox)->nonfull);
        AssertRC(rc);
    }
    rc = LWIPMutexRelease((mbox)->mutex);
    AssertRC(rc);
}
示例#20
0
/**
 * Initiate termination of the thread because something failed in a bad way.
 *
 * @param   pThread         The PDM thread.
 */
static void pdmR3ThreadBailOut(PPDMTHREAD pThread)
{
    for (;;)
    {
        PDMTHREADSTATE enmState = pThread->enmState;
        switch (enmState)
        {
            case PDMTHREADSTATE_SUSPENDING:
            case PDMTHREADSTATE_SUSPENDED:
                if (!pdmR3AtomicCmpXchgState(pThread, PDMTHREADSTATE_TERMINATING, enmState))
                    continue;
                RTSemEventMultiSignal(pThread->Internal.s.BlockEvent);
                break;

            case PDMTHREADSTATE_RESUMING:
                if (!pdmR3AtomicCmpXchgState(pThread, PDMTHREADSTATE_TERMINATING, enmState))
                    continue;
                break;

            case PDMTHREADSTATE_RUNNING:
                if (!pdmR3AtomicCmpXchgState(pThread, PDMTHREADSTATE_TERMINATING, enmState))
                    continue;
                pdmR3ThreadWakeUp(pThread);
                break;

            case PDMTHREADSTATE_TERMINATING:
            case PDMTHREADSTATE_TERMINATED:
                break;

            case PDMTHREADSTATE_INITIALIZING:
            default:
                AssertMsgFailed(("enmState=%d\n", enmState));
                break;
        }
        break;
    }
}
示例#21
0
/**
 * Marks the whole task as complete and sets the result code.
 *
 * If the result code indicates a failure (|FAILED(@a aResultCode)|) then this
 * method will import the error info from the current thread and assign it to
 * the errorInfo attribute (it will return an error if no info is available in
 * such case).
 *
 * If the result code indicates a success (|SUCCEEDED(@a aResultCode)|) then
 * the current operation is set to the last.
 *
 * Note that this method may be called only once for the given Progress object.
 * Subsequent calls will assert.
 *
 * @param aResultCode   Operation result code.
 */
HRESULT Progress::i_notifyComplete(HRESULT aResultCode)
{
    AutoCaller autoCaller(this);
    AssertComRCReturnRC(autoCaller.rc());

    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);

    AssertReturn(mCompleted == FALSE, E_FAIL);

    LogFunc(("aResultCode=%d\n", aResultCode));

    if (mCanceled && SUCCEEDED(aResultCode))
        aResultCode = E_FAIL;

    HRESULT rc = i_setResultCode(aResultCode);

    mCompleted = TRUE;

    if (!FAILED(aResultCode))
    {
        m_ulCurrentOperation = m_cOperations - 1; /* last operation */
        m_ulOperationPercent = 100;
    }

#if !defined VBOX_COM_INPROC
    /* remove from the global collection of pending progress operations */
    if (mParent)
        mParent->i_removeProgress(mId.ref());
#endif

    /* wake up all waiting threads */
    if (mWaitersCount > 0)
        RTSemEventMultiSignal(mCompletedSem);

    return rc;
}
示例#22
0
/**
 * Get an entry from an mbox.
 */
u32_t sys_arch_mbox_fetch(sys_mbox_t mbox, void **msg, u32_t timeout)
{
    int rc;
    RTMSINTERVAL cMillies;
    uint64_t tsStart, tsEnd;

    Assert(mbox != NULL);
    tsStart = RTTimeMilliTS();
    if (timeout == 0)
        cMillies = RT_INDEFINITE_WAIT;
    else
        cMillies = timeout;
    rc = LWIPMutexRequest(mbox->mutex, cMillies);
    if (rc == VERR_TIMEOUT)
        return SYS_ARCH_TIMEOUT;
    AssertRC(rc);
    while (mbox->head == mbox->tail)
    {
        /* mbox is empty, have to wait until a slot is filled. */
        rc = LWIPMutexRelease(mbox->mutex);
        AssertRC(rc);
        if (timeout != 0)
        {
            tsEnd = RTTimeMilliTS();
            if (tsEnd - tsStart >= cMillies)
                return SYS_ARCH_TIMEOUT;
            cMillies -= tsEnd - tsStart;
        }
        rc = RTSemEventMultiWait(mbox->nonempty, cMillies);
        if (rc == VERR_TIMEOUT)
            return SYS_ARCH_TIMEOUT;
        AssertRC(rc);
        if (timeout != 0)
        {
            tsEnd = RTTimeMilliTS();
            if (tsEnd - tsStart >= cMillies)
                return SYS_ARCH_TIMEOUT;
            cMillies -= tsEnd - tsStart;
        }
        rc = LWIPMutexRequest(mbox->mutex, cMillies);
        if (rc == VERR_TIMEOUT)
            return SYS_ARCH_TIMEOUT;
        AssertRC(rc);
    }
    if ((mbox->head + 1) % MBOX_ENTRIES_MAX == mbox->tail)
    {
        rc = RTSemEventMultiSignal(mbox->nonfull);
        AssertRC(rc);
    }
    if (msg != NULL)
        *msg = mbox->apvEntries[mbox->tail];
    mbox->tail++;
    mbox->tail %= MBOX_ENTRIES_MAX;
    rc = RTSemEventMultiSignal(mbox->nonfull);
    if (mbox->head == mbox->tail)
    {
        rc = RTSemEventMultiReset(mbox->nonempty);
        AssertRC(rc);
    }
    rc = LWIPMutexRelease(mbox->mutex);
    AssertRC(rc);
    tsEnd = RTTimeMilliTS();
    return tsEnd - tsStart;
}
/** @copydoc VBOXSERVICE::pfnStop */
static DECLCALLBACK(void) VBoxServiceVMStatsStop(void)
{
    RTSemEventMultiSignal(g_VMStatEvent);
}
示例#24
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;
}
/** @copydoc VBOXSERVICE::pfnStop */
static DECLCALLBACK(void) VBoxServiceVMInfoStop(void)
{
    RTSemEventMultiSignal(g_hVMInfoEvent);
}
示例#26
0
/**
 * Service control handler (extended).
 *
 * @returns Windows status (see HandlerEx).
 * @retval  NO_ERROR if handled.
 * @retval  ERROR_CALL_NOT_IMPLEMENTED if not handled.
 *
 * @param   dwControl       The control code.
 * @param   dwEventType     Event type. (specific to the control?)
 * @param   pvEventData     Event data, specific to the event.
 * @param   pvContext       The context pointer registered with the handler.
 *                          Currently not used.
 */
static DWORD WINAPI supSvcWinServiceCtrlHandlerEx(DWORD dwControl, DWORD dwEventType, LPVOID pvEventData, LPVOID pvContext)
{
    LogFlow(("supSvcWinServiceCtrlHandlerEx: dwControl=%#x dwEventType=%#x pvEventData=%p\n",
             dwControl, dwEventType, pvEventData));

    switch (dwControl)
    {
        /*
         * Interrogate the service about it's current status.
         * MSDN says that this should just return NO_ERROR and does
         * not need to set the status again.
         */
        case SERVICE_CONTROL_INTERROGATE:
            return NO_ERROR;

        /*
         * Request to stop the service.
         */
        case SERVICE_CONTROL_STOP:
        {
            /*
             * Check if the real services can be stopped and then tell them to stop.
             */
            supSvcWinSetServiceStatus(SERVICE_STOP_PENDING, 3000, NO_ERROR);
            int rc = supSvcTryStopServices();
            if (RT_SUCCESS(rc))
            {
                /*
                 * Notify the main thread that we're done, it will wait for the
                 * real services to stop, destroy them, and finally set the windows
                 * service status to SERVICE_STOPPED and return.
                 */
                rc = RTSemEventMultiSignal(g_hSupSvcWinEvent);
                if (RT_FAILURE(rc))
                    supSvcLogError("SERVICE_CONTROL_STOP: RTSemEventMultiSignal failed, %Rrc\n", rc);
            }
            return NO_ERROR;
        }

        case SERVICE_CONTROL_PAUSE:
        case SERVICE_CONTROL_CONTINUE:
        case SERVICE_CONTROL_SHUTDOWN:
        case SERVICE_CONTROL_PARAMCHANGE:
        case SERVICE_CONTROL_NETBINDADD:
        case SERVICE_CONTROL_NETBINDREMOVE:
        case SERVICE_CONTROL_NETBINDENABLE:
        case SERVICE_CONTROL_NETBINDDISABLE:
        case SERVICE_CONTROL_DEVICEEVENT:
        case SERVICE_CONTROL_HARDWAREPROFILECHANGE:
        case SERVICE_CONTROL_POWEREVENT:
        case SERVICE_CONTROL_SESSIONCHANGE:
#ifdef SERVICE_CONTROL_PRESHUTDOWN /* vista */
        case SERVICE_CONTROL_PRESHUTDOWN:
#endif
        default:
            return ERROR_CALL_NOT_IMPLEMENTED;
    }

    NOREF(dwEventType);
    NOREF(pvEventData);
    NOREF(pvContext);
    return NO_ERROR;
}
示例#27
0
/**
 * @interface_method_impl{VBOXSERVICE,pfnStop}
 */
static DECLCALLBACK(void) vgsvcVMStatsStop(void)
{
    RTSemEventMultiSignal(g_VMStatEvent);
}
示例#28
0
int main()
{
    RTR3InitExeNoArguments(0);

    /*
     * Just a simple testcase.
     */
    RTPrintf("tstOnce: TESTING - smoke...\n");
    RTONCE Once1 = RTONCE_INITIALIZER;
    g_fOnceCB1 = false;
    int rc = RTOnce(&Once1, Once1CB, (void *)1);
    if (rc != VINF_SUCCESS)
        RTPrintf("tstOnce: ERROR - Once1, 1 failed, rc=%Rrc\n", rc);
    g_fOnceCB1 = false;
    rc = RTOnce(&Once1, Once1CB, (void *)1);
    if (rc != VINF_SUCCESS)
        RTPrintf("tstOnce: ERROR - Once1, 2 failed, rc=%Rrc\n", rc);

    /*
     * Throw a bunch of threads up against a init once thing.
     */
    RTPrintf("tstOnce: TESTING - bunch of threads...\n");
    /* create the semaphore they'll be waiting on. */
    rc = RTSemEventMultiCreate(&g_hEventMulti);
    if (RT_FAILURE(rc))
    {
        RTPrintf("tstOnce: FATAL ERROR - RTSemEventMultiCreate returned %Rrc\n", rc);
        return 1;
    }

    /* create the threads */
    RTTHREAD aThreads[32];
    for (unsigned i = 0; i < RT_ELEMENTS(aThreads); i++)
    {
        char szName[16];
        RTStrPrintf(szName, sizeof(szName), "ONCE2-%d\n", i);
        rc = RTThreadCreate(&aThreads[i], Once2Thread, NULL, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, szName);
        if (RT_FAILURE(rc))
        {
            RTPrintf("tstOnce: ERROR - failed to create thread #%d\n", i);
            g_cErrors++;
        }
    }

    /* kick them off and yield */
    rc = RTSemEventMultiSignal(g_hEventMulti);
    if (RT_FAILURE(rc))
    {
        RTPrintf("tstOnce: FATAL ERROR - RTSemEventMultiSignal returned %Rrc\n", rc);
        return 1;
    }
    RTThreadYield();

    /* wait for all of them to finish up, 30 seconds each. */
    for (unsigned i = 0; i < RT_ELEMENTS(aThreads); i++)
        if (aThreads[i] != NIL_RTTHREAD)
        {
            int rc2;
            rc = RTThreadWait(aThreads[i], 30*1000, &rc2);
            if (RT_FAILURE(rc))
            {
                RTPrintf("tstOnce: ERROR - RTThreadWait on thread #%u returned %Rrc\n", i, rc);
                g_cErrors++;
            }
            else if (RT_FAILURE(rc2))
            {
                RTPrintf("tstOnce: ERROR - Thread #%u returned %Rrc\n", i, rc2);
                g_cErrors++;
            }
        }

    /*
     * Summary.
     */
    if (!g_cErrors)
        RTPrintf("tstOnce: SUCCESS\n");
    else
        RTPrintf("tstOnce: FAILURE - %d errors\n", g_cErrors);

    return !!g_cErrors;
}
示例#29
0
/**
 * @interface_method_impl{VBOXSERVICE,pfnStop}
 */
static DECLCALLBACK(void) vgsvcTimeSyncStop(void)
{
    RTSemEventMultiSignal(g_TimeSyncEvent);
}
/** @copydoc VBOXSERVICE::pfnStop */
static DECLCALLBACK(void) VBoxServiceTimeSyncStop(void)
{
    RTSemEventMultiSignal(g_TimeSyncEvent);
}