status_t VBoxDisplayService::_ServiceThread()
{
    LogFlow(("VBoxDisplayService::_ServiceThread"));

    VbglR3CtlFilterMask(VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST, 0);
    VbglR3SetGuestCaps(VMMDEV_GUEST_SUPPORTS_GRAPHICS, 0);
    for (;;)
    {
        uint32_t events;
        int rc = VbglR3WaitEvent(VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST, 5000, &events);
        if (rc == -6) // timed out?
            continue;

        if (RT_SUCCESS(rc))
        {
            uint32_t cx, cy, cBits, iDisplay;
            int rc2 = VbglR3GetDisplayChangeRequest(&cx, &cy, &cBits, &iDisplay, true);
            LogFlow(("rc2=%d screen %d size changed (%d, %d, %d)\n", rc2, iDisplay, cx, cy, cBits));

            if (RT_SUCCESS(rc2))
            {
                display_mode mode;
                fScreen.GetMode(&mode);
                if (cBits == 0)
                    cBits = get_depth_for_color_space(mode.space);

                mode.timing.h_display = cx;
                mode.timing.v_display = cy;
                mode.space            = get_color_space_for_depth(cBits);
                mode.virtual_width    = cx;
                mode.virtual_height   = cy;

                /*= {
                    {0, cx, 0, 0, cBits * cx / 8, cy, 0, 0, cBits * cy / 8, 0},
                    get_color_space_for_depth(cBits),
                    cx, cy, 0, 0, 0
                };*/

                fScreen.SetMode(&mode, false);
            }
        }
        else
            fExiting = true;

        LogFlow(("processed host event rc = %d\n", rc));
        if (fExiting)
            break;
    }
    return 0;
}
/**
 * Waits for a CPU hot plugging event and retrieve the data associated with it.
 *
 * @returns VBox status code.
 * @param   penmEventType   Where to store the event type on success.
 * @param   pidCpuCore      Where to store the CPU core ID on success.
 * @param   pidCpuPackage   Where to store the CPU package ID on success.
 */
VBGLR3DECL(int) VbglR3CpuHotPlugWaitForEvent(VMMDevCpuEventType *penmEventType, uint32_t *pidCpuCore, uint32_t *pidCpuPackage)
{
    AssertPtrReturn(penmEventType, VERR_INVALID_POINTER);
    AssertPtrReturn(pidCpuCore, VERR_INVALID_POINTER);
    AssertPtrReturn(pidCpuPackage, VERR_INVALID_POINTER);

    uint32_t fEvents = 0;
    int rc = VbglR3WaitEvent(VMMDEV_EVENT_CPU_HOTPLUG, RT_INDEFINITE_WAIT, &fEvents);
    if (RT_SUCCESS(rc))
    {
        /* did we get the right event? */
        if (fEvents & VMMDEV_EVENT_CPU_HOTPLUG)
        {
            VMMDevGetCpuHotPlugRequest Req;

            /* get the CPU hot plugging request */
            vmmdevInitRequest(&Req.header, VMMDevReq_GetCpuHotPlugRequest);
            Req.idCpuCore    = UINT32_MAX;
            Req.idCpuPackage = UINT32_MAX;
            Req.enmEventType = VMMDevCpuEventType_None;
            rc = vbglR3GRPerform(&Req.header);
            if (RT_SUCCESS(rc))
            {
                *penmEventType = Req.enmEventType;
                *pidCpuCore    = Req.idCpuCore;
                *pidCpuPackage = Req.idCpuPackage;
                return VINF_SUCCESS;
            }
        }
        else
            rc = VERR_TRY_AGAIN;
    }
    else if (rc == VERR_TIMEOUT) /* just in case */
        rc = VERR_TRY_AGAIN;
    return rc;
}
/** @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;
}
Example #4
0
/**
 * Display change request monitor thread function.
 * Before entering the loop, we re-read the last request
 * received, and if the first one received inside the
 * loop is identical we ignore it, because it is probably
 * stale.
 */
static int runDisplay(Display *pDisplay)
{
    LogRelFlowFunc(("\n"));
    Cursor hClockCursor = XCreateFontCursor(pDisplay, XC_watch);
    Cursor hArrowCursor = XCreateFontCursor(pDisplay, XC_left_ptr);
    int RRMaj, RRMin;
    if (!XRRQueryVersion(pDisplay, &RRMaj, &RRMin))
        RRMin = 0;
    const char *pcszXrandr = "xrandr";
    if (RTFileExists("/usr/X11/bin/xrandr"))
        pcszXrandr = "/usr/X11/bin/xrandr";
    int rc = RTThreadCreate(NULL, x11ConnectionMonitor, NULL, 0,
                   RTTHREADTYPE_INFREQUENT_POLLER, 0, "X11 monitor");
    if (RT_FAILURE(rc))
        return rc;
    while (true)
    {
        uint32_t fEvents = 0, cx = 0, cy = 0, cBits = 0, iDisplay = 0;
        rc = VbglR3WaitEvent(  VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST
                             | VMMDEV_EVENT_MOUSE_CAPABILITIES_CHANGED,
                             RT_INDEFINITE_WAIT, &fEvents);
        if (RT_FAILURE(rc) && rc != VERR_INTERRUPTED)  /* VERR_NO_MEMORY? */
            return rc;
        /* Jiggle the mouse pointer to wake up the driver. */
        XGrabPointer(pDisplay,
                     DefaultRootWindow(pDisplay), true, 0, GrabModeAsync,
                     GrabModeAsync, None, hClockCursor, CurrentTime);
        XFlush(pDisplay);
        XGrabPointer(pDisplay,
                     DefaultRootWindow(pDisplay), true, 0, GrabModeAsync,
                     GrabModeAsync, None, hArrowCursor, CurrentTime);
        XFlush(pDisplay);
        XUngrabPointer(pDisplay, CurrentTime);
        XFlush(pDisplay);
        /* And if it is a size hint, set the new size now that the video
         * driver has had a chance to update its list. */
        if (RT_SUCCESS(rc) && (fEvents & VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST))
        {
            int rc2 = VbglR3GetDisplayChangeRequest(&cx, &cy, &cBits,
                                                    &iDisplay, true);
            /* If we are not stopping, sleep for a bit to avoid using up
                too much CPU while retrying. */
            if (RT_FAILURE(rc2))
                RTThreadYield();
            else
                if (RRMin < 2)
                    setSize(pDisplay, cx, cy);
                else
                {
                    char szCommand[256];
                    RTStrPrintf(szCommand, sizeof(szCommand),
                                "%s --output VBOX%u --set VBOX_MODE %dx%d",
                                pcszXrandr, iDisplay, cx, cy);
                    system(szCommand);
                    RTStrPrintf(szCommand, sizeof(szCommand),
                                "%s --output VBOX%u --preferred",
                                pcszXrandr, iDisplay);
                    system(szCommand);
                }
        }
    }
    LogRelFlowFunc(("returning VINF_SUCCESS\n"));
    return VINF_SUCCESS;
}