From nobody Mon Feb 9 20:31:33 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1491488878774803.3814430846784; Thu, 6 Apr 2017 07:27:58 -0700 (PDT) Received: from localhost ([::1]:46177 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cw8OD-0006xB-B4 for importer@patchew.org; Thu, 06 Apr 2017 10:27:57 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46345) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cw8Mm-0005tT-GF for qemu-devel@nongnu.org; Thu, 06 Apr 2017 10:26:31 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cw8Mj-0001uG-6K for qemu-devel@nongnu.org; Thu, 06 Apr 2017 10:26:28 -0400 Received: from mx1.redhat.com ([209.132.183.28]:40686) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1cw8Md-0001rD-Jq; Thu, 06 Apr 2017 10:26:19 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 955948123D; Thu, 6 Apr 2017 14:26:18 +0000 (UTC) Received: from lemon.redhat.com (ovpn-8-70.pek2.redhat.com [10.72.8.70]) by smtp.corp.redhat.com (Postfix) with ESMTP id D6A2A9B54F; Thu, 6 Apr 2017 14:26:13 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 955948123D Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=famz@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 955948123D From: Fam Zheng To: qemu-devel@nongnu.org Date: Thu, 6 Apr 2017 22:25:27 +0800 Message-Id: <20170406142527.25835-6-famz@redhat.com> In-Reply-To: <20170406142527.25835-1-famz@redhat.com> References: <20170406142527.25835-1-famz@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Thu, 06 Apr 2017 14:26:18 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH for-2.9 5/5] coroutine: Explicitly specify AioContext when creating coroutine X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Fam Zheng , qemu-block@nongnu.org, Max Reitz , Ed Swierk , Stefan Hajnoczi , Paolo Bonzini Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Coroutine in block layer should always be waken up in bs->aio_context rather than the "current" context where it is entered. They differ when the main loop is doing QMP tasks. Race conditions happen without this patch, because the wrong context is acquired in co_schedule_bh_cb, while the entered coroutine works on a different one. Make the block layer explicitly specify a desired context for each created coroutine. For the rest, always use qemu_get_aio_context(). Signed-off-by: Fam Zheng Reviewed-by: Eric Blake --- block.c | 9 +++++++- block/blkverify.c | 4 ++-- block/block-backend.c | 4 ++-- block/io.c | 14 ++++++------- block/nbd-client.c | 2 +- block/quorum.c | 6 +++--- block/sheepdog.c | 4 ++-- blockjob.c | 2 +- hw/9pfs/9p.c | 4 ++-- include/block/block.h | 3 +++ include/qemu/coroutine.h | 3 ++- include/qemu/main-loop.h | 2 +- migration/migration.c | 3 ++- nbd/server.c | 6 ++++-- qemu-img.c | 3 ++- qemu-io-cmds.c | 3 ++- tests/test-aio-multithread.c | 12 +++++++---- tests/test-coroutine.c | 50 ++++++++++++++++++++++++++++++----------= ---- tests/test-thread-pool.c | 3 ++- util/qemu-coroutine.c | 6 ++++-- 20 files changed, 92 insertions(+), 51 deletions(-) diff --git a/block.c b/block.c index e70684a..d3598d5 100644 --- a/block.c +++ b/block.c @@ -357,7 +357,8 @@ int bdrv_create(BlockDriver *drv, const char* filename, /* Fast-path if already in coroutine context */ bdrv_create_co_entry(&cco); } else { - co =3D qemu_coroutine_create(bdrv_create_co_entry, &cco); + co =3D qemu_coroutine_create(qemu_get_aio_context(), + bdrv_create_co_entry, &cco); qemu_coroutine_enter(co); while (cco.ret =3D=3D NOT_DONE) { aio_poll(qemu_get_aio_context(), true); @@ -4323,6 +4324,12 @@ AioContext *bdrv_get_aio_context(BlockDriverState *b= s) return bs->aio_context; } =20 +Coroutine *bdrv_coroutine_create(BlockDriverState *bs, + CoroutineEntry *entry, void *opaque) +{ + return qemu_coroutine_create(bdrv_get_aio_context(bs), entry, opaque); +} + static void bdrv_do_remove_aio_context_notifier(BdrvAioNotifier *ban) { QLIST_REMOVE(ban, list); diff --git a/block/blkverify.c b/block/blkverify.c index 9a1e21c..df761cf 100644 --- a/block/blkverify.c +++ b/block/blkverify.c @@ -204,8 +204,8 @@ blkverify_co_prwv(BlockDriverState *bs, BlkverifyReques= t *r, uint64_t offset, .request_fn =3D is_write ? bdrv_co_pwritev : bdrv_co_preadv, }; =20 - co_a =3D qemu_coroutine_create(blkverify_do_test_req, r); - co_b =3D qemu_coroutine_create(blkverify_do_raw_req, r); + co_a =3D bdrv_coroutine_create(bs, blkverify_do_test_req, r); + co_b =3D bdrv_coroutine_create(bs, blkverify_do_raw_req, r); =20 qemu_coroutine_enter(co_a); qemu_coroutine_enter(co_b); diff --git a/block/block-backend.c b/block/block-backend.c index 0b63773..6a91514 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -1006,7 +1006,7 @@ static int blk_prw(BlockBackend *blk, int64_t offset,= uint8_t *buf, /* Fast-path if already in coroutine context */ co_entry(&rwco); } else { - Coroutine *co =3D qemu_coroutine_create(co_entry, &rwco); + Coroutine *co =3D bdrv_coroutine_create(blk_bs(blk), co_entry, &rw= co); qemu_coroutine_enter(co); BDRV_POLL_WHILE(blk_bs(blk), rwco.ret =3D=3D NOT_DONE); } @@ -1113,7 +1113,7 @@ static BlockAIOCB *blk_aio_prwv(BlockBackend *blk, in= t64_t offset, int bytes, acb->bytes =3D bytes; acb->has_returned =3D false; =20 - co =3D qemu_coroutine_create(co_entry, acb); + co =3D bdrv_coroutine_create(blk_bs(blk), co_entry, acb); qemu_coroutine_enter(co); =20 acb->has_returned =3D true; diff --git a/block/io.c b/block/io.c index b9cfd18..41d7d7b 100644 --- a/block/io.c +++ b/block/io.c @@ -620,7 +620,7 @@ static int bdrv_prwv_co(BdrvChild *child, int64_t offse= t, /* Fast-path if already in coroutine context */ bdrv_rw_co_entry(&rwco); } else { - co =3D qemu_coroutine_create(bdrv_rw_co_entry, &rwco); + co =3D bdrv_coroutine_create(child->bs, bdrv_rw_co_entry, &rwco); qemu_coroutine_enter(co); BDRV_POLL_WHILE(child->bs, rwco.ret =3D=3D NOT_DONE); } @@ -1876,7 +1876,7 @@ int64_t bdrv_get_block_status_above(BlockDriverState = *bs, /* Fast-path if already in coroutine context */ bdrv_get_block_status_above_co_entry(&data); } else { - co =3D qemu_coroutine_create(bdrv_get_block_status_above_co_entry, + co =3D bdrv_coroutine_create(bs, bdrv_get_block_status_above_co_en= try, &data); qemu_coroutine_enter(co); BDRV_POLL_WHILE(bs, !data.done); @@ -2002,7 +2002,7 @@ bdrv_rw_vmstate(BlockDriverState *bs, QEMUIOVector *q= iov, int64_t pos, .is_read =3D is_read, .ret =3D -EINPROGRESS, }; - Coroutine *co =3D qemu_coroutine_create(bdrv_co_rw_vmstate_entry, = &data); + Coroutine *co =3D bdrv_coroutine_create(bs, bdrv_co_rw_vmstate_ent= ry, &data); =20 qemu_coroutine_enter(co); while (data.ret =3D=3D -EINPROGRESS) { @@ -2220,7 +2220,7 @@ static BlockAIOCB *bdrv_co_aio_prw_vector(BdrvChild *= child, acb->req.flags =3D flags; acb->is_write =3D is_write; =20 - co =3D qemu_coroutine_create(bdrv_co_do_rw, acb); + co =3D bdrv_coroutine_create(child->bs, bdrv_co_do_rw, acb); qemu_coroutine_enter(co); =20 bdrv_co_maybe_schedule_bh(acb); @@ -2251,7 +2251,7 @@ BlockAIOCB *bdrv_aio_flush(BlockDriverState *bs, acb->need_bh =3D true; acb->req.error =3D -EINPROGRESS; =20 - co =3D qemu_coroutine_create(bdrv_aio_flush_co_entry, acb); + co =3D bdrv_coroutine_create(bs, bdrv_aio_flush_co_entry, acb); qemu_coroutine_enter(co); =20 bdrv_co_maybe_schedule_bh(acb); @@ -2384,7 +2384,7 @@ int bdrv_flush(BlockDriverState *bs) /* Fast-path if already in coroutine context */ bdrv_flush_co_entry(&flush_co); } else { - co =3D qemu_coroutine_create(bdrv_flush_co_entry, &flush_co); + co =3D bdrv_coroutine_create(bs, bdrv_flush_co_entry, &flush_co); qemu_coroutine_enter(co); BDRV_POLL_WHILE(bs, flush_co.ret =3D=3D NOT_DONE); } @@ -2531,7 +2531,7 @@ int bdrv_pdiscard(BlockDriverState *bs, int64_t offse= t, int count) /* Fast-path if already in coroutine context */ bdrv_pdiscard_co_entry(&rwco); } else { - co =3D qemu_coroutine_create(bdrv_pdiscard_co_entry, &rwco); + co =3D bdrv_coroutine_create(bs, bdrv_pdiscard_co_entry, &rwco); qemu_coroutine_enter(co); BDRV_POLL_WHILE(bs, rwco.ret =3D=3D NOT_DONE); } diff --git a/block/nbd-client.c b/block/nbd-client.c index 1e2952f..526e56b 100644 --- a/block/nbd-client.c +++ b/block/nbd-client.c @@ -421,7 +421,7 @@ int nbd_client_init(BlockDriverState *bs, /* Now that we're connected, set the socket to be non-blocking and * kick the reply mechanism. */ qio_channel_set_blocking(QIO_CHANNEL(sioc), false, NULL); - client->read_reply_co =3D qemu_coroutine_create(nbd_read_reply_entry, = client); + client->read_reply_co =3D bdrv_coroutine_create(bs, nbd_read_reply_ent= ry, client); nbd_client_attach_aio_context(bs, bdrv_get_aio_context(bs)); =20 logout("Established connection with NBD server\n"); diff --git a/block/quorum.c b/block/quorum.c index 40205fb..b34e7eb 100644 --- a/block/quorum.c +++ b/block/quorum.c @@ -317,7 +317,7 @@ static bool quorum_rewrite_bad_versions(QuorumAIOCB *ac= b, .idx =3D item->index, }; =20 - co =3D qemu_coroutine_create(quorum_rewrite_entry, &data); + co =3D bdrv_coroutine_create(acb->bs, quorum_rewrite_entry, &d= ata); qemu_coroutine_enter(co); } } @@ -625,7 +625,7 @@ static int read_quorum_children(QuorumAIOCB *acb) .idx =3D i, }; =20 - co =3D qemu_coroutine_create(read_quorum_children_entry, &data); + co =3D bdrv_coroutine_create(acb->bs, read_quorum_children_entry, = &data); qemu_coroutine_enter(co); } =20 @@ -730,7 +730,7 @@ static int quorum_co_pwritev(BlockDriverState *bs, uint= 64_t offset, .idx =3D i, }; =20 - co =3D qemu_coroutine_create(write_quorum_entry, &data); + co =3D bdrv_coroutine_create(bs, write_quorum_entry, &data); qemu_coroutine_enter(co); } =20 diff --git a/block/sheepdog.c b/block/sheepdog.c index 1b71fc8..bb2feca 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -734,7 +734,7 @@ static int do_req(int sockfd, BlockDriverState *bs, She= epdogReq *hdr, if (qemu_in_coroutine()) { do_co_req(&srco); } else { - co =3D qemu_coroutine_create(do_co_req, &srco); + co =3D bdrv_coroutine_create(bs, do_co_req, &srco); if (bs) { qemu_coroutine_enter(co); BDRV_POLL_WHILE(bs, !srco.finished); @@ -939,7 +939,7 @@ static void co_read_response(void *opaque) BDRVSheepdogState *s =3D opaque; =20 if (!s->co_recv) { - s->co_recv =3D qemu_coroutine_create(aio_read_response, opaque); + s->co_recv =3D bdrv_coroutine_create(s->bs, aio_read_response, opa= que); } =20 aio_co_wake(s->co_recv); diff --git a/blockjob.c b/blockjob.c index 9b619f385..487920f 100644 --- a/blockjob.c +++ b/blockjob.c @@ -286,7 +286,7 @@ void block_job_start(BlockJob *job) { assert(job && !block_job_started(job) && job->paused && job->driver && job->driver->start); - job->co =3D qemu_coroutine_create(block_job_co_entry, job); + job->co =3D bdrv_coroutine_create(blk_bs(job->blk), block_job_co_entry= , job); job->pause_count--; job->busy =3D true; job->paused =3D false; diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c index c80ba67..5ad4bc7 100644 --- a/hw/9pfs/9p.c +++ b/hw/9pfs/9p.c @@ -3462,7 +3462,7 @@ void pdu_submit(V9fsPDU *pdu) if (is_ro_export(&s->ctx) && !is_read_only_op(pdu)) { handler =3D v9fs_fs_ro; } - co =3D qemu_coroutine_create(handler, pdu); + co =3D qemu_coroutine_create(qemu_get_aio_context(), handler, pdu); qemu_coroutine_enter(co); } =20 @@ -3595,7 +3595,7 @@ void v9fs_reset(V9fsState *s) aio_poll(qemu_get_aio_context(), true); } =20 - co =3D qemu_coroutine_create(virtfs_co_reset, &data); + co =3D qemu_coroutine_create(qemu_get_aio_context(), virtfs_co_reset, = &data); qemu_coroutine_enter(co); =20 while (!data.done) { diff --git a/include/block/block.h b/include/block/block.h index 5149260..5dc06bf 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -555,6 +555,9 @@ bool bdrv_debug_is_suspended(BlockDriverState *bs, cons= t char *tag); */ AioContext *bdrv_get_aio_context(BlockDriverState *bs); =20 +Coroutine *bdrv_coroutine_create(BlockDriverState *bs, + CoroutineEntry *entry, void *opaque); + /** * bdrv_set_aio_context: * diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h index e60beaf..57ee53d 100644 --- a/include/qemu/coroutine.h +++ b/include/qemu/coroutine.h @@ -63,7 +63,8 @@ typedef void coroutine_fn CoroutineEntry(void *opaque); * Use qemu_coroutine_enter() to actually transfer control to the coroutin= e. * The opaque argument is passed as the argument to the entry point. */ -Coroutine *qemu_coroutine_create(CoroutineEntry *entry, void *opaque); +Coroutine *qemu_coroutine_create(AioContext *ctx, + CoroutineEntry *entry, void *opaque); =20 /** * Transfer control to a coroutine diff --git a/include/qemu/main-loop.h b/include/qemu/main-loop.h index d7e24af..6680823 100644 --- a/include/qemu/main-loop.h +++ b/include/qemu/main-loop.h @@ -68,7 +68,7 @@ int qemu_init_main_loop(Error **errp); * } * * ... - * QEMUCoroutine *co =3D qemu_coroutine_create(coroutine_entry, NULL); + * QEMUCoroutine *co =3D qemu_coroutine_create(ctx, coroutine_entry, N= ULL); * QEMUBH *start_bh =3D qemu_bh_new(enter_co_bh, co); * qemu_bh_schedule(start_bh); * while (...) { diff --git a/migration/migration.c b/migration/migration.c index 54060f7..7a9a1c6 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -445,7 +445,8 @@ static void process_incoming_migration_co(void *opaque) =20 void migration_fd_process_incoming(QEMUFile *f) { - Coroutine *co =3D qemu_coroutine_create(process_incoming_migration_co,= f); + Coroutine *co =3D qemu_coroutine_create(qemu_get_aio_context(), + process_incoming_migration_co, f= ); =20 migrate_decompress_threads_create(); qemu_file_set_blocking(f, false); diff --git a/nbd/server.c b/nbd/server.c index 924a1fe..ee639ab 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -1363,7 +1363,8 @@ static void nbd_client_receive_next_request(NBDClient= *client) { if (!client->recv_coroutine && client->nb_requests < MAX_NBD_REQUESTS)= { nbd_client_get(client); - client->recv_coroutine =3D qemu_coroutine_create(nbd_trip, client); + client->recv_coroutine =3D qemu_coroutine_create(client->exp->ctx, + nbd_trip, client); aio_co_schedule(client->exp->ctx, client->recv_coroutine); } } @@ -1417,6 +1418,7 @@ void nbd_client_new(NBDExport *exp, client->close =3D close_fn; =20 data->client =3D client; - data->co =3D qemu_coroutine_create(nbd_co_client_start, data); + data->co =3D qemu_coroutine_create(exp ? exp->ctx : qemu_get_aio_conte= xt(), + nbd_co_client_start, data); qemu_coroutine_enter(data->co); } diff --git a/qemu-img.c b/qemu-img.c index b220cf7..9b3dd98 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -1894,7 +1894,8 @@ static int convert_do_copy(ImgConvertState *s) =20 qemu_co_mutex_init(&s->lock); for (i =3D 0; i < s->num_coroutines; i++) { - s->co[i] =3D qemu_coroutine_create(convert_co_do_copy, s); + s->co[i] =3D qemu_coroutine_create(qemu_get_aio_context(), + convert_co_do_copy, s); s->wait_sector_num[i] =3D -1; qemu_coroutine_enter(s->co[i]); } diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c index 883f53b..31944bb 100644 --- a/qemu-io-cmds.c +++ b/qemu-io-cmds.c @@ -520,7 +520,8 @@ static int do_co_pwrite_zeroes(BlockBackend *blk, int64= _t offset, return -ERANGE; } =20 - co =3D qemu_coroutine_create(co_pwrite_zeroes_entry, &data); + co =3D qemu_coroutine_create(qemu_get_aio_context(), + co_pwrite_zeroes_entry, &data); qemu_coroutine_enter(co); while (!data.done) { aio_poll(blk_get_aio_context(blk), true); diff --git a/tests/test-aio-multithread.c b/tests/test-aio-multithread.c index 549d784..325dded 100644 --- a/tests/test-aio-multithread.c +++ b/tests/test-aio-multithread.c @@ -168,7 +168,8 @@ static void test_multi_co_schedule(int seconds) =20 create_aio_contexts(); for (i =3D 0; i < NUM_CONTEXTS; i++) { - Coroutine *co1 =3D qemu_coroutine_create(test_multi_co_schedule_en= try, NULL); + Coroutine *co1 =3D qemu_coroutine_create(ctx[i], + test_multi_co_schedule_entr= y, NULL); aio_co_schedule(ctx[i], co1); } =20 @@ -233,7 +234,8 @@ static void test_multi_co_mutex(int threads, int second= s) assert(threads <=3D NUM_CONTEXTS); running =3D threads; for (i =3D 0; i < threads; i++) { - Coroutine *co1 =3D qemu_coroutine_create(test_multi_co_mutex_entry= , NULL); + Coroutine *co1 =3D qemu_coroutine_create(ctx[i], + test_multi_co_mutex_entry, = NULL); aio_co_schedule(ctx[i], co1); } =20 @@ -352,7 +354,8 @@ static void test_multi_fair_mutex(int threads, int seco= nds) assert(threads <=3D NUM_CONTEXTS); running =3D threads; for (i =3D 0; i < threads; i++) { - Coroutine *co1 =3D qemu_coroutine_create(test_multi_fair_mutex_ent= ry, NULL); + Coroutine *co1 =3D qemu_coroutine_create(ctx[i], + test_multi_fair_mutex_entry= , NULL); aio_co_schedule(ctx[i], co1); } =20 @@ -408,7 +411,8 @@ static void test_multi_mutex(int threads, int seconds) assert(threads <=3D NUM_CONTEXTS); running =3D threads; for (i =3D 0; i < threads; i++) { - Coroutine *co1 =3D qemu_coroutine_create(test_multi_mutex_entry, N= ULL); + Coroutine *co1 =3D qemu_coroutine_create(ctx[i], + test_multi_mutex_entry, NUL= L); aio_co_schedule(ctx[i], co1); } =20 diff --git a/tests/test-coroutine.c b/tests/test-coroutine.c index abd97c2..12a6575 100644 --- a/tests/test-coroutine.c +++ b/tests/test-coroutine.c @@ -14,6 +14,7 @@ #include "qemu/osdep.h" #include "qemu/coroutine.h" #include "qemu/coroutine_int.h" +#include "qemu/main-loop.h" =20 /* * Check that qemu_in_coroutine() works @@ -30,7 +31,8 @@ static void test_in_coroutine(void) =20 g_assert(!qemu_in_coroutine()); =20 - coroutine =3D qemu_coroutine_create(verify_in_coroutine, NULL); + coroutine =3D qemu_coroutine_create(qemu_get_aio_context(), + verify_in_coroutine, NULL); qemu_coroutine_enter(coroutine); } =20 @@ -48,7 +50,8 @@ static void test_self(void) { Coroutine *coroutine; =20 - coroutine =3D qemu_coroutine_create(verify_self, &coroutine); + coroutine =3D qemu_coroutine_create(qemu_get_aio_context(), + verify_self, &coroutine); qemu_coroutine_enter(coroutine); } =20 @@ -77,7 +80,8 @@ static void coroutine_fn verify_entered_step_1(void *opaq= ue) =20 g_assert(qemu_coroutine_entered(self)); =20 - coroutine =3D qemu_coroutine_create(verify_entered_step_2, self); + coroutine =3D qemu_coroutine_create(qemu_get_aio_context(), + verify_entered_step_2, self); g_assert(!qemu_coroutine_entered(coroutine)); qemu_coroutine_enter(coroutine); g_assert(!qemu_coroutine_entered(coroutine)); @@ -88,7 +92,8 @@ static void test_entered(void) { Coroutine *coroutine; =20 - coroutine =3D qemu_coroutine_create(verify_entered_step_1, NULL); + coroutine =3D qemu_coroutine_create(qemu_get_aio_context(), + verify_entered_step_1, NULL); g_assert(!qemu_coroutine_entered(coroutine)); qemu_coroutine_enter(coroutine); } @@ -112,7 +117,8 @@ static void coroutine_fn nest(void *opaque) if (nd->n_enter < nd->max) { Coroutine *child; =20 - child =3D qemu_coroutine_create(nest, nd); + child =3D qemu_coroutine_create(qemu_get_aio_context(), + nest, nd); qemu_coroutine_enter(child); } =20 @@ -128,7 +134,8 @@ static void test_nesting(void) .max =3D 128, }; =20 - root =3D qemu_coroutine_create(nest, &nd); + root =3D qemu_coroutine_create(qemu_get_aio_context(), + nest, &nd); qemu_coroutine_enter(root); =20 /* Must enter and return from max nesting level */ @@ -157,7 +164,8 @@ static void test_yield(void) bool done =3D false; int i =3D -1; /* one extra time to return from coroutine */ =20 - coroutine =3D qemu_coroutine_create(yield_5_times, &done); + coroutine =3D qemu_coroutine_create(qemu_get_aio_context(), + yield_5_times, &done); while (!done) { qemu_coroutine_enter(coroutine); i++; @@ -182,8 +190,11 @@ static void test_co_queue(void) Coroutine *c2; Coroutine tmp; =20 - c2 =3D qemu_coroutine_create(c2_fn, NULL); - c1 =3D qemu_coroutine_create(c1_fn, c2); + qemu_init_main_loop(NULL); + c2 =3D qemu_coroutine_create(qemu_get_aio_context(), + c2_fn, NULL); + c1 =3D qemu_coroutine_create(qemu_get_aio_context(), + c1_fn, c2); =20 qemu_coroutine_enter(c1); =20 @@ -213,13 +224,15 @@ static void test_lifecycle(void) bool done =3D false; =20 /* Create, enter, and return from coroutine */ - coroutine =3D qemu_coroutine_create(set_and_exit, &done); + coroutine =3D qemu_coroutine_create(qemu_get_aio_context(), + set_and_exit, &done); qemu_coroutine_enter(coroutine); g_assert(done); /* expect done to be true (first time) */ =20 /* Repeat to check that no state affects this test */ done =3D false; - coroutine =3D qemu_coroutine_create(set_and_exit, &done); + coroutine =3D qemu_coroutine_create(qemu_get_aio_context(), + set_and_exit, &done); qemu_coroutine_enter(coroutine); g_assert(done); /* expect done to be true (second time) */ } @@ -254,7 +267,8 @@ static void do_order_test(void) { Coroutine *co; =20 - co =3D qemu_coroutine_create(co_order_test, NULL); + co =3D qemu_coroutine_create(qemu_get_aio_context(), + co_order_test, NULL); record_push(1, 1); qemu_coroutine_enter(co); record_push(1, 2); @@ -296,7 +310,8 @@ static void perf_lifecycle(void) =20 g_test_timer_start(); for (i =3D 0; i < max; i++) { - coroutine =3D qemu_coroutine_create(empty_coroutine, NULL); + coroutine =3D qemu_coroutine_create(qemu_get_aio_context(), + empty_coroutine, NULL); qemu_coroutine_enter(coroutine); } duration =3D g_test_timer_elapsed(); @@ -320,7 +335,8 @@ static void perf_nesting(void) .n_return =3D 0, .max =3D maxnesting, }; - root =3D qemu_coroutine_create(nest, &nd); + root =3D qemu_coroutine_create(qemu_get_aio_context(), + nest, &nd); qemu_coroutine_enter(root); } duration =3D g_test_timer_elapsed(); @@ -350,7 +366,8 @@ static void perf_yield(void) =20 maxcycles =3D 100000000; i =3D maxcycles; - Coroutine *coroutine =3D qemu_coroutine_create(yield_loop, &i); + Coroutine *coroutine =3D qemu_coroutine_create(qemu_get_aio_context(), + yield_loop, &i); =20 g_test_timer_start(); while (i > 0) { @@ -400,7 +417,8 @@ static void perf_cost(void) =20 g_test_timer_start(); while (i++ < maxcycles) { - co =3D qemu_coroutine_create(perf_cost_func, &i); + co =3D qemu_coroutine_create(qemu_get_aio_context(), + perf_cost_func, &i); qemu_coroutine_enter(co); qemu_coroutine_enter(co); } diff --git a/tests/test-thread-pool.c b/tests/test-thread-pool.c index 91b4ec5..86d993a 100644 --- a/tests/test-thread-pool.c +++ b/tests/test-thread-pool.c @@ -92,7 +92,8 @@ static void co_test_cb(void *opaque) static void test_submit_co(void) { WorkerTestData data; - Coroutine *co =3D qemu_coroutine_create(co_test_cb, &data); + Coroutine *co =3D qemu_coroutine_create(qemu_get_aio_context(), + co_test_cb, &data); =20 qemu_coroutine_enter(co); =20 diff --git a/util/qemu-coroutine.c b/util/qemu-coroutine.c index 72412e5..690d5a4 100644 --- a/util/qemu-coroutine.c +++ b/util/qemu-coroutine.c @@ -43,7 +43,8 @@ static void coroutine_pool_cleanup(Notifier *n, void *val= ue) } } =20 -Coroutine *qemu_coroutine_create(CoroutineEntry *entry, void *opaque) +Coroutine *qemu_coroutine_create(AioContext *ctx, + CoroutineEntry *entry, void *opaque) { Coroutine *co =3D NULL; =20 @@ -78,6 +79,7 @@ Coroutine *qemu_coroutine_create(CoroutineEntry *entry, v= oid *opaque) =20 co->entry =3D entry; co->entry_arg =3D opaque; + co->ctx =3D ctx; QSIMPLEQ_INIT(&co->co_queue_wakeup); return co; } @@ -107,6 +109,7 @@ void qemu_coroutine_enter(Coroutine *co) Coroutine *self =3D qemu_coroutine_self(); CoroutineAction ret; =20 + assert(co->ctx); trace_qemu_coroutine_enter(self, co, co->entry_arg); =20 if (co->caller) { @@ -115,7 +118,6 @@ void qemu_coroutine_enter(Coroutine *co) } =20 co->caller =3D self; - co->ctx =3D qemu_get_current_aio_context(); =20 /* Store co->ctx before anything that stores co. Matches * barrier in aio_co_wake and qemu_co_mutex_wake. --=20 2.9.3