bool Fence::FenceAwaiter::await_suspend(T awaitingCoroutine) noexcept { Scheduler* scheduler = nullptr; if constexpr (std::is_base_of_v<SchedulablePromiseTag, std::decay_t<decltype(awaitingCoroutine.promise())>>) { scheduler = static_cast<const SchedulablePromiseTag&>(awaitingCoroutine.promise()).m_scheduler; } return await_suspend(std::experimental::coroutine_handle<>(awaitingCoroutine), scheduler); }
static int suspend_evtchn_init(int xc, int domid) { struct xs_handle *xs; char path[128]; char *portstr; unsigned int plen; int port; int rc; si.xce = -1; si.suspend_evtchn = -1; xs = xs_daemon_open(); if (!xs) { warnx("failed to get xenstore handle"); return -1; } sprintf(path, "/local/domain/%d/device/suspend/event-channel", domid); portstr = xs_read(xs, XBT_NULL, path, &plen); xs_daemon_close(xs); if (!portstr || !plen) { warnx("could not read suspend event channel"); return -1; } port = atoi(portstr); free(portstr); si.xce = xc_evtchn_open(); if (si.xce < 0) { warnx("failed to open event channel handle"); goto cleanup; } si.suspend_evtchn = xc_evtchn_bind_interdomain(si.xce, domid, port); if (si.suspend_evtchn < 0) { warnx("failed to bind suspend event channel: %d", si.suspend_evtchn); goto cleanup; } rc = xc_domain_subscribe_for_suspend(xc, domid, port); if (rc < 0) { warnx("failed to subscribe to domain: %d", rc); goto cleanup; } /* event channel is pending immediately after binding */ await_suspend(); return 0; cleanup: suspend_evtchn_release(); return -1; }
/** * Issue a suspend request to a dedicated event channel in the guest, and * receive the acknowledgement from the subscribe event channel. */ static int evtchn_suspend(void) { int rc; rc = xc_evtchn_notify(si.xce, si.suspend_evtchn); if (rc < 0) { warnx("failed to notify suspend request channel: %d", rc); return 0; } if (await_suspend() < 0) { warnx("suspend failed"); return 0; } /* notify xend that it can do device migration */ printf("suspended\n"); fflush(stdout); return 1; }