*/
sigemptyset(&set);
sigaddset(&set, SIG_IPI);
- pthread_sigmask(SIG_BLOCK, &set, NULL);
-
- sigemptyset(&set);
sigaddset(&set, SIGIO);
sigaddset(&set, SIGALRM);
sigaddset(&set, SIGBUS);
pthread_sigmask(SIG_BLOCK, &set, NULL);
+ sigdelset(&set, SIG_IPI);
sigfd = qemu_signalfd(&set);
if (sigfd == -1) {
fprintf(stderr, "failed to create signalfd\n");
#else /* _WIN32 */
-HANDLE qemu_event_handle;
+static HANDLE qemu_event_handle = NULL;
static void dummy_event_handler(void *opaque)
{
void qemu_notify_event(void)
{
+ if (!qemu_event_handle) {
+ return;
+ }
if (!SetEvent(qemu_event_handle)) {
fprintf(stderr, "qemu_notify_event: SetEvent failed: %ld\n",
GetLastError());
}
#endif
-int qemu_init_main_loop(void)
+int main_loop_init(void)
{
int ret;
return 0;
}
-
+static fd_set rfds, wfds, xfds;
+static int nfds;
static GPollFD poll_fds[1024 * 2]; /* this is probably overkill */
static int n_poll_fds;
static int max_priority;
+#ifndef _WIN32
static void glib_select_fill(int *max_fd, fd_set *rfds, fd_set *wfds,
- fd_set *xfds, struct timeval *tv)
+ fd_set *xfds, uint32_t *cur_timeout)
{
GMainContext *context = g_main_context_default();
int i;
- int timeout = 0, cur_timeout;
+ int timeout = 0;
g_main_context_prepare(context, &max_priority);
}
}
- cur_timeout = (tv->tv_sec * 1000) + ((tv->tv_usec + 500) / 1000);
- if (timeout >= 0 && timeout < cur_timeout) {
- tv->tv_sec = timeout / 1000;
- tv->tv_usec = (timeout % 1000) * 1000;
+ if (timeout >= 0 && timeout < *cur_timeout) {
+ *cur_timeout = timeout;
}
}
}
}
-#ifdef _WIN32
+static int os_host_main_loop_wait(uint32_t timeout)
+{
+ struct timeval tv, *tvarg = NULL;
+ int ret;
+
+ glib_select_fill(&nfds, &rfds, &wfds, &xfds, &timeout);
+
+ if (timeout < UINT32_MAX) {
+ tvarg = &tv;
+ tv.tv_sec = timeout / 1000;
+ tv.tv_usec = (timeout % 1000) * 1000;
+ }
+
+ if (timeout > 0) {
+ qemu_mutex_unlock_iothread();
+ }
+
+ ret = select(nfds + 1, &rfds, &wfds, &xfds, tvarg);
+
+ if (timeout > 0) {
+ qemu_mutex_lock_iothread();
+ }
+
+ glib_select_poll(&rfds, &wfds, &xfds, (ret < 0));
+ return ret;
+}
+#else
/***********************************************************/
/* Polling handling */
/* Wait objects support */
typedef struct WaitObjects {
int num;
+ int revents[MAXIMUM_WAIT_OBJECTS + 1];
HANDLE events[MAXIMUM_WAIT_OBJECTS + 1];
WaitObjectFunc *func[MAXIMUM_WAIT_OBJECTS + 1];
void *opaque[MAXIMUM_WAIT_OBJECTS + 1];
w->events[w->num] = handle;
w->func[w->num] = func;
w->opaque[w->num] = opaque;
+ w->revents[w->num] = 0;
w->num++;
return 0;
}
w->events[i] = w->events[i + 1];
w->func[i] = w->func[i + 1];
w->opaque[i] = w->opaque[i + 1];
+ w->revents[i] = w->revents[i + 1];
}
}
if (found) {
}
}
-static void os_host_main_loop_wait(int *timeout)
+void qemu_fd_register(int fd)
+{
+ WSAEventSelect(fd, qemu_event_handle, FD_READ | FD_ACCEPT | FD_CLOSE |
+ FD_CONNECT | FD_WRITE | FD_OOB);
+}
+
+static int os_host_main_loop_wait(uint32_t timeout)
{
- int ret, ret2, i;
+ GMainContext *context = g_main_context_default();
+ int ret, i;
PollingEntry *pe;
+ WaitObjects *w = &wait_objects;
+ gint poll_timeout;
+ static struct timeval tv0;
/* XXX: need to suppress polling by better using win32 events */
ret = 0;
for (pe = first_polling_entry; pe != NULL; pe = pe->next) {
ret |= pe->func(pe->opaque);
}
- if (ret == 0) {
- int err;
- WaitObjects *w = &wait_objects;
+ if (ret != 0) {
+ return ret;
+ }
- qemu_mutex_unlock_iothread();
- ret = WaitForMultipleObjects(w->num, w->events, FALSE, *timeout);
- qemu_mutex_lock_iothread();
- if (WAIT_OBJECT_0 + 0 <= ret && ret <= WAIT_OBJECT_0 + w->num - 1) {
- if (w->func[ret - WAIT_OBJECT_0]) {
- w->func[ret - WAIT_OBJECT_0](w->opaque[ret - WAIT_OBJECT_0]);
- }
+ if (nfds >= 0) {
+ ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv0);
+ if (ret != 0) {
+ timeout = 0;
+ }
+ }
+
+ g_main_context_prepare(context, &max_priority);
+ n_poll_fds = g_main_context_query(context, max_priority, &poll_timeout,
+ poll_fds, ARRAY_SIZE(poll_fds));
+ g_assert(n_poll_fds <= ARRAY_SIZE(poll_fds));
- /* Check for additional signaled events */
- for (i = (ret - WAIT_OBJECT_0 + 1); i < w->num; i++) {
- /* Check if event is signaled */
- ret2 = WaitForSingleObject(w->events[i], 0);
- if (ret2 == WAIT_OBJECT_0) {
- if (w->func[i]) {
- w->func[i](w->opaque[i]);
- }
- } else if (ret2 != WAIT_TIMEOUT) {
- err = GetLastError();
- fprintf(stderr, "WaitForSingleObject error %d %d\n", i, err);
- }
+ for (i = 0; i < w->num; i++) {
+ poll_fds[n_poll_fds + i].fd = (DWORD_PTR)w->events[i];
+ poll_fds[n_poll_fds + i].events = G_IO_IN;
+ }
+
+ if (poll_timeout < 0 || timeout < poll_timeout) {
+ poll_timeout = timeout;
+ }
+
+ qemu_mutex_unlock_iothread();
+ ret = g_poll(poll_fds, n_poll_fds + w->num, poll_timeout);
+ qemu_mutex_lock_iothread();
+ if (ret > 0) {
+ for (i = 0; i < w->num; i++) {
+ w->revents[i] = poll_fds[n_poll_fds + i].revents;
+ }
+ for (i = 0; i < w->num; i++) {
+ if (w->revents[i] && w->func[i]) {
+ w->func[i](w->opaque[i]);
}
- } else if (ret != WAIT_TIMEOUT) {
- err = GetLastError();
- fprintf(stderr, "WaitForMultipleObjects error %d %d\n", ret, err);
}
}
- *timeout = 0;
-}
-#else
-static inline void os_host_main_loop_wait(int *timeout)
-{
+ if (g_main_context_check(context, max_priority, poll_fds, n_poll_fds)) {
+ g_main_context_dispatch(context);
+ }
+
+ /* If an edge-triggered socket event occurred, select will return a
+ * positive result on the next iteration. We do not need to do anything
+ * here.
+ */
+
+ return ret;
}
#endif
int main_loop_wait(int nonblocking)
{
- fd_set rfds, wfds, xfds;
- int ret, nfds;
- struct timeval tv;
- int timeout;
+ int ret;
+ uint32_t timeout = UINT32_MAX;
if (nonblocking) {
timeout = 0;
} else {
- timeout = qemu_calculate_timeout();
qemu_bh_update_timeout(&timeout);
}
- os_host_main_loop_wait(&timeout);
-
- tv.tv_sec = timeout / 1000;
- tv.tv_usec = (timeout % 1000) * 1000;
-
/* poll any events */
/* XXX: separate device handlers from system ones */
nfds = -1;
FD_ZERO(&xfds);
#ifdef CONFIG_SLIRP
+ slirp_update_timeout(&timeout);
slirp_select_fill(&nfds, &rfds, &wfds, &xfds);
#endif
qemu_iohandler_fill(&nfds, &rfds, &wfds, &xfds);
- glib_select_fill(&nfds, &rfds, &wfds, &xfds, &tv);
-
- if (timeout > 0) {
- qemu_mutex_unlock_iothread();
- }
-
- ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv);
-
- if (timeout > 0) {
- qemu_mutex_lock_iothread();
- }
-
- glib_select_poll(&rfds, &wfds, &xfds, (ret < 0));
+ ret = os_host_main_loop_wait(timeout);
qemu_iohandler_poll(&rfds, &wfds, &xfds, ret);
#ifdef CONFIG_SLIRP
slirp_select_poll(&rfds, &wfds, &xfds, (ret < 0));