diff options
-rw-r--r-- | accel/tcg/debuginfo.h | 2 | ||||
-rw-r--r-- | hw/9pfs/coth.h | 2 | ||||
-rw-r--r-- | include/block/aio.h | 2 | ||||
-rw-r--r-- | include/io/channel.h | 2 | ||||
-rw-r--r-- | include/qemu/coroutine-core.h | 154 | ||||
-rw-r--r-- | include/qemu/coroutine.h | 97 | ||||
-rw-r--r-- | include/qemu/lockable.h | 2 | ||||
-rw-r--r-- | include/qemu/typedefs.h | 1 | ||||
-rw-r--r-- | nbd/client-connection.c | 1 | ||||
-rw-r--r-- | tests/unit/test-aio.c | 2 | ||||
-rw-r--r-- | ui/console.c | 1 |
11 files changed, 164 insertions, 102 deletions
diff --git a/accel/tcg/debuginfo.h b/accel/tcg/debuginfo.h index 7542cfe6e0..f064e1c144 100644 --- a/accel/tcg/debuginfo.h +++ b/accel/tcg/debuginfo.h @@ -7,6 +7,8 @@ #ifndef ACCEL_TCG_DEBUGINFO_H #define ACCEL_TCG_DEBUGINFO_H +#include "qemu/bitops.h" + /* * Debuginfo describing a certain address. */ diff --git a/hw/9pfs/coth.h b/hw/9pfs/coth.h index 1a1edbdc2a..2c54249b35 100644 --- a/hw/9pfs/coth.h +++ b/hw/9pfs/coth.h @@ -16,7 +16,7 @@ #define QEMU_9P_COTH_H #include "qemu/thread.h" -#include "qemu/coroutine.h" +#include "qemu/coroutine-core.h" #include "9p.h" /* diff --git a/include/block/aio.h b/include/block/aio.h index 0f65a3cc9e..3a546e7515 100644 --- a/include/block/aio.h +++ b/include/block/aio.h @@ -17,7 +17,7 @@ #ifdef CONFIG_LINUX_IO_URING #include <liburing.h> #endif -#include "qemu/coroutine.h" +#include "qemu/coroutine-core.h" #include "qemu/queue.h" #include "qemu/event_notifier.h" #include "qemu/thread.h" diff --git a/include/io/channel.h b/include/io/channel.h index f1b7e05f81..78b15f7870 100644 --- a/include/io/channel.h +++ b/include/io/channel.h @@ -22,7 +22,7 @@ #define QIO_CHANNEL_H #include "qom/object.h" -#include "qemu/coroutine.h" +#include "qemu/coroutine-core.h" #include "block/aio.h" #define TYPE_QIO_CHANNEL "qio-channel" diff --git a/include/qemu/coroutine-core.h b/include/qemu/coroutine-core.h new file mode 100644 index 0000000000..230bb56517 --- /dev/null +++ b/include/qemu/coroutine-core.h @@ -0,0 +1,154 @@ +/* + * QEMU coroutine implementation + * + * Copyright IBM, Corp. 2011 + * + * Authors: + * Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> + * Kevin Wolf <kwolf@redhat.com> + * + * This work is licensed under the terms of the GNU LGPL, version 2 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ + +#ifndef QEMU_COROUTINE_CORE_H +#define QEMU_COROUTINE_CORE_H + +/** + * Coroutines are a mechanism for stack switching and can be used for + * cooperative userspace threading. These functions provide a simple but + * useful flavor of coroutines that is suitable for writing sequential code, + * rather than callbacks, for operations that need to give up control while + * waiting for events to complete. + * + * These functions are re-entrant and may be used outside the global mutex. + * + * Functions that execute in coroutine context cannot be called + * directly from normal functions. Use @coroutine_fn to mark such + * functions. For example: + * + * static void coroutine_fn foo(void) { + * .... + * } + * + * In the future it would be nice to have the compiler or a static + * checker catch misuse of such functions. This annotation might make + * it possible and in the meantime it serves as documentation. + */ + +/** + * Mark a function that executes in coroutine context + * + * + * Functions that execute in coroutine context cannot be called + * directly from normal functions. Use @coroutine_fn to mark such + * functions. For example: + * + * static void coroutine_fn foo(void) { + * .... + * } + * + * In the future it would be nice to have the compiler or a static + * checker catch misuse of such functions. This annotation might make + * it possible and in the meantime it serves as documentation. + */ + +typedef struct Coroutine Coroutine; +typedef struct CoMutex CoMutex; + +/** + * Coroutine entry point + * + * When the coroutine is entered for the first time, opaque is passed in as an + * argument. + * + * When this function returns, the coroutine is destroyed automatically and + * execution continues in the caller who last entered the coroutine. + */ +typedef void coroutine_fn CoroutineEntry(void *opaque); + +/** + * Create a new coroutine + * + * Use qemu_coroutine_enter() to actually transfer control to the coroutine. + * The opaque argument is passed as the argument to the entry point. + */ +Coroutine *qemu_coroutine_create(CoroutineEntry *entry, void *opaque); + +/** + * Transfer control to a coroutine + */ +void qemu_coroutine_enter(Coroutine *coroutine); + +/** + * Transfer control to a coroutine if it's not active (i.e. part of the call + * stack of the running coroutine). Otherwise, do nothing. + */ +void qemu_coroutine_enter_if_inactive(Coroutine *co); + +/** + * Transfer control to a coroutine and associate it with ctx + */ +void qemu_aio_coroutine_enter(AioContext *ctx, Coroutine *co); + +/** + * Transfer control back to a coroutine's caller + * + * This function does not return until the coroutine is re-entered using + * qemu_coroutine_enter(). + */ +void coroutine_fn qemu_coroutine_yield(void); + +/** + * Get the AioContext of the given coroutine + */ +AioContext *qemu_coroutine_get_aio_context(Coroutine *co); + +/** + * Get the currently executing coroutine + */ +Coroutine *qemu_coroutine_self(void); + +/** + * Return whether or not currently inside a coroutine + * + * This can be used to write functions that work both when in coroutine context + * and when not in coroutine context. Note that such functions cannot use the + * coroutine_fn annotation since they work outside coroutine context. + */ +bool qemu_in_coroutine(void); + +/** + * Return true if the coroutine is currently entered + * + * A coroutine is "entered" if it has not yielded from the current + * qemu_coroutine_enter() call used to run it. This does not mean that the + * coroutine is currently executing code since it may have transferred control + * to another coroutine using qemu_coroutine_enter(). + * + * When several coroutines enter each other there may be no way to know which + * ones have already been entered. In such situations this function can be + * used to avoid recursively entering coroutines. + */ +bool qemu_coroutine_entered(Coroutine *co); + +/** + * Initialises a CoMutex. This must be called before any other operation is used + * on the CoMutex. + */ +void qemu_co_mutex_init(CoMutex *mutex); + +/** + * Locks the mutex. If the lock cannot be taken immediately, control is + * transferred to the caller of the current coroutine. + */ +void coroutine_fn qemu_co_mutex_lock(CoMutex *mutex); + +/** + * Unlocks the mutex and schedules the next coroutine that was waiting for this + * lock to be run. + */ +void coroutine_fn qemu_co_mutex_unlock(CoMutex *mutex); + +#endif diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h index 2496a4f4ef..a65be6697f 100644 --- a/include/qemu/coroutine.h +++ b/include/qemu/coroutine.h @@ -15,6 +15,7 @@ #ifndef QEMU_COROUTINE_H #define QEMU_COROUTINE_H +#include "qemu/coroutine-core.h" #include "qemu/queue.h" #include "qemu/timer.h" @@ -40,84 +41,6 @@ * it possible and in the meantime it serves as documentation. */ -typedef struct Coroutine Coroutine; - -/** - * Coroutine entry point - * - * When the coroutine is entered for the first time, opaque is passed in as an - * argument. - * - * When this function returns, the coroutine is destroyed automatically and - * execution continues in the caller who last entered the coroutine. - */ -typedef void coroutine_fn CoroutineEntry(void *opaque); - -/** - * Create a new coroutine - * - * Use qemu_coroutine_enter() to actually transfer control to the coroutine. - * The opaque argument is passed as the argument to the entry point. - */ -Coroutine *qemu_coroutine_create(CoroutineEntry *entry, void *opaque); - -/** - * Transfer control to a coroutine - */ -void qemu_coroutine_enter(Coroutine *coroutine); - -/** - * Transfer control to a coroutine if it's not active (i.e. part of the call - * stack of the running coroutine). Otherwise, do nothing. - */ -void qemu_coroutine_enter_if_inactive(Coroutine *co); - -/** - * Transfer control to a coroutine and associate it with ctx - */ -void qemu_aio_coroutine_enter(AioContext *ctx, Coroutine *co); - -/** - * Transfer control back to a coroutine's caller - * - * This function does not return until the coroutine is re-entered using - * qemu_coroutine_enter(). - */ -void coroutine_fn qemu_coroutine_yield(void); - -/** - * Get the AioContext of the given coroutine - */ -AioContext *qemu_coroutine_get_aio_context(Coroutine *co); - -/** - * Get the currently executing coroutine - */ -Coroutine *qemu_coroutine_self(void); - -/** - * Return whether or not currently inside a coroutine - * - * This can be used to write functions that work both when in coroutine context - * and when not in coroutine context. Note that such functions cannot use the - * coroutine_fn annotation since they work outside coroutine context. - */ -bool qemu_in_coroutine(void); - -/** - * Return true if the coroutine is currently entered - * - * A coroutine is "entered" if it has not yielded from the current - * qemu_coroutine_enter() call used to run it. This does not mean that the - * coroutine is currently executing code since it may have transferred control - * to another coroutine using qemu_coroutine_enter(). - * - * When several coroutines enter each other there may be no way to know which - * ones have already been entered. In such situations this function can be - * used to avoid recursively entering coroutines. - */ -bool qemu_coroutine_entered(Coroutine *co); - /** * Provides a mutex that can be used to synchronise coroutines */ @@ -146,24 +69,6 @@ struct CoMutex { }; /** - * Initialises a CoMutex. This must be called before any other operation is used - * on the CoMutex. - */ -void qemu_co_mutex_init(CoMutex *mutex); - -/** - * Locks the mutex. If the lock cannot be taken immediately, control is - * transferred to the caller of the current coroutine. - */ -void coroutine_fn qemu_co_mutex_lock(CoMutex *mutex); - -/** - * Unlocks the mutex and schedules the next coroutine that was waiting for this - * lock to be run. - */ -void coroutine_fn qemu_co_mutex_unlock(CoMutex *mutex); - -/** * Assert that the current coroutine holds @mutex. */ static inline coroutine_fn void qemu_co_mutex_assert_locked(CoMutex *mutex) diff --git a/include/qemu/lockable.h b/include/qemu/lockable.h index 86db7cb04c..9823220446 100644 --- a/include/qemu/lockable.h +++ b/include/qemu/lockable.h @@ -13,7 +13,7 @@ #ifndef QEMU_LOCKABLE_H #define QEMU_LOCKABLE_H -#include "qemu/coroutine.h" +#include "qemu/coroutine-core.h" #include "qemu/thread.h" typedef void QemuLockUnlockFunc(void *); diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h index fba04875c2..c7c8a85315 100644 --- a/include/qemu/typedefs.h +++ b/include/qemu/typedefs.h @@ -38,7 +38,6 @@ typedef struct BusState BusState; typedef struct Chardev Chardev; typedef struct Clock Clock; typedef struct CompatProperty CompatProperty; -typedef struct CoMutex CoMutex; typedef struct ConfidentialGuestSupport ConfidentialGuestSupport; typedef struct CPUAddressSpace CPUAddressSpace; typedef struct CPUArchState CPUArchState; diff --git a/nbd/client-connection.c b/nbd/client-connection.c index 0c5f917efa..e5b1046a1c 100644 --- a/nbd/client-connection.c +++ b/nbd/client-connection.c @@ -29,6 +29,7 @@ #include "qapi/qapi-visit-sockets.h" #include "qapi/clone-visitor.h" +#include "qemu/coroutine.h" struct NBDClientConnection { /* Initialization constants, never change */ diff --git a/tests/unit/test-aio.c b/tests/unit/test-aio.c index 178048d2f2..321d7ab01a 100644 --- a/tests/unit/test-aio.c +++ b/tests/unit/test-aio.c @@ -16,7 +16,7 @@ #include "qemu/timer.h" #include "qemu/sockets.h" #include "qemu/error-report.h" -#include "qemu/coroutine.h" +#include "qemu/coroutine-core.h" #include "qemu/main-loop.h" static AioContext *ctx; diff --git a/ui/console.c b/ui/console.c index 9ff9217f9b..ab43561fe1 100644 --- a/ui/console.c +++ b/ui/console.c @@ -27,6 +27,7 @@ #include "hw/qdev-core.h" #include "qapi/error.h" #include "qapi/qapi-commands-ui.h" +#include "qemu/coroutine.h" #include "qemu/fifo8.h" #include "qemu/main-loop.h" #include "qemu/module.h" |