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"
187a78db75ad42aea283f5073f51891464104a9fc3David 'Digit' Turner#include "qemu/timer.h"
19e7216d82dbaa19892ad62b07402d512234559a6eDavid 'Digit' Turner#include "sysemu/char.h"
20cc330d4169441727fecf1da08aee806fc021c4e2David 'Digit' Turner#include "android/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)
37dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        timer_del(tt);
387a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    else
39dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        timer_mod(tt, qemu_clock_get_ms(QEMU_CLOCK_HOST) + timeout_ms);
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)
47dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        timer_del(tt);
487a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    else
49dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        timer_mod(tt, deadline_ms);
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;
56dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    timer_del(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;
63dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    return 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;
70dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    timer_free(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;
88dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    timer->impl  = timer_new(QEMU_CLOCK_HOST, SCALE_MS, 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{
143aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    QLoopIo*  io = g_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 */
202e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine    if (io->ready && (io->ready & wanted) == 0) {
2037a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner        qloopio_removePending(io);
204e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine    }
2057a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
2067a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    /* recompute read/write handlers for QEMU */
2077a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    IOHandler* fd_read  = (wanted & LOOP_IO_READ)  ? qloopio_handleRead  : NULL;
2087a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    IOHandler* fd_write = (wanted & LOOP_IO_WRITE) ? qloopio_handleWrite : NULL;
2097a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    qemu_set_fd_handler(io->fd, fd_read, fd_write, io);
210e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine    io->wanted = wanted;
2117a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner}
2127a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
2137a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void
2147a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerqloopio_wantRead(void* impl)
2157a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{
2167a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    QLoopIo* io = impl;
2177a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    qloopio_modify(io, io->wanted | LOOP_IO_READ);
2187a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner}
2197a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
2207a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void
2217a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerqloopio_wantWrite(void* impl)
2227a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{
2237a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    QLoopIo* io = impl;
2247a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    qloopio_modify(io, io->wanted | LOOP_IO_WRITE);
2257a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner}
2267a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
2277a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void
2287a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerqloopio_dontWantRead(void* impl)
2297a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{
2307a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    QLoopIo* io = impl;
2317a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    qloopio_modify(io, io->wanted & ~LOOP_IO_READ);
2327a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner}
2337a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
2347a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void
2357a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerqloopio_dontWantWrite(void* impl)
2367a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{
2377a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    QLoopIo* io = impl;
2387a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    qloopio_modify(io, io->wanted & ~LOOP_IO_WRITE);
2397a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner}
2407a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
2417a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void
2427a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerqloopio_free(void* impl)
2437a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{
2447a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    QLoopIo* io = impl;
2457a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    if (io->ready)
2467a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner        qloopio_removePending(io);
2477a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
2487a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    /* remove from global list */
2497a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    qlooper_delIo(io->looper, io);
2507a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
2517a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    /* make QEMU forget about this fd */
2527a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    qemu_set_fd_handler(io->fd, NULL, NULL, NULL);
2537a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    io->fd = -1;
254aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    g_free(io);
2557a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner}
2567a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
257a65e41529e4e3900372d54859f8c559cf79d953cDavid 'Digit' Turnerstatic unsigned
258a65e41529e4e3900372d54859f8c559cf79d953cDavid 'Digit' Turnerqloopio_poll(void* impl)
259a65e41529e4e3900372d54859f8c559cf79d953cDavid 'Digit' Turner{
260a65e41529e4e3900372d54859f8c559cf79d953cDavid 'Digit' Turner    QLoopIo* io = impl;
261a65e41529e4e3900372d54859f8c559cf79d953cDavid 'Digit' Turner    return io->ready;
262a65e41529e4e3900372d54859f8c559cf79d953cDavid 'Digit' Turner}
263a65e41529e4e3900372d54859f8c559cf79d953cDavid 'Digit' Turner
2647a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic const LoopIoClass  qlooper_io_class = {
2657a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    qloopio_wantRead,
2667a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    qloopio_wantWrite,
2677a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    qloopio_dontWantRead,
2687a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    qloopio_dontWantWrite,
269a65e41529e4e3900372d54859f8c559cf79d953cDavid 'Digit' Turner    qloopio_poll,
2707a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    qloopio_free
2717a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner};
2727a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
2737a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void
2747a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerqlooper_io_init(Looper*     looper,
2757a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner                LoopIo*     loopio,
2767a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner                int         fd,
2777a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner                LoopIoFunc  callback,
2787a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner                void*       opaque)
2797a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{
2807a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    QLoopIo* io = qloopio_new(fd, callback, opaque, (QLooper*)looper);
2817a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
2827a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    socket_set_nonblock(fd);
2837a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
2847a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    loopio->clazz = (LoopIoClass*) &qlooper_io_class;
2857a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    loopio->impl  = io;
2867a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner}
2877a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
2887a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstruct QLooper {
2897a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    Looper    looper;
2907a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    QLoopIo*  io_list;
2917a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    QLoopIo*  io_pending;
2927a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    QEMUBH*   io_bh;
2937a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner};
2947a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
2957a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void
2967a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerqlooper_addIo(QLooper* looper, QLoopIo* io)
2977a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{
2987a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    io->next        = looper->io_list;
2997a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    looper->io_list = io;
3007a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner}
3017a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
3027a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void
3037a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerqlooper_delIo(QLooper* looper, QLoopIo* io)
3047a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{
3057a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    QLoopIo** pnode = &looper->io_list;
3067a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    for (;;) {
3077a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner        if (*pnode == NULL)
3087a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner            break;
3097a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner        if (*pnode == io) {
3107a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner            *pnode = io->next;
3117a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner            io->next = NULL;
3127a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner            break;
3137a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner        }
3147a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner        pnode = &(*pnode)->next;
3157a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    }
3167a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner}
3177a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
3187a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void
3197a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerqlooper_addPendingIo(QLooper* looper, QLoopIo* io)
3207a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{
3217a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    if (looper->io_pending == NULL) {
3227a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner        qemu_bh_schedule(looper->io_bh);
3237a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    }
3247a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    io->pendingNext    = looper->io_pending;
325e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine    looper->io_pending = io;
3267a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner}
3277a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
3287a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void
3297a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerqlooper_delPendingIo(QLooper* looper, QLoopIo* io)
3307a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{
3317a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    QLoopIo** pnode = &looper->io_pending;
3327a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    for (;;) {
3337a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner        if (*pnode == NULL)
3347a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner            break;
3357a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner        if (*pnode == io) {
3367a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner            *pnode = io->pendingNext;
3377a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner            break;
3387a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner        }
3397a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner        pnode = &(*pnode)->pendingNext;
3407a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    }
3417a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    io->pendingNext = NULL;
3427a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner}
3437a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
3447a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner/* This function is called by the main event loop when pending i/o
3457a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * events were registered with qlooper_addPendingIo(). It will parse
3467a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * the list of pending QLoopIo and call the user callback with the
3477a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner * appropriate flags.
3487a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner */
3497a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void
3507a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerqlooper_handle_io_bh(void* opaque)
3517a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{
3527a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    QLooper*  looper = opaque;
3537a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    QLoopIo*  io;
3547a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
3557a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    while ((io = looper->io_pending) != NULL) {
3567a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner        unsigned ready;
3577a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner        /* extract from list */
3587a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner        looper->io_pending = io->pendingNext;
3597a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner        io->pendingNext    = NULL;
3607a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner        /* call the user callback, clear io->ready before to
3617a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner         * indicate that the item is not on the pending list
3627a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner         * anymore.
3637a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner         */
3647a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner        ready     = io->ready;
3657a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner        io->ready = 0;
3667a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner        io->user_callback(io->user_opaque, io->fd, ready);
3677a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    }
3687a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner}
3697a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
3707a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic Duration
3717a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerqlooper_now(Looper* ll)
3727a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{
373dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    return qemu_clock_get_ms(QEMU_CLOCK_HOST);
3747a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner}
3757a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
3767a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerextern void qemu_system_shutdown_request(void);
3777a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
3787a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void
3797a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerqlooper_forceQuit(Looper* ll)
3807a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{
3817a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    qemu_system_shutdown_request();
3827a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner}
3837a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
3841bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner/* The user cannot call looper_run on the core event loop, because it
3851bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner * is started by qemu_main() explicitely instead, so just panic. */
3861bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turnerint
3871bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turnerqlooper_run(Looper* ll, Duration deadline_ms)
3881bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner{
3891bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner    APANIC("Trying to run the QEMU main event loop explicitely!");
3901bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner    return EINVAL;
3911bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner}
3921bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner
3937a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerstatic void
3947a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerqlooper_destroy(Looper* ll)
3957a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{
3967a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    QLooper*  looper = (QLooper*)ll;
3977a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    QLoopIo*  io;
3987a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
3997a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    while ((io = looper->io_list) != NULL)
4007a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner        qloopio_free(io);
4017a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
4027a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    qemu_bh_delete(looper->io_bh);
403aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    g_free(looper);
4047a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner}
4057a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
4067a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' TurnerLooper*
4077a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turnerlooper_newCore(void)
4087a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner{
409aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    QLooper*  looper = g_malloc0(sizeof(*looper));
4107a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
4117a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    looper->io_list    = NULL;
4127a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    looper->io_pending = NULL;
4137a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    looper->io_bh      = qemu_bh_new(qlooper_handle_io_bh, looper);
4147a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
4157a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    looper->looper.now        = qlooper_now;
4167a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    looper->looper.timer_init = qlooper_timer_init;
4177a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    looper->looper.io_init    = qlooper_io_init;
4181bb627cd086588d3f9650fac04f4034961caf9f1David 'Digit' Turner    looper->looper.run        = qlooper_run;
4197a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    looper->looper.forceQuit  = qlooper_forceQuit;
4207a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    looper->looper.destroy    = qlooper_destroy;
4217a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner
4227a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner    return &looper->looper;
4237a17b608de24e3aaf7d5ca030bb80a74dcc3baf9David 'Digit' Turner}
424