diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/block/aio.h | 26 | ||||
-rw-r--r-- | include/qemu/module.h | 4 | ||||
-rw-r--r-- | include/qemu/queue.h | 32 | ||||
-rw-r--r-- | include/qemu/rcu_queue.h | 47 | ||||
-rw-r--r-- | include/sysemu/qtest.h | 4 | ||||
-rw-r--r-- | include/sysemu/sysemu.h | 4 |
6 files changed, 111 insertions, 6 deletions
diff --git a/include/block/aio.h b/include/block/aio.h index 7ba9bd7874..9dd61cee7e 100644 --- a/include/block/aio.h +++ b/include/block/aio.h @@ -42,6 +42,7 @@ void qemu_aio_unref(void *p); void qemu_aio_ref(void *p); typedef struct AioHandler AioHandler; +typedef QLIST_HEAD(, AioHandler) AioHandlerList; typedef void QEMUBHFunc(void *opaque); typedef bool AioPollFn(void *opaque); typedef void IOHandler(void *opaque); @@ -51,6 +52,19 @@ struct ThreadPool; struct LinuxAioState; struct LuringState; +/* + * Each aio_bh_poll() call carves off a slice of the BH list, so that newly + * scheduled BHs are not processed until the next aio_bh_poll() call. All + * active aio_bh_poll() calls chain their slices together in a list, so that + * nested aio_bh_poll() calls process all scheduled bottom halves. + */ +typedef QSLIST_HEAD(, QEMUBH) BHList; +typedef struct BHListSlice BHListSlice; +struct BHListSlice { + BHList bh_list; + QSIMPLEQ_ENTRY(BHListSlice) next; +}; + struct AioContext { GSource source; @@ -58,7 +72,10 @@ struct AioContext { QemuRecMutex lock; /* The list of registered AIO handlers. Protected by ctx->list_lock. */ - QLIST_HEAD(, AioHandler) aio_handlers; + AioHandlerList aio_handlers; + + /* The list of AIO handlers to be deleted. Protected by ctx->list_lock. */ + AioHandlerList deleted_aio_handlers; /* Used to avoid unnecessary event_notifier_set calls in aio_notify; * accessed with atomic primitives. If this field is 0, everything @@ -91,8 +108,11 @@ struct AioContext { */ QemuLockCnt list_lock; - /* Anchor of the list of Bottom Halves belonging to the context */ - struct QEMUBH *first_bh; + /* Bottom Halves pending aio_bh_poll() processing */ + BHList bh_list; + + /* Chained BH list slices for each nested aio_bh_poll() call */ + QSIMPLEQ_HEAD(, BHListSlice) bh_slice_list; /* Used by aio_notify. * diff --git a/include/qemu/module.h b/include/qemu/module.h index 65ba596e46..684753d808 100644 --- a/include/qemu/module.h +++ b/include/qemu/module.h @@ -46,6 +46,7 @@ typedef enum { MODULE_INIT_TRACE, MODULE_INIT_XEN_BACKEND, MODULE_INIT_LIBQOS, + MODULE_INIT_FUZZ_TARGET, MODULE_INIT_MAX } module_init_type; @@ -56,7 +57,8 @@ typedef enum { #define xen_backend_init(function) module_init(function, \ MODULE_INIT_XEN_BACKEND) #define libqos_init(function) module_init(function, MODULE_INIT_LIBQOS) - +#define fuzz_target_init(function) module_init(function, \ + MODULE_INIT_FUZZ_TARGET) #define block_module_load_one(lib) module_load_one("block-", lib) #define ui_module_load_one(lib) module_load_one("ui-", lib) #define audio_module_load_one(lib) module_load_one("audio-", lib) diff --git a/include/qemu/queue.h b/include/qemu/queue.h index 19425f973f..294db54eb1 100644 --- a/include/qemu/queue.h +++ b/include/qemu/queue.h @@ -144,6 +144,23 @@ struct { \ *(elm)->field.le_prev = (elm)->field.le_next; \ } while (/*CONSTCOND*/0) +/* + * Like QLIST_REMOVE() but safe to call when elm is not in a list + */ +#define QLIST_SAFE_REMOVE(elm, field) do { \ + if ((elm)->field.le_prev != NULL) { \ + if ((elm)->field.le_next != NULL) \ + (elm)->field.le_next->field.le_prev = \ + (elm)->field.le_prev; \ + *(elm)->field.le_prev = (elm)->field.le_next; \ + (elm)->field.le_next = NULL; \ + (elm)->field.le_prev = NULL; \ + } \ +} while (/*CONSTCOND*/0) + +/* Is elm in a list? */ +#define QLIST_IS_INSERTED(elm, field) ((elm)->field.le_prev != NULL) + #define QLIST_FOREACH(var, head, field) \ for ((var) = ((head)->lh_first); \ (var); \ @@ -211,9 +228,20 @@ struct { \ (head)->slh_first = (head)->slh_first->field.sle_next; \ } while (/*CONSTCOND*/0) -#define QSLIST_REMOVE_AFTER(slistelm, field) do { \ +#define QSLIST_REMOVE_AFTER(slistelm, field) do { \ (slistelm)->field.sle_next = \ - QSLIST_NEXT(QSLIST_NEXT((slistelm), field), field); \ + QSLIST_NEXT(QSLIST_NEXT((slistelm), field), field); \ +} while (/*CONSTCOND*/0) + +#define QSLIST_REMOVE(head, elm, type, field) do { \ + if ((head)->slh_first == (elm)) { \ + QSLIST_REMOVE_HEAD((head), field); \ + } else { \ + struct type *curelm = (head)->slh_first; \ + while (curelm->field.sle_next != (elm)) \ + curelm = curelm->field.sle_next; \ + curelm->field.sle_next = curelm->field.sle_next->field.sle_next; \ + } \ } while (/*CONSTCOND*/0) #define QSLIST_FOREACH(var, head, field) \ diff --git a/include/qemu/rcu_queue.h b/include/qemu/rcu_queue.h index 2d386f303e..558961cc27 100644 --- a/include/qemu/rcu_queue.h +++ b/include/qemu/rcu_queue.h @@ -262,6 +262,53 @@ extern "C" { (var) && ((next) = atomic_rcu_read(&(var)->field.tqe_next), 1); \ (var) = (next)) +/* + * RCU singly-linked list + */ + +/* Singly-linked list access methods */ +#define QSLIST_EMPTY_RCU(head) (atomic_read(&(head)->slh_first) == NULL) +#define QSLIST_FIRST_RCU(head) atomic_rcu_read(&(head)->slh_first) +#define QSLIST_NEXT_RCU(elm, field) atomic_rcu_read(&(elm)->field.sle_next) + +/* Singly-linked list functions */ +#define QSLIST_INSERT_HEAD_RCU(head, elm, field) do { \ + (elm)->field.sle_next = (head)->slh_first; \ + atomic_rcu_set(&(head)->slh_first, (elm)); \ +} while (/*CONSTCOND*/0) + +#define QSLIST_INSERT_AFTER_RCU(head, listelm, elm, field) do { \ + (elm)->field.sle_next = (listelm)->field.sle_next; \ + atomic_rcu_set(&(listelm)->field.sle_next, (elm)); \ +} while (/*CONSTCOND*/0) + +#define QSLIST_REMOVE_HEAD_RCU(head, field) do { \ + atomic_set(&(head)->slh_first, (head)->slh_first->field.sle_next); \ +} while (/*CONSTCOND*/0) + +#define QSLIST_REMOVE_RCU(head, elm, type, field) do { \ + if ((head)->slh_first == (elm)) { \ + QSLIST_REMOVE_HEAD_RCU((head), field); \ + } else { \ + struct type *curr = (head)->slh_first; \ + while (curr->field.sle_next != (elm)) { \ + curr = curr->field.sle_next; \ + } \ + atomic_set(&curr->field.sle_next, \ + curr->field.sle_next->field.sle_next); \ + } \ +} while (/*CONSTCOND*/0) + +#define QSLIST_FOREACH_RCU(var, head, field) \ + for ((var) = atomic_rcu_read(&(head)->slh_first); \ + (var); \ + (var) = atomic_rcu_read(&(var)->field.sle_next)) + +#define QSLIST_FOREACH_SAFE_RCU(var, head, field, next) \ + for ((var) = atomic_rcu_read(&(head)->slh_first); \ + (var) && ((next) = atomic_rcu_read(&(var)->field.sle_next), 1); \ + (var) = (next)) + #ifdef __cplusplus } #endif diff --git a/include/sysemu/qtest.h b/include/sysemu/qtest.h index 5ed09c80b1..eedd3664f0 100644 --- a/include/sysemu/qtest.h +++ b/include/sysemu/qtest.h @@ -26,4 +26,8 @@ bool qtest_driver(void); void qtest_server_init(const char *qtest_chrdev, const char *qtest_log, Error **errp); +void qtest_server_set_send_handler(void (*send)(void *, const char *), + void *opaque); +void qtest_server_inproc_recv(void *opaque, const char *buf); + #endif diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h index c0678c1ca3..dec64fcc17 100644 --- a/include/sysemu/sysemu.h +++ b/include/sysemu/sysemu.h @@ -115,6 +115,10 @@ QemuOpts *qemu_get_machine_opts(void); bool defaults_enabled(void); +void qemu_init(int argc, char **argv, char **envp); +void qemu_main_loop(void); +void qemu_cleanup(void); + extern QemuOptsList qemu_legacy_drive_opts; extern QemuOptsList qemu_common_drive_opts; extern QemuOptsList qemu_drive_opts; |