|
@@ -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;
|
|
|
}
|
|
|
|
|
|
/***********************************************************/
|