aboutsummaryrefslogtreecommitdiff
path: root/vl.c
diff options
context:
space:
mode:
Diffstat (limited to 'vl.c')
-rw-r--r--vl.c60
1 files changed, 37 insertions, 23 deletions
diff --git a/vl.c b/vl.c
index 1afe36e6e9..137074b9ef 100644
--- a/vl.c
+++ b/vl.c
@@ -7578,6 +7578,8 @@ struct QEMUBH {
QEMUBHFunc *cb;
void *opaque;
int scheduled;
+ int idle;
+ int deleted;
QEMUBH *next;
};
@@ -7591,37 +7593,56 @@ QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque)
return NULL;
bh->cb = cb;
bh->opaque = opaque;
+ bh->next = first_bh;
+ first_bh = bh;
return bh;
}
int qemu_bh_poll(void)
{
- QEMUBH *bh, **pbh;
+ QEMUBH *bh, **bhp;
int ret;
ret = 0;
- for(;;) {
- pbh = &first_bh;
- bh = *pbh;
- if (!bh)
- break;
- ret = 1;
- *pbh = bh->next;
- bh->scheduled = 0;
- bh->cb(bh->opaque);
+ for (bh = first_bh; bh; bh = bh->next) {
+ if (!bh->deleted && bh->scheduled) {
+ bh->scheduled = 0;
+ if (!bh->idle)
+ ret = 1;
+ bh->idle = 0;
+ bh->cb(bh->opaque);
+ }
}
+
+ /* remove deleted bhs */
+ bhp = &first_bh;
+ while (*bhp) {
+ bh = *bhp;
+ if (bh->deleted) {
+ *bhp = bh->next;
+ qemu_free(bh);
+ } else
+ bhp = &bh->next;
+ }
+
return ret;
}
+void qemu_bh_schedule_idle(QEMUBH *bh)
+{
+ if (bh->scheduled)
+ return;
+ bh->scheduled = 1;
+ bh->idle = 1;
+}
+
void qemu_bh_schedule(QEMUBH *bh)
{
CPUState *env = cpu_single_env;
if (bh->scheduled)
return;
bh->scheduled = 1;
- bh->next = first_bh;
- first_bh = bh;
-
+ bh->idle = 0;
/* stop the currently executing CPU to execute the BH ASAP */
if (env) {
cpu_interrupt(env, CPU_INTERRUPT_EXIT);
@@ -7630,20 +7651,13 @@ void qemu_bh_schedule(QEMUBH *bh)
void qemu_bh_cancel(QEMUBH *bh)
{
- QEMUBH **pbh;
- if (bh->scheduled) {
- pbh = &first_bh;
- while (*pbh != bh)
- pbh = &(*pbh)->next;
- *pbh = bh->next;
- bh->scheduled = 0;
- }
+ bh->scheduled = 0;
}
void qemu_bh_delete(QEMUBH *bh)
{
- qemu_bh_cancel(bh);
- qemu_free(bh);
+ bh->scheduled = 0;
+ bh->deleted = 1;
}
/***********************************************************/