Exemplo n.º 1
0
int GuestWaitEventBase::Wait(RTMSINTERVAL uTimeoutMS)
{
    int rc = VINF_SUCCESS;

    if (ASMAtomicReadBool(&mfAborted))
        rc = VERR_CANCELLED;

    if (RT_SUCCESS(rc))
    {
        AssertReturn(mEventSem != NIL_RTSEMEVENT, VERR_CANCELLED);

        RTMSINTERVAL msInterval = uTimeoutMS;
        if (!uTimeoutMS)
            msInterval = RT_INDEFINITE_WAIT;
        rc = RTSemEventWait(mEventSem, msInterval);
        if (ASMAtomicReadBool(&mfAborted))
            rc = VERR_CANCELLED;
        if (RT_SUCCESS(rc))
        {
            /* If waiting succeeded, return the overall
             * result code. */
            rc = mRc;
        }
    }

    return rc;
}
Exemplo n.º 2
0
RTDECL(bool) RTReqQueueIsBusy(RTREQQUEUE hQueue)
{
    PRTREQQUEUEINT pQueue = hQueue;
    AssertPtrReturn(pQueue, false);

    if (ASMAtomicReadBool(&pQueue->fBusy))
        return true;
    if (ASMAtomicReadPtrT(&pQueue->pReqs, PRTREQ) != NULL)
        return true;
    if (ASMAtomicReadBool(&pQueue->fBusy))
        return true;
    return false;
}
Exemplo n.º 3
0
int GuestWaitEventBase::SignalInternal(int rc, int guestRc,
                                       const GuestWaitEventPayload *pPayload)
{
    if (ASMAtomicReadBool(&mfAborted))
        return VERR_CANCELLED;

#ifdef VBOX_STRICT
    if (rc == VERR_GSTCTL_GUEST_ERROR)
        AssertMsg(RT_FAILURE(guestRc), ("Guest error indicated but no actual guest error set (%Rrc)\n", guestRc));
    else
        AssertMsg(RT_SUCCESS(guestRc), ("No guest error indicated but actual guest error set (%Rrc)\n", guestRc));
#endif

    int rc2;
    if (pPayload)
        rc2 = mPayload.CopyFromDeep(*pPayload);
    else
        rc2 = VINF_SUCCESS;
    if (RT_SUCCESS(rc2))
    {
        mRc = rc;
        mGuestRc = guestRc;

        rc2 = RTSemEventSignal(mEventSem);
    }

    return rc2;
}
/**
 * Internal worker for waking up the waiting thread.
 */
static void rtFileAioCtxWakeup(PRTFILEAIOCTXINTERNAL pCtxInt)
{
    /*
     * Read the thread handle before the status flag.
     * If we read the handle after the flag we might
     * end up with an invalid handle because the thread
     * waiting in RTFileAioCtxWakeup() might get scheduled
     * before we read the flag and returns.
     * We can ensure that the handle is valid if fWaiting is true
     * when reading the handle before the status flag.
     */
    RTTHREAD hThread;
    ASMAtomicReadHandle(&pCtxInt->hThreadWait, &hThread);
    bool fWaiting = ASMAtomicReadBool(&pCtxInt->fWaiting);
    if (fWaiting)
    {
        /*
         * If a thread waits the handle must be valid.
         * It is possible that the thread returns from
         * aio_suspend() before the signal is send.
         * This is no problem because we already set fWokenUp
         * to true which will let the thread return VERR_INTERRUPTED
         * and the next call to RTFileAioCtxWait() will not
         * return VERR_INTERRUPTED because signals are not saved
         * and will simply vanish if the destination thread can't
         * receive it.
         */
        Assert(hThread != NIL_RTTHREAD);
        RTThreadPoke(hThread);
    }
}
Exemplo n.º 5
0
RTDECL(bool) RTCircBufIsWriting(PRTCIRCBUF pBuf)
{
    /* Validate input. */
    AssertPtrReturn(pBuf, 0);

    return ASMAtomicReadBool(&pBuf->fWriting);
}
/**
 * Stop this service.
 */
void org_virtualbox_VBoxVFS::stop(IOService *pProvider)
{
    int rc;

    AssertReturnVoid(ASMAtomicReadBool(&g_fInstantiated));

    rc = VBoxVFSUnRegisterFilesystem();
    if (RT_FAILURE(rc))
    {
        PERROR("VBoxVFS filesystem is busy. Make sure all "
               "shares are unmounted (%d)", rc);
    }

    vboxDisconnect(&g_vboxSFClient);
    PINFO("VBox client disconnected");

    vboxUninit();
    PINFO("Low level uninit done");

    coreService->release();
    PINFO("VBoxGuest service released");

    IOService::stop(pProvider);

    ASMAtomicWriteBool(&g_fInstantiated, false);

    PINFO("Successfully stopped I/O kit class instance");
}
Exemplo n.º 7
0
int GuestCtrlEvent::Cancel(void)
{
    int rc = VINF_SUCCESS;
    if (!ASMAtomicReadBool(&fCompleted))
    {
        if (!ASMAtomicReadBool(&fCanceled))
        {
            ASMAtomicXchgBool(&fCanceled, true);

            LogFlowThisFunc(("Cancelling event ...\n"));
            rc = hEventSem != NIL_RTSEMEVENT
               ? RTSemEventSignal(hEventSem) : VINF_SUCCESS;
        }
    }

    return rc;
}
Exemplo n.º 8
0
/**
 * Reads a register value.
 *
 * @returns VBox status code.
 * @param   pVBoxSCSI    Pointer to the SCSI state.
 * @param   iRegister    Index of the register to read.
 * @param   pu32Value    Where to store the content of the register.
 */
int vboxscsiReadRegister(PVBOXSCSI pVBoxSCSI, uint8_t iRegister, uint32_t *pu32Value)
{
    uint8_t uVal = 0;

    switch (iRegister)
    {
        case 0:
        {
            if (ASMAtomicReadBool(&pVBoxSCSI->fBusy) == true)
            {
                uVal |= VBOX_SCSI_BUSY;
                /* There is an I/O operation in progress.
                 * Yield the execution thread to let the I/O thread make progress.
                 */
                RTThreadYield();
            }
            else
                uVal &= ~VBOX_SCSI_BUSY;
            break;
        }
        case 1:
        {
            if (pVBoxSCSI->cbBuf > 0)
            {
                AssertMsg(pVBoxSCSI->pBuf, ("pBuf is NULL\n"));
                uVal = pVBoxSCSI->pBuf[pVBoxSCSI->iBuf];
                pVBoxSCSI->iBuf++;
                pVBoxSCSI->cbBuf--;
                if (pVBoxSCSI->cbBuf == 0)
                {
                    /** The guest read the last byte from the data in buffer.
                     *  Clear everything and reset command buffer.
                     */
                    RTMemFree(pVBoxSCSI->pBuf);
                    pVBoxSCSI->pBuf  = NULL;
                    pVBoxSCSI->cbCDB = 0;
                    pVBoxSCSI->iCDB  = 0;
                    pVBoxSCSI->iBuf  = 0;
                    pVBoxSCSI->uTargetDevice = 0;
                    pVBoxSCSI->enmState = VBOXSCSISTATE_NO_COMMAND;
                    memset(pVBoxSCSI->aCDB, 0, sizeof(pVBoxSCSI->aCDB));
                }
            }
            break;
        }
        case 2:
        {
            uVal = pVBoxSCSI->regIdentify;
            break;
        }
        default:
            AssertMsgFailed(("Invalid register to read from %u\n", iRegister));
    }

    *pu32Value = uVal;

    return VINF_SUCCESS;
}
DECLHIDDEN(void) rtR0MpNotificationNativeTerm(void)
{
    if (ASMAtomicReadBool(&g_fSolCpuWatch) == true)
    {
        mutex_enter(&cpu_lock);
        unregister_cpu_setup_func(rtMpNotificationCpuEvent, NULL /* pvArg */);
        ASMAtomicWriteBool(&g_fSolCpuWatch, false);
        mutex_exit(&cpu_lock);
    }
}
Exemplo n.º 10
0
/**
 * Block the main thread until the service shuts down.
 */
void VBoxServiceMainWait(void)
{
    int rc;

    VBoxServiceReportStatus(VBoxGuestFacilityStatus_Active);

#ifdef RT_OS_WINDOWS
    /*
     * Wait for the semaphore to be signalled.
     */
    VBoxServiceVerbose(1, "Waiting in main thread\n");
    rc = RTSemEventCreate(&g_hEvtWindowsService);
    AssertRC(rc);
    while (!ASMAtomicReadBool(&g_fWindowsServiceShutdown))
    {
        rc = RTSemEventWait(g_hEvtWindowsService, RT_INDEFINITE_WAIT);
        AssertRC(rc);
    }
    RTSemEventDestroy(g_hEvtWindowsService);
    g_hEvtWindowsService = NIL_RTSEMEVENT;
#else
    /*
     * Wait explicitly for a HUP, INT, QUIT, ABRT or TERM signal, blocking
     * all important signals.
     *
     * The annoying EINTR/ERESTART loop is for the benefit of Solaris where
     * sigwait returns when we receive a SIGCHLD.  Kind of makes sense since
     */
    sigset_t signalMask;
    sigemptyset(&signalMask);
    sigaddset(&signalMask, SIGHUP);
    sigaddset(&signalMask, SIGINT);
    sigaddset(&signalMask, SIGQUIT);
    sigaddset(&signalMask, SIGABRT);
    sigaddset(&signalMask, SIGTERM);
    pthread_sigmask(SIG_BLOCK, &signalMask, NULL);

    int iSignal;
    do
    {
        iSignal = -1;
        rc = sigwait(&signalMask, &iSignal);
    }
    while (   rc == EINTR
# ifdef ERESTART
              || rc == ERESTART
# endif
          );

    VBoxServiceVerbose(3, "VBoxServiceMainWait: Received signal %d (rc=%d)\n", iSignal, rc);
#endif /* !RT_OS_WINDOWS */
}
Exemplo n.º 11
0
static void pdmacFileAioMgrWakeup(PPDMACEPFILEMGR pAioMgr)
{
    bool fWokenUp = ASMAtomicXchgBool(&pAioMgr->fWokenUp, true);
    if (!fWokenUp)
    {
        bool fWaitingEventSem = ASMAtomicReadBool(&pAioMgr->fWaitingEventSem);
        if (fWaitingEventSem)
        {
            int rc = RTSemEventSignal(pAioMgr->EventSem);
            AssertRC(rc);
        }
    }
}
Exemplo n.º 12
0
RTDECL(int) RTFileAioCtxWakeup(RTFILEAIOCTX hAioCtx)
{
    PRTFILEAIOCTXINTERNAL pCtxInt = hAioCtx;
    RTFILEAIOCTX_VALID_RETURN(pCtxInt);

    /** @todo r=bird: Define the protocol for how to resume work after calling
     *        this function. */

    bool fWokenUp    = ASMAtomicXchgBool(&pCtxInt->fWokenUp, true);

    /*
     * Read the thread handle before the status flag.
     * If we read the handle after the flag we might
     * end up with an invalid handle because the thread
     * waiting in RTFileAioCtxWakeup() might get scheduled
     * before we read the flag and returns.
     * We can ensure that the handle is valid if fWaiting is true
     * when reading the handle before the status flag.
     */
    RTTHREAD hThread;
    ASMAtomicReadHandle(&pCtxInt->hThreadWait, &hThread);
    bool fWaiting    = ASMAtomicReadBool(&pCtxInt->fWaiting);
    if (    !fWokenUp
            &&  fWaiting)
    {
        /*
         * If a thread waits the handle must be valid.
         * It is possible that the thread returns from
         * rtFileAsyncIoLinuxGetEvents() before the signal
         * is send.
         * This is no problem because we already set fWokenUp
         * to true which will let the thread return VERR_INTERRUPTED
         * and the next call to RTFileAioCtxWait() will not
         * return VERR_INTERRUPTED because signals are not saved
         * and will simply vanish if the destination thread can't
         * receive it.
         */
        Assert(hThread != NIL_RTTHREAD);
        RTThreadPoke(hThread);
    }

    return VINF_SUCCESS;
}
DECLHIDDEN(int) rtR0MpNotificationNativeInit(void)
{
    if (ASMAtomicReadBool(&g_fSolCpuWatch) == true)
        return VERR_WRONG_ORDER;

    /*
     * Register the callback building the online cpu set as we do so.
     */
    RTCpuSetEmpty(&g_rtMpSolCpuSet);

    mutex_enter(&cpu_lock);
    register_cpu_setup_func(rtMpNotificationCpuEvent, NULL /* pvArg */);

    for (int i = 0; i < (int)RTMpGetCount(); ++i)
        if (cpu_is_online(cpu[i]))
            rtMpNotificationCpuEvent(CPU_ON, i, NULL /* pvArg */);

    ASMAtomicWriteBool(&g_fSolCpuWatch, true);
    mutex_exit(&cpu_lock);

    return VINF_SUCCESS;
}
Exemplo n.º 14
0
RTDECL(int) RTFileAioCtxWakeup(RTFILEAIOCTX hAioCtx)
{
    int rc = VINF_SUCCESS;
    PRTFILEAIOCTXINTERNAL pCtxInt = hAioCtx;
    RTFILEAIOCTX_VALID_RETURN(pCtxInt);

    bool fWokenUp = ASMAtomicXchgBool(&pCtxInt->fWokenUp, true);
    bool fWaiting = ASMAtomicReadBool(&pCtxInt->fWaiting);

    if (   !fWokenUp
        && fWaiting)
    {
        BOOL fSucceeded = PostQueuedCompletionStatus(pCtxInt->hIoCompletionPort,
                                                     0, AIO_CONTEXT_WAKEUP_EVENT,
                                                     NULL);

        if (!fSucceeded)
            rc = RTErrConvertFromWin32(GetLastError());
    }

    return rc;
}
Exemplo n.º 15
0
bool GuestCtrlEvent::Canceled(void)
{
    return ASMAtomicReadBool(&fCanceled);
}
static DECLCALLBACK(int) gimDevR3DbgRecvThread(RTTHREAD hThreadSelf, void *pvUser)
{
    RT_NOREF1(hThreadSelf);

    /*
     * Validate.
     */
    PPDMDEVINS pDevIns = (PPDMDEVINS)pvUser;
    AssertReturn(pDevIns, VERR_INVALID_PARAMETER);
    PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);

    PGIMDEV pThis = PDMINS_2_DATA(pDevIns, PGIMDEV);
    AssertReturn(pThis, VERR_INVALID_POINTER);
    AssertReturn(pThis->DbgSetup.cbDbgRecvBuf, VERR_INTERNAL_ERROR);
    AssertReturn(pThis->Dbg.hDbgRecvThreadSem != NIL_RTSEMEVENTMULTI, VERR_INTERNAL_ERROR_2);
    AssertReturn(pThis->Dbg.pvDbgRecvBuf, VERR_INTERNAL_ERROR_3);

    PVM pVM = PDMDevHlpGetVM(pDevIns);
    AssertReturn(pVM, VERR_INVALID_POINTER);

    PPDMISTREAM pDbgDrvStream = pThis->Dbg.pDbgDrvStream;
    AssertReturn(pDbgDrvStream, VERR_INVALID_POINTER);

    for (;;)
    {
        /*
         * Read incoming debug data.
         */
        size_t cbRead = pThis->DbgSetup.cbDbgRecvBuf;
        int rc = pDbgDrvStream->pfnRead(pDbgDrvStream, pThis->Dbg.pvDbgRecvBuf, &cbRead);
        if (   RT_SUCCESS(rc)
            && cbRead > 0)
        {
            /*
             * Notify the consumer thread.
             */
            if (ASMAtomicReadBool(&pThis->Dbg.fDbgRecvBufRead) == false)
            {
                if (pThis->DbgSetup.pfnDbgRecvBufAvail)
                    pThis->DbgSetup.pfnDbgRecvBufAvail(pVM);
                pThis->Dbg.cbDbgRecvBufRead = cbRead;
                RTSemEventMultiReset(pThis->Dbg.hDbgRecvThreadSem);
                ASMAtomicWriteBool(&pThis->Dbg.fDbgRecvBufRead, true);
            }

            /*
             * Wait until the consumer thread has acknowledged reading of the
             * current buffer or we're asked to shut down.
             *
             * It is important that we do NOT re-invoke 'pfnRead' before the
             * current buffer is consumed, otherwise we risk data corruption.
             */
            while (   ASMAtomicReadBool(&pThis->Dbg.fDbgRecvBufRead) == true
                   && !pThis->fDbgRecvThreadShutdown)
            {
                RTSemEventMultiWait(pThis->Dbg.hDbgRecvThreadSem, RT_INDEFINITE_WAIT);
            }
        }
#ifdef RT_OS_LINUX
        else if (rc == VERR_NET_CONNECTION_REFUSED)
        {
            /*
             * With the current, simplistic PDMISTREAM interface, this is the best we can do.
             * Even using RTSocketSelectOne[Ex] on Linux returns immediately with 'ready-to-read'
             * on localhost UDP sockets that are not connected on the other end.
             */
            /** @todo Fix socket waiting semantics on localhost Linux unconnected UDP sockets. */
            RTThreadSleep(400);
        }
#endif
        else if (   rc != VINF_TRY_AGAIN
                 && rc != VERR_TRY_AGAIN
                 && rc != VERR_NET_CONNECTION_RESET_BY_PEER)
        {
            LogRel(("GIMDev: Debug thread terminating with rc=%Rrc\n", rc));
            break;
        }

        if (pThis->fDbgRecvThreadShutdown)
        {
            LogRel(("GIMDev: Debug thread shutting down\n"));
            break;
        }
    }

    return VINF_SUCCESS;
}
Exemplo n.º 17
0
/**
 * A fallback method in case something goes wrong with the normal
 * I/O manager.
 */
DECLCALLBACK(int) pdmacFileAioMgrFailsafe(RTTHREAD hThreadSelf, void *pvUser)
{
    int             rc      = VINF_SUCCESS;
    PPDMACEPFILEMGR pAioMgr = (PPDMACEPFILEMGR)pvUser;
    NOREF(hThreadSelf);

    while (   (pAioMgr->enmState == PDMACEPFILEMGRSTATE_RUNNING)
           || (pAioMgr->enmState == PDMACEPFILEMGRSTATE_SUSPENDING))
    {
        ASMAtomicWriteBool(&pAioMgr->fWaitingEventSem, true);
        if (!ASMAtomicReadBool(&pAioMgr->fWokenUp))
            rc = RTSemEventWait(pAioMgr->EventSem, pAioMgr->msBwLimitExpired);
        ASMAtomicWriteBool(&pAioMgr->fWaitingEventSem, false);
        Assert(RT_SUCCESS(rc) || rc == VERR_TIMEOUT);

        LogFlow(("Got woken up\n"));
        ASMAtomicWriteBool(&pAioMgr->fWokenUp, false);

        /* Process endpoint events first. */
        PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint = pAioMgr->pEndpointsHead;
        while (pEndpoint)
        {
            pAioMgr->msBwLimitExpired = RT_INDEFINITE_WAIT;
            rc = pdmacFileAioMgrFailsafeProcessEndpoint(pAioMgr, pEndpoint);
            AssertRC(rc);
            pEndpoint = pEndpoint->AioMgr.pEndpointNext;
        }

        /* Now check for an external blocking event. */
        if (pAioMgr->fBlockingEventPending)
        {
            switch (pAioMgr->enmBlockingEvent)
            {
                case PDMACEPFILEAIOMGRBLOCKINGEVENT_ADD_ENDPOINT:
                {
                    PPDMASYNCCOMPLETIONENDPOINTFILE pEndpointNew = pAioMgr->BlockingEventData.AddEndpoint.pEndpoint;
                    AssertMsg(VALID_PTR(pEndpointNew), ("Adding endpoint event without a endpoint to add\n"));

                    pEndpointNew->enmState = PDMASYNCCOMPLETIONENDPOINTFILESTATE_ACTIVE;

                    pEndpointNew->AioMgr.pEndpointNext = pAioMgr->pEndpointsHead;
                    pEndpointNew->AioMgr.pEndpointPrev = NULL;
                    if (pAioMgr->pEndpointsHead)
                        pAioMgr->pEndpointsHead->AioMgr.pEndpointPrev = pEndpointNew;
                    pAioMgr->pEndpointsHead = pEndpointNew;

                    pAioMgr->cEndpoints++;

                    /*
                     * Process the task list the first time. There might be pending requests
                     * if the endpoint was migrated from another endpoint.
                     */
                    rc = pdmacFileAioMgrFailsafeProcessEndpoint(pAioMgr, pEndpointNew);
                    AssertRC(rc);
                    break;
                }
                case PDMACEPFILEAIOMGRBLOCKINGEVENT_REMOVE_ENDPOINT:
                {
                    PPDMASYNCCOMPLETIONENDPOINTFILE pEndpointRemove = pAioMgr->BlockingEventData.RemoveEndpoint.pEndpoint;
                    AssertMsg(VALID_PTR(pEndpointRemove), ("Removing endpoint event without a endpoint to remove\n"));

                    pEndpointRemove->enmState = PDMASYNCCOMPLETIONENDPOINTFILESTATE_REMOVING;

                    PPDMASYNCCOMPLETIONENDPOINTFILE pPrev = pEndpointRemove->AioMgr.pEndpointPrev;
                    PPDMASYNCCOMPLETIONENDPOINTFILE pNext = pEndpointRemove->AioMgr.pEndpointNext;

                    if (pPrev)
                        pPrev->AioMgr.pEndpointNext = pNext;
                    else
                        pAioMgr->pEndpointsHead = pNext;

                    if (pNext)
                        pNext->AioMgr.pEndpointPrev = pPrev;

                    pAioMgr->cEndpoints--;
                    break;
                }
                case PDMACEPFILEAIOMGRBLOCKINGEVENT_CLOSE_ENDPOINT:
                {
                    PPDMASYNCCOMPLETIONENDPOINTFILE pEndpointClose = pAioMgr->BlockingEventData.CloseEndpoint.pEndpoint;
                    AssertMsg(VALID_PTR(pEndpointClose), ("Close endpoint event without a endpoint to Close\n"));

                    pEndpointClose->enmState = PDMASYNCCOMPLETIONENDPOINTFILESTATE_CLOSING;

                    /* Make sure all tasks finished. */
                    rc = pdmacFileAioMgrFailsafeProcessEndpoint(pAioMgr, pEndpointClose);
                    AssertRC(rc);
                    break;
                }
                case PDMACEPFILEAIOMGRBLOCKINGEVENT_SHUTDOWN:
                    pAioMgr->enmState = PDMACEPFILEMGRSTATE_SHUTDOWN;
                    break;
                case PDMACEPFILEAIOMGRBLOCKINGEVENT_SUSPEND:
                    pAioMgr->enmState = PDMACEPFILEMGRSTATE_SUSPENDING;
                    break;
                case PDMACEPFILEAIOMGRBLOCKINGEVENT_RESUME:
                    pAioMgr->enmState = PDMACEPFILEMGRSTATE_RUNNING;
                    break;
                default:
                    AssertMsgFailed(("Invalid event type %d\n", pAioMgr->enmBlockingEvent));
            }

            ASMAtomicWriteBool(&pAioMgr->fBlockingEventPending, false);
            pAioMgr->enmBlockingEvent = PDMACEPFILEAIOMGRBLOCKINGEVENT_INVALID;

            /* Release the waiting thread. */
            rc = RTSemEventSignal(pAioMgr->EventSemBlock);
            AssertRC(rc);
        }
    }

    return rc;
}