14f999d05SKevin Wolf /* 24f999d05SKevin Wolf * QEMU System Emulator 34f999d05SKevin Wolf * 44f999d05SKevin Wolf * Copyright (c) 2003-2008 Fabrice Bellard 54f999d05SKevin Wolf * 64f999d05SKevin Wolf * Permission is hereby granted, free of charge, to any person obtaining a copy 74f999d05SKevin Wolf * of this software and associated documentation files (the "Software"), to deal 84f999d05SKevin Wolf * in the Software without restriction, including without limitation the rights 94f999d05SKevin Wolf * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 104f999d05SKevin Wolf * copies of the Software, and to permit persons to whom the Software is 114f999d05SKevin Wolf * furnished to do so, subject to the following conditions: 124f999d05SKevin Wolf * 134f999d05SKevin Wolf * The above copyright notice and this permission notice shall be included in 144f999d05SKevin Wolf * all copies or substantial portions of the Software. 154f999d05SKevin Wolf * 164f999d05SKevin Wolf * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 174f999d05SKevin Wolf * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 184f999d05SKevin Wolf * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 194f999d05SKevin Wolf * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 204f999d05SKevin Wolf * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 214f999d05SKevin Wolf * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 224f999d05SKevin Wolf * THE SOFTWARE. 234f999d05SKevin Wolf */ 244f999d05SKevin Wolf 254f999d05SKevin Wolf #include "qemu-common.h" 269a1e9481SKevin Wolf #include "qemu-aio.h" 279a1e9481SKevin Wolf 289a1e9481SKevin Wolf /* Anchor of the list of Bottom Halves belonging to the context */ 29384acbf4SKevin Wolf static struct QEMUBH *first_bh; 304f999d05SKevin Wolf 314f999d05SKevin Wolf /***********************************************************/ 324f999d05SKevin Wolf /* bottom halves (can be seen as timers which expire ASAP) */ 334f999d05SKevin Wolf 344f999d05SKevin Wolf struct QEMUBH { 354f999d05SKevin Wolf QEMUBHFunc *cb; 364f999d05SKevin Wolf void *opaque; 374f999d05SKevin Wolf int scheduled; 384f999d05SKevin Wolf int idle; 394f999d05SKevin Wolf int deleted; 404f999d05SKevin Wolf QEMUBH *next; 414f999d05SKevin Wolf }; 424f999d05SKevin Wolf 434f999d05SKevin Wolf QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque) 444f999d05SKevin Wolf { 454f999d05SKevin Wolf QEMUBH *bh; 467267c094SAnthony Liguori bh = g_malloc0(sizeof(QEMUBH)); 474f999d05SKevin Wolf bh->cb = cb; 484f999d05SKevin Wolf bh->opaque = opaque; 49384acbf4SKevin Wolf bh->next = first_bh; 50384acbf4SKevin Wolf first_bh = bh; 514f999d05SKevin Wolf return bh; 524f999d05SKevin Wolf } 534f999d05SKevin Wolf 544f999d05SKevin Wolf int qemu_bh_poll(void) 554f999d05SKevin Wolf { 567887f620SKevin Wolf QEMUBH *bh, **bhp, *next; 574f999d05SKevin Wolf int ret; 58*648fb0eaSKevin Wolf static int nesting = 0; 59*648fb0eaSKevin Wolf 60*648fb0eaSKevin Wolf nesting++; 614f999d05SKevin Wolf 624f999d05SKevin Wolf ret = 0; 63384acbf4SKevin Wolf for (bh = first_bh; bh; bh = next) { 647887f620SKevin Wolf next = bh->next; 654f999d05SKevin Wolf if (!bh->deleted && bh->scheduled) { 664f999d05SKevin Wolf bh->scheduled = 0; 674f999d05SKevin Wolf if (!bh->idle) 684f999d05SKevin Wolf ret = 1; 694f999d05SKevin Wolf bh->idle = 0; 704f999d05SKevin Wolf bh->cb(bh->opaque); 714f999d05SKevin Wolf } 724f999d05SKevin Wolf } 734f999d05SKevin Wolf 74*648fb0eaSKevin Wolf nesting--; 75*648fb0eaSKevin Wolf 764f999d05SKevin Wolf /* remove deleted bhs */ 77*648fb0eaSKevin Wolf if (!nesting) { 78384acbf4SKevin Wolf bhp = &first_bh; 794f999d05SKevin Wolf while (*bhp) { 804f999d05SKevin Wolf bh = *bhp; 814f999d05SKevin Wolf if (bh->deleted) { 824f999d05SKevin Wolf *bhp = bh->next; 837267c094SAnthony Liguori g_free(bh); 84*648fb0eaSKevin Wolf } else { 854f999d05SKevin Wolf bhp = &bh->next; 864f999d05SKevin Wolf } 87*648fb0eaSKevin Wolf } 88*648fb0eaSKevin Wolf } 894f999d05SKevin Wolf 904f999d05SKevin Wolf return ret; 914f999d05SKevin Wolf } 924f999d05SKevin Wolf 934f999d05SKevin Wolf void qemu_bh_schedule_idle(QEMUBH *bh) 944f999d05SKevin Wolf { 954f999d05SKevin Wolf if (bh->scheduled) 964f999d05SKevin Wolf return; 974f999d05SKevin Wolf bh->scheduled = 1; 984f999d05SKevin Wolf bh->idle = 1; 994f999d05SKevin Wolf } 1004f999d05SKevin Wolf 1014f999d05SKevin Wolf void qemu_bh_schedule(QEMUBH *bh) 1024f999d05SKevin Wolf { 1034f999d05SKevin Wolf if (bh->scheduled) 1044f999d05SKevin Wolf return; 1054f999d05SKevin Wolf bh->scheduled = 1; 1064f999d05SKevin Wolf bh->idle = 0; 1074f999d05SKevin Wolf /* stop the currently executing CPU to execute the BH ASAP */ 1084f999d05SKevin Wolf qemu_notify_event(); 1094f999d05SKevin Wolf } 1104f999d05SKevin Wolf 1114f999d05SKevin Wolf void qemu_bh_cancel(QEMUBH *bh) 1124f999d05SKevin Wolf { 1134f999d05SKevin Wolf bh->scheduled = 0; 1144f999d05SKevin Wolf } 1154f999d05SKevin Wolf 1164f999d05SKevin Wolf void qemu_bh_delete(QEMUBH *bh) 1174f999d05SKevin Wolf { 1184f999d05SKevin Wolf bh->scheduled = 0; 1194f999d05SKevin Wolf bh->deleted = 1; 1204f999d05SKevin Wolf } 1214f999d05SKevin Wolf 1224f999d05SKevin Wolf void qemu_bh_update_timeout(int *timeout) 1234f999d05SKevin Wolf { 1244f999d05SKevin Wolf QEMUBH *bh; 1254f999d05SKevin Wolf 126384acbf4SKevin Wolf for (bh = first_bh; bh; bh = bh->next) { 1274f999d05SKevin Wolf if (!bh->deleted && bh->scheduled) { 1284f999d05SKevin Wolf if (bh->idle) { 1294f999d05SKevin Wolf /* idle bottom halves will be polled at least 1304f999d05SKevin Wolf * every 10ms */ 1314f999d05SKevin Wolf *timeout = MIN(10, *timeout); 1324f999d05SKevin Wolf } else { 1334f999d05SKevin Wolf /* non-idle bottom halves will be executed 1344f999d05SKevin Wolf * immediately */ 1354f999d05SKevin Wolf *timeout = 0; 1364f999d05SKevin Wolf break; 1374f999d05SKevin Wolf } 1384f999d05SKevin Wolf } 1394f999d05SKevin Wolf } 1404f999d05SKevin Wolf } 1414f999d05SKevin Wolf 142