looper-qemu.c revision 1bb627cd086588d3f9650fac04f4034961caf9f1
17a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner/* Copyright (C) 2010 The Android Open Source Project 27a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner** 37a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner** This software is licensed under the terms of the GNU General Public 47a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner** License version 2, as published by the Free Software Foundation, and 57a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner** may be copied, distributed, and modified under those terms. 67a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner** 77a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner** This program is distributed in the hope that it will be useful, 87a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner** but WITHOUT ANY WARRANTY; without even the implied warranty of 97a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 107a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner** GNU General Public License for more details. 117a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner*/ 127a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 137a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner/* Implement the Looper interface on top of the QEMU main event loop */ 147a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 157a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner#include <android/looper.h> 161bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner#include <android/utils/panic.h> 177a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner#include "qemu-common.h" 187a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner#include "qemu-timer.h" 197a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner#include "qemu-char.h" 207a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner#include "sockets.h" /* for socket_set_nonblock() */ 217a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 227a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner/********************************************************************** 237a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner ********************************************************************** 247a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner ***** 257a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner ***** T I M E R S 267a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner ***** 277a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner ********************************************************************** 287a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner **********************************************************************/ 297a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 307a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner/* Model a timer simple as a QEMUTimer for the host_clock */ 317a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 327a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void 337a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerqlooptimer_startRelative(void* impl, Duration timeout_ms) 347a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 357a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner QEMUTimer* tt = impl; 367a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner if (timeout_ms == DURATION_INFINITE) 377a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner qemu_del_timer(tt); 387a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner else 397a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner qemu_mod_timer(tt, qemu_get_clock_ns(host_clock) + timeout_ms*1000000); 407a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 417a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 427a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void 437a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerqlooptimer_startAbsolute(void* impl, Duration deadline_ms) 447a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 457a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner QEMUTimer* tt = impl; 467a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner if (deadline_ms == DURATION_INFINITE) 477a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner qemu_del_timer(tt); 487a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner else 497a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner qemu_mod_timer(tt, deadline_ms*1000000); 507a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 517a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 527a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void 537a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerqlooptimer_stop(void* impl) 547a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 557a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner QEMUTimer* tt = impl; 567a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner qemu_del_timer(tt); 577a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 587a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 597a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic int 607a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerqlooptimer_isActive(void* impl) 617a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 627a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner QEMUTimer* tt = impl; 637a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner return qemu_timer_pending(tt); 647a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 657a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 667a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void 677a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerqlooptimer_free(void* impl) 687a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 697a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner QEMUTimer* tt = impl; 707a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner qemu_free_timer(tt); 717a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 727a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 737a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic const LoopTimerClass qlooptimer_class = { 747a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner qlooptimer_startRelative, 757a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner qlooptimer_startAbsolute, 767a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner qlooptimer_stop, 777a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner qlooptimer_isActive, 787a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner qlooptimer_free 797a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner}; 807a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 817a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void 827a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerqlooper_timer_init(Looper* looper, 837a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner LoopTimer* timer, 847a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner LoopTimerFunc callback, 857a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner void* opaque) 867a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 877a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner timer->clazz = (LoopTimerClass*) &qlooptimer_class; 887a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner timer->impl = qemu_new_timer(host_clock, callback, opaque); 897a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 907a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 917a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner/********************************************************************** 927a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner ********************************************************************** 937a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner ***** 947a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner ***** F I L E D E S C R I P T O R S 957a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner ***** 967a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner ********************************************************************** 977a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner **********************************************************************/ 987a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 997a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner/* Modeling the LoopIo is a bit more complex because the main event loop 1007a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * will call different functions for read and write readiness, while our 1017a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * users expect a single call with a mask of ready events. 1027a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * 1037a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * Since the QEMU main event loop looks like the following: 1047a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * 1057a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * 1/ perform select() 1067a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * 2/ for each file descriptor: 1077a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * if readReady: 1087a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * call readHandler() 1097a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * if writeReady: 1107a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * call writeHandler() 1117a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * 3/ run timers 1127a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * 4/ run bottom-half handlers 1137a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * 1147a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * We're going to provide simple read and write handlers that only mark 1157a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * the file descriptor for readiness, and put it on a "pending list". 1167a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * 1177a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * Then, we're going to schedule a bottom-half handler when such a pending 1187a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * i/o event occurs, in order to call the user callback with the correct 1197a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * flags. 1207a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner */ 1217a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 1227a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnertypedef struct QLoopIo QLoopIo; 1237a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 1247a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnertypedef struct QLooper QLooper; 1257a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 1267a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstruct QLoopIo { 1277a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner int fd; 1287a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner LoopIoFunc user_callback; 1297a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner void* user_opaque; 1307a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner unsigned wanted; 1317a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner unsigned ready; 1327a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner QLooper* looper; 1337a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner QLoopIo* pendingNext; 1347a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner QLoopIo* next; 1357a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner}; 1367a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 1377a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void qlooper_addIo(QLooper* looper, QLoopIo* io); 1387a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void qlooper_delIo(QLooper* looper, QLoopIo* io); 1397a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 1407a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic QLoopIo* 1417a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerqloopio_new(int fd, LoopIoFunc callback, void* opaque, QLooper* qlooper) 1427a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 1437a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner QLoopIo* io = qemu_malloc(sizeof(*io)); 1447a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 1457a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner io->fd = fd; 1467a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner io->user_callback = callback; 1477a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner io->user_opaque = opaque; 1487a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner io->wanted = 0; 1497a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner io->ready = 0; 1507a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner io->looper = qlooper; 1517a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner io->pendingNext = NULL; 1527a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 1537a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner qlooper_addIo(qlooper, io); 1547a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 1557a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner return io; 1567a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 1577a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 1587a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void qlooper_addPendingIo(QLooper* qlooper, QLoopIo* io); 1597a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void qlooper_delPendingIo(QLooper* qlooper, QLoopIo* io); 1607a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 1617a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void 1627a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerqloopio_removePending(QLoopIo* io) 1637a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 1647a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner if (io->ready != 0) { 1657a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner qlooper_delPendingIo(io->looper, io); 1667a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner io->ready = 0; 1677a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner } 1687a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 1697a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 1707a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void 1717a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerqloopio_setReady(QLoopIo* io, unsigned flag) 1727a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 1737a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner if (io->ready == 0) { 1747a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner qlooper_addPendingIo(io->looper, io); 1757a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner } 1767a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner io->ready |= flag; 1777a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 1787a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 1797a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void 1807a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerqloopio_handleRead(void* opaque) 1817a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 1827a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner QLoopIo* io = opaque; 1837a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner qloopio_setReady(io, LOOP_IO_READ); 1847a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 1857a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 1867a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void 1877a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerqloopio_handleWrite(void* opaque) 1887a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 1897a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner QLoopIo* io = opaque; 1907a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner qloopio_setReady(io, LOOP_IO_WRITE); 1917a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 1927a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 1937a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void 1947a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerqloopio_modify(QLoopIo* io, unsigned wanted) 1957a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 1967a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner /* no change, don't bother */ 1977a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner if (wanted == io->wanted) 1987a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner return; 1997a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 2007a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner /* if we're pending, but the new mask doesn't care about 2017a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * out state, remove from pending list */ 2027a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner if (io->ready && (io->ready & wanted) == 0) 2037a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner qloopio_removePending(io); 2047a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 2057a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner /* recompute read/write handlers for QEMU */ 2067a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner IOHandler* fd_read = (wanted & LOOP_IO_READ) ? qloopio_handleRead : NULL; 2077a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner IOHandler* fd_write = (wanted & LOOP_IO_WRITE) ? qloopio_handleWrite : NULL; 2087a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner qemu_set_fd_handler(io->fd, fd_read, fd_write, io); 2097a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 2107a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 2117a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void 2127a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerqloopio_wantRead(void* impl) 2137a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 2147a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner QLoopIo* io = impl; 2157a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner qloopio_modify(io, io->wanted | LOOP_IO_READ); 2167a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 2177a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 2187a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void 2197a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerqloopio_wantWrite(void* impl) 2207a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 2217a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner QLoopIo* io = impl; 2227a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner qloopio_modify(io, io->wanted | LOOP_IO_WRITE); 2237a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 2247a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 2257a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void 2267a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerqloopio_dontWantRead(void* impl) 2277a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 2287a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner QLoopIo* io = impl; 2297a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner qloopio_modify(io, io->wanted & ~LOOP_IO_READ); 2307a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 2317a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 2327a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void 2337a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerqloopio_dontWantWrite(void* impl) 2347a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 2357a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner QLoopIo* io = impl; 2367a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner qloopio_modify(io, io->wanted & ~LOOP_IO_WRITE); 2377a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 2387a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 2397a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void 2407a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerqloopio_free(void* impl) 2417a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 2427a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner QLoopIo* io = impl; 2437a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner if (io->ready) 2447a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner qloopio_removePending(io); 2457a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 2467a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner /* remove from global list */ 2477a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner qlooper_delIo(io->looper, io); 2487a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 2497a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner /* make QEMU forget about this fd */ 2507a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner qemu_set_fd_handler(io->fd, NULL, NULL, NULL); 2517a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner io->fd = -1; 2527a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner qemu_free(io); 2537a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 2547a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 2557a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic const LoopIoClass qlooper_io_class = { 2567a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner qloopio_wantRead, 2577a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner qloopio_wantWrite, 2587a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner qloopio_dontWantRead, 2597a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner qloopio_dontWantWrite, 2607a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner qloopio_free 2617a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner}; 2627a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 2637a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void 2647a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerqlooper_io_init(Looper* looper, 2657a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner LoopIo* loopio, 2667a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner int fd, 2677a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner LoopIoFunc callback, 2687a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner void* opaque) 2697a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 2707a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner QLoopIo* io = qloopio_new(fd, callback, opaque, (QLooper*)looper); 2717a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 2727a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner socket_set_nonblock(fd); 2737a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 2747a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner loopio->clazz = (LoopIoClass*) &qlooper_io_class; 2757a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner loopio->impl = io; 2767a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 2777a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 2787a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstruct QLooper { 2797a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner Looper looper; 2807a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner QLoopIo* io_list; 2817a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner QLoopIo* io_pending; 2827a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner QEMUBH* io_bh; 2837a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner}; 2847a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 2857a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void 2867a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerqlooper_addIo(QLooper* looper, QLoopIo* io) 2877a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 2887a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner io->next = looper->io_list; 2897a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner looper->io_list = io; 2907a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 2917a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 2927a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void 2937a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerqlooper_delIo(QLooper* looper, QLoopIo* io) 2947a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 2957a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner QLoopIo** pnode = &looper->io_list; 2967a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner for (;;) { 2977a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner if (*pnode == NULL) 2987a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner break; 2997a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner if (*pnode == io) { 3007a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner *pnode = io->next; 3017a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner io->next = NULL; 3027a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner break; 3037a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner } 3047a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner pnode = &(*pnode)->next; 3057a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner } 3067a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 3077a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 3087a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void 3097a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerqlooper_addPendingIo(QLooper* looper, QLoopIo* io) 3107a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 3117a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner if (looper->io_pending == NULL) { 3127a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner qemu_bh_schedule(looper->io_bh); 3137a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner } 3147a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner io->pendingNext = looper->io_pending; 3157a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner looper->io_pending = io->pendingNext; 3167a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 3177a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 3187a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void 3197a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerqlooper_delPendingIo(QLooper* looper, QLoopIo* io) 3207a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 3217a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner QLoopIo** pnode = &looper->io_pending; 3227a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner for (;;) { 3237a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner if (*pnode == NULL) 3247a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner break; 3257a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner if (*pnode == io) { 3267a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner *pnode = io->pendingNext; 3277a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner break; 3287a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner } 3297a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner pnode = &(*pnode)->pendingNext; 3307a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner } 3317a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner io->pendingNext = NULL; 3327a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 3337a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 3347a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner/* This function is called by the main event loop when pending i/o 3357a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * events were registered with qlooper_addPendingIo(). It will parse 3367a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * the list of pending QLoopIo and call the user callback with the 3377a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * appropriate flags. 3387a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner */ 3397a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void 3407a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerqlooper_handle_io_bh(void* opaque) 3417a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 3427a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner QLooper* looper = opaque; 3437a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner QLoopIo* io; 3447a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 3457a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner while ((io = looper->io_pending) != NULL) { 3467a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner unsigned ready; 3477a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner /* extract from list */ 3487a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner looper->io_pending = io->pendingNext; 3497a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner io->pendingNext = NULL; 3507a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner /* call the user callback, clear io->ready before to 3517a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * indicate that the item is not on the pending list 3527a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * anymore. 3537a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner */ 3547a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner ready = io->ready; 3557a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner io->ready = 0; 3567a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner io->user_callback(io->user_opaque, io->fd, ready); 3577a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner } 3587a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 3597a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 3607a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic Duration 3617a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerqlooper_now(Looper* ll) 3627a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 3637a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner return qemu_get_clock_ns(host_clock)/1000000; 3647a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 3657a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 3667a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerextern void qemu_system_shutdown_request(void); 3677a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 3687a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void 3697a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerqlooper_forceQuit(Looper* ll) 3707a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 3717a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner qemu_system_shutdown_request(); 3727a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 3737a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 3741bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner/* The user cannot call looper_run on the core event loop, because it 3751bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner * is started by qemu_main() explicitely instead, so just panic. */ 3761bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turnerint 3771bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turnerqlooper_run(Looper* ll, Duration deadline_ms) 3781bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner{ 3791bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner APANIC("Trying to run the QEMU main event loop explicitely!"); 3801bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner return EINVAL; 3811bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner} 3821bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner 3837a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void 3847a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerqlooper_destroy(Looper* ll) 3857a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 3867a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner QLooper* looper = (QLooper*)ll; 3877a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner QLoopIo* io; 3887a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 3897a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner while ((io = looper->io_list) != NULL) 3907a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner qloopio_free(io); 3917a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 3927a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner qemu_bh_delete(looper->io_bh); 3937a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner qemu_free(looper); 3947a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 3957a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 3967a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' TurnerLooper* 3977a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerlooper_newCore(void) 3987a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{ 3997a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner QLooper* looper = qemu_mallocz(sizeof(*looper)); 4007a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 4017a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner looper->io_list = NULL; 4027a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner looper->io_pending = NULL; 4037a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner looper->io_bh = qemu_bh_new(qlooper_handle_io_bh, looper); 4047a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 4057a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner looper->looper.now = qlooper_now; 4067a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner looper->looper.timer_init = qlooper_timer_init; 4077a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner looper->looper.io_init = qlooper_io_init; 4081bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner looper->looper.run = qlooper_run; 4097a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner looper->looper.forceQuit = qlooper_forceQuit; 4107a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner looper->looper.destroy = qlooper_destroy; 4117a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner 4127a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner return &looper->looper; 4137a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner} 414