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; }
/** * 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; }