async.c (c2b38b277a7882a592f4f2ec955084b2b756daaa) async.c (0c330a734b51c177ab8488932ac3b0c4d63a718a)
1/*
2 * Data plane event loop
3 *
4 * Copyright (c) 2003-2008 Fabrice Bellard
5 * Copyright (c) 2009-2017 QEMU contributors
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal

--- 17 unchanged lines hidden (view full) ---

26#include "qemu/osdep.h"
27#include "qapi/error.h"
28#include "qemu-common.h"
29#include "block/aio.h"
30#include "block/thread-pool.h"
31#include "qemu/main-loop.h"
32#include "qemu/atomic.h"
33#include "block/raw-aio.h"
1/*
2 * Data plane event loop
3 *
4 * Copyright (c) 2003-2008 Fabrice Bellard
5 * Copyright (c) 2009-2017 QEMU contributors
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal

--- 17 unchanged lines hidden (view full) ---

26#include "qemu/osdep.h"
27#include "qapi/error.h"
28#include "qemu-common.h"
29#include "block/aio.h"
30#include "block/thread-pool.h"
31#include "qemu/main-loop.h"
32#include "qemu/atomic.h"
33#include "block/raw-aio.h"
34#include "qemu/coroutine_int.h"
35#include "trace.h"
34
35/***********************************************************/
36/* bottom halves (can be seen as timers which expire ASAP) */
37
38struct QEMUBH {
39 AioContext *ctx;
40 QEMUBHFunc *cb;
41 void *opaque;

--- 228 unchanged lines hidden (view full) ---

270#ifdef CONFIG_LINUX_AIO
271 if (ctx->linux_aio) {
272 laio_detach_aio_context(ctx->linux_aio, ctx);
273 laio_cleanup(ctx->linux_aio);
274 ctx->linux_aio = NULL;
275 }
276#endif
277
36
37/***********************************************************/
38/* bottom halves (can be seen as timers which expire ASAP) */
39
40struct QEMUBH {
41 AioContext *ctx;
42 QEMUBHFunc *cb;
43 void *opaque;

--- 228 unchanged lines hidden (view full) ---

272#ifdef CONFIG_LINUX_AIO
273 if (ctx->linux_aio) {
274 laio_detach_aio_context(ctx->linux_aio, ctx);
275 laio_cleanup(ctx->linux_aio);
276 ctx->linux_aio = NULL;
277 }
278#endif
279
280 assert(QSLIST_EMPTY(&ctx->scheduled_coroutines));
281 qemu_bh_delete(ctx->co_schedule_bh);
282
278 qemu_lockcnt_lock(&ctx->list_lock);
279 assert(!qemu_lockcnt_count(&ctx->list_lock));
280 while (ctx->first_bh) {
281 QEMUBH *next = ctx->first_bh->next;
282
283 /* qemu_bh_delete() must have been called on BHs in this AioContext */
284 assert(ctx->first_bh->deleted);
285

--- 73 unchanged lines hidden (view full) ---

359static bool event_notifier_poll(void *opaque)
360{
361 EventNotifier *e = opaque;
362 AioContext *ctx = container_of(e, AioContext, notifier);
363
364 return atomic_read(&ctx->notified);
365}
366
283 qemu_lockcnt_lock(&ctx->list_lock);
284 assert(!qemu_lockcnt_count(&ctx->list_lock));
285 while (ctx->first_bh) {
286 QEMUBH *next = ctx->first_bh->next;
287
288 /* qemu_bh_delete() must have been called on BHs in this AioContext */
289 assert(ctx->first_bh->deleted);
290

--- 73 unchanged lines hidden (view full) ---

364static bool event_notifier_poll(void *opaque)
365{
366 EventNotifier *e = opaque;
367 AioContext *ctx = container_of(e, AioContext, notifier);
368
369 return atomic_read(&ctx->notified);
370}
371
372static void co_schedule_bh_cb(void *opaque)
373{
374 AioContext *ctx = opaque;
375 QSLIST_HEAD(, Coroutine) straight, reversed;
376
377 QSLIST_MOVE_ATOMIC(&reversed, &ctx->scheduled_coroutines);
378 QSLIST_INIT(&straight);
379
380 while (!QSLIST_EMPTY(&reversed)) {
381 Coroutine *co = QSLIST_FIRST(&reversed);
382 QSLIST_REMOVE_HEAD(&reversed, co_scheduled_next);
383 QSLIST_INSERT_HEAD(&straight, co, co_scheduled_next);
384 }
385
386 while (!QSLIST_EMPTY(&straight)) {
387 Coroutine *co = QSLIST_FIRST(&straight);
388 QSLIST_REMOVE_HEAD(&straight, co_scheduled_next);
389 trace_aio_co_schedule_bh_cb(ctx, co);
390 qemu_coroutine_enter(co);
391 }
392}
393
367AioContext *aio_context_new(Error **errp)
368{
369 int ret;
370 AioContext *ctx;
371
372 ctx = (AioContext *) g_source_new(&aio_source_funcs, sizeof(AioContext));
373 aio_context_setup(ctx);
374
375 ret = event_notifier_init(&ctx->notifier, false);
376 if (ret < 0) {
377 error_setg_errno(errp, -ret, "Failed to initialize event notifier");
378 goto fail;
379 }
380 g_source_set_can_recurse(&ctx->source, true);
381 qemu_lockcnt_init(&ctx->list_lock);
394AioContext *aio_context_new(Error **errp)
395{
396 int ret;
397 AioContext *ctx;
398
399 ctx = (AioContext *) g_source_new(&aio_source_funcs, sizeof(AioContext));
400 aio_context_setup(ctx);
401
402 ret = event_notifier_init(&ctx->notifier, false);
403 if (ret < 0) {
404 error_setg_errno(errp, -ret, "Failed to initialize event notifier");
405 goto fail;
406 }
407 g_source_set_can_recurse(&ctx->source, true);
408 qemu_lockcnt_init(&ctx->list_lock);
409
410 ctx->co_schedule_bh = aio_bh_new(ctx, co_schedule_bh_cb, ctx);
411 QSLIST_INIT(&ctx->scheduled_coroutines);
412
382 aio_set_event_notifier(ctx, &ctx->notifier,
383 false,
384 (EventNotifierHandler *)
385 event_notifier_dummy_cb,
386 event_notifier_poll);
387#ifdef CONFIG_LINUX_AIO
388 ctx->linux_aio = NULL;
389#endif

--- 7 unchanged lines hidden (view full) ---

397 ctx->poll_shrink = 0;
398
399 return ctx;
400fail:
401 g_source_destroy(&ctx->source);
402 return NULL;
403}
404
413 aio_set_event_notifier(ctx, &ctx->notifier,
414 false,
415 (EventNotifierHandler *)
416 event_notifier_dummy_cb,
417 event_notifier_poll);
418#ifdef CONFIG_LINUX_AIO
419 ctx->linux_aio = NULL;
420#endif

--- 7 unchanged lines hidden (view full) ---

428 ctx->poll_shrink = 0;
429
430 return ctx;
431fail:
432 g_source_destroy(&ctx->source);
433 return NULL;
434}
435
436void aio_co_schedule(AioContext *ctx, Coroutine *co)
437{
438 trace_aio_co_schedule(ctx, co);
439 QSLIST_INSERT_HEAD_ATOMIC(&ctx->scheduled_coroutines,
440 co, co_scheduled_next);
441 qemu_bh_schedule(ctx->co_schedule_bh);
442}
443
444void aio_co_wake(struct Coroutine *co)
445{
446 AioContext *ctx;
447
448 /* Read coroutine before co->ctx. Matches smp_wmb in
449 * qemu_coroutine_enter.
450 */
451 smp_read_barrier_depends();
452 ctx = atomic_read(&co->ctx);
453
454 if (ctx != qemu_get_current_aio_context()) {
455 aio_co_schedule(ctx, co);
456 return;
457 }
458
459 if (qemu_in_coroutine()) {
460 Coroutine *self = qemu_coroutine_self();
461 assert(self != co);
462 QSIMPLEQ_INSERT_TAIL(&self->co_queue_wakeup, co, co_queue_next);
463 } else {
464 aio_context_acquire(ctx);
465 qemu_coroutine_enter(co);
466 aio_context_release(ctx);
467 }
468}
469
405void aio_context_ref(AioContext *ctx)
406{
407 g_source_ref(&ctx->source);
408}
409
410void aio_context_unref(AioContext *ctx)
411{
412 g_source_unref(&ctx->source);
413}
414
415void aio_context_acquire(AioContext *ctx)
416{
417 qemu_rec_mutex_lock(&ctx->lock);
418}
419
420void aio_context_release(AioContext *ctx)
421{
422 qemu_rec_mutex_unlock(&ctx->lock);
423}
470void aio_context_ref(AioContext *ctx)
471{
472 g_source_ref(&ctx->source);
473}
474
475void aio_context_unref(AioContext *ctx)
476{
477 g_source_unref(&ctx->source);
478}
479
480void aio_context_acquire(AioContext *ctx)
481{
482 qemu_rec_mutex_lock(&ctx->lock);
483}
484
485void aio_context_release(AioContext *ctx)
486{
487 qemu_rec_mutex_unlock(&ctx->lock);
488}