bool deleted;
};
+void aio_bh_schedule_oneshot(AioContext *ctx, QEMUBHFunc *cb, void *opaque)
+{
+ QEMUBH *bh;
+ bh = g_new(QEMUBH, 1);
+ *bh = (QEMUBH){
+ .ctx = ctx,
+ .cb = cb,
+ .opaque = opaque,
+ };
+ qemu_mutex_lock(&ctx->bh_lock);
+ bh->next = ctx->first_bh;
+ bh->scheduled = 1;
+ bh->deleted = 1;
+ /* Make sure that the members are ready before putting bh into list */
+ smp_wmb();
+ ctx->first_bh = bh;
+ qemu_mutex_unlock(&ctx->bh_lock);
+}
+
QEMUBH *aio_bh_new(AioContext *ctx, QEMUBHFunc *cb, void *opaque)
{
QEMUBH *bh;
* thread sees the zero before bh->cb has run, and thus will call
* aio_notify again if necessary.
*/
- if (!bh->deleted && atomic_xchg(&bh->scheduled, 0)) {
+ if (atomic_xchg(&bh->scheduled, 0)) {
/* Idle BHs and the notify BH don't count as progress */
if (!bh->idle && bh != ctx->notify_dummy_bh) {
ret = 1;
bhp = &ctx->first_bh;
while (*bhp) {
bh = *bhp;
- if (bh->deleted) {
+ if (bh->deleted && !bh->scheduled) {
*bhp = bh->next;
g_free(bh);
} else {
QEMUBH *bh;
for (bh = ctx->first_bh; bh; bh = bh->next) {
- if (!bh->deleted && bh->scheduled) {
+ if (bh->scheduled) {
if (bh->idle) {
/* idle bottom halves will be polled at least
* every 10ms */
aio_notify_accept(ctx);
for (bh = ctx->first_bh; bh; bh = bh->next) {
- if (!bh->deleted && bh->scheduled) {
+ if (bh->scheduled) {
return true;
}
}
/* Relinquish ownership of the AioContext. */
void aio_context_release(AioContext *ctx);
+/**
+ * aio_bh_schedule_oneshot: Allocate a new bottom half structure that will run
+ * only once and as soon as possible.
+ */
+void aio_bh_schedule_oneshot(AioContext *ctx, QEMUBHFunc *cb, void *opaque);
+
/**
* aio_bh_new: Allocate a new bottom half structure.
*