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