This is just a sketch. It needs comments and a real commit message. As is, it goes on top of Kevin's series. It is meant to be squashed into PATCH 06.
Signed-off-by: Markus Armbruster <arm...@redhat.com> --- include/qemu/coroutine.h | 4 ++++ include/qemu/coroutine_int.h | 2 ++ monitor/monitor.c | 36 +++++++++++++++--------------------- util/qemu-coroutine.c | 20 ++++++++++++++++++++ 4 files changed, 41 insertions(+), 21 deletions(-) diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h index dfd261c5b1..11da47092c 100644 --- a/include/qemu/coroutine.h +++ b/include/qemu/coroutine.h @@ -65,6 +65,10 @@ typedef void coroutine_fn CoroutineEntry(void *opaque); */ Coroutine *qemu_coroutine_create(CoroutineEntry *entry, void *opaque); +Coroutine *qemu_coroutine_create_with_storage(CoroutineEntry *entry, + void *opaque, size_t storage); +void *qemu_coroutine_local_storage(Coroutine *co); + /** * Transfer control to a coroutine */ diff --git a/include/qemu/coroutine_int.h b/include/qemu/coroutine_int.h index bd6b0468e1..7d7865a02f 100644 --- a/include/qemu/coroutine_int.h +++ b/include/qemu/coroutine_int.h @@ -41,6 +41,8 @@ struct Coroutine { void *entry_arg; Coroutine *caller; + void *coroutine_local_storage; + /* Only used when the coroutine has terminated. */ QSLIST_ENTRY(Coroutine) pool_next; diff --git a/monitor/monitor.c b/monitor/monitor.c index 50fb5b20d3..047a8fb380 100644 --- a/monitor/monitor.c +++ b/monitor/monitor.c @@ -82,38 +82,32 @@ bool qmp_dispatcher_co_shutdown; */ bool qmp_dispatcher_co_busy; -/* - * Protects mon_list, monitor_qapi_event_state, coroutine_mon, - * monitor_destroyed. - */ +/* Protects mon_list, monitor_qapi_event_state, monitor_destroyed. */ QemuMutex monitor_lock; static GHashTable *monitor_qapi_event_state; -static GHashTable *coroutine_mon; /* Maps Coroutine* to Monitor* */ MonitorList mon_list; int mon_refcount; static bool monitor_destroyed; +static Monitor **monitor_curp(Coroutine *co) +{ + static __thread Monitor *global_cur_mon; + + if (co == qmp_dispatcher_co) { + return qemu_coroutine_local_storage(co); + } + return &global_cur_mon; +} + Monitor *monitor_cur(void) { - Monitor *mon; - - qemu_mutex_lock(&monitor_lock); - mon = g_hash_table_lookup(coroutine_mon, qemu_coroutine_self()); - qemu_mutex_unlock(&monitor_lock); - - return mon; + return *monitor_curp(qemu_coroutine_self()); } void monitor_set_cur(Coroutine *co, Monitor *mon) { - qemu_mutex_lock(&monitor_lock); - if (mon) { - g_hash_table_replace(coroutine_mon, co, mon); - } else { - g_hash_table_remove(coroutine_mon, co); - } - qemu_mutex_unlock(&monitor_lock); + *monitor_curp(co) = mon; } /** @@ -666,14 +660,14 @@ void monitor_init_globals_core(void) { monitor_qapi_event_init(); qemu_mutex_init(&monitor_lock); - coroutine_mon = g_hash_table_new(NULL, NULL); /* * The dispatcher BH must run in the main loop thread, since we * have commands assuming that context. It would be nice to get * rid of those assumptions. */ - qmp_dispatcher_co = qemu_coroutine_create(monitor_qmp_dispatcher_co, NULL); + qmp_dispatcher_co = qemu_coroutine_create_with_storage( + monitor_qmp_dispatcher_co, NULL, sizeof(Monitor **)); atomic_mb_set(&qmp_dispatcher_co_busy, true); aio_co_schedule(iohandler_get_aio_context(), qmp_dispatcher_co); } diff --git a/util/qemu-coroutine.c b/util/qemu-coroutine.c index c3caa6c770..87bf7f0fc0 100644 --- a/util/qemu-coroutine.c +++ b/util/qemu-coroutine.c @@ -81,8 +81,28 @@ Coroutine *qemu_coroutine_create(CoroutineEntry *entry, void *opaque) return co; } +Coroutine *qemu_coroutine_create_with_storage(CoroutineEntry *entry, + void *opaque, size_t storage) +{ + Coroutine *co = qemu_coroutine_create(entry, opaque); + + if (!co) { + return NULL; + } + + co->coroutine_local_storage = g_malloc0(storage); + return co; +} + +void *qemu_coroutine_local_storage(Coroutine *co) +{ + return co->coroutine_local_storage; +} + static void coroutine_delete(Coroutine *co) { + g_free(co->coroutine_local_storage); + co->coroutine_local_storage = NULL; co->caller = NULL; if (CONFIG_COROUTINE_POOL) { -- 2.26.2