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} |