qemu-block
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 12/35] define magic macros for stackless coroutines


From: Paolo Bonzini
Subject: [PATCH 12/35] define magic macros for stackless coroutines
Date: Thu, 10 Mar 2022 13:43:50 +0100

Because conversion to stackless coroutines is incredibly repetitive,
define some magic variable-argument macros that simplify the task:

- CO_DECLARE_FRAME() declares a frame structure, with a couple common fields
  and the extras coming from variable arguments

- CO_INIT_FRAME() allocates the frame structure, builds it using any arguments
  provided by the user, and continues with the second part of the
  awaitable function that takes the frame as its only argument

- CO_ARG() declare variables and load them from the frame structure.  It
  uses typeof() to avoid repetition of the type of the variable (it is needed
  only twice, in CO_DECLARE_FRAME() and in the declaration of the user-visible
  awaitable function)

- CO_DECLARE() also declares variables using typeof, but it's for locals that
  are not prepared by CO_INIT_FRAME()

- CO_SAVE() and CO_LOAD() copy to and from the frame structure

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 include/qemu/coroutine.h | 41 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 41 insertions(+)

diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h
index 2f2be6abfe..df148ff80e 100644
--- a/include/qemu/coroutine.h
+++ b/include/qemu/coroutine.h
@@ -361,4 +361,45 @@ void qemu_coroutine_decrease_pool_batch_size(unsigned int 
additional_pool_size);
 void *coroutine_only_fn stack_alloc(CoroutineImpl *func, size_t bytes);
 CoroutineAction coroutine_only_fn stack_free(CoroutineFrame *f);
 
+
+#define CO_DO(MACRO, ...) CO_DO_(MACRO, __VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 
2, 1, 0)
+#define CO_DO_(MACRO, a0, a1, a2, a3, a4, a5, a6, a7, a8 , a9, n, ...) 
CO_DO##n(MACRO, a0, a1, a2, a3, a4, a5, a6, a7, a8 , a9)
+#define CO_DO0(MACRO, a0, ...)
+#define CO_DO1(MACRO, a0, ...) MACRO(a0)
+#define CO_DO2(MACRO, a0, ...) MACRO(a0); CO_DO1(MACRO, __VA_ARGS__)
+#define CO_DO3(MACRO, a0, ...) MACRO(a0); CO_DO2(MACRO, __VA_ARGS__)
+#define CO_DO4(MACRO, a0, ...) MACRO(a0); CO_DO3(MACRO, __VA_ARGS__)
+#define CO_DO5(MACRO, a0, ...) MACRO(a0); CO_DO4(MACRO, __VA_ARGS__)
+#define CO_DO6(MACRO, a0, ...) MACRO(a0); CO_DO5(MACRO, __VA_ARGS__)
+#define CO_DO7(MACRO, a0, ...) MACRO(a0); CO_DO6(MACRO, __VA_ARGS__)
+#define CO_DO8(MACRO, a0, ...) MACRO(a0); CO_DO7(MACRO, __VA_ARGS__)
+#define CO_DO9(MACRO, a0, ...) MACRO(a0); CO_DO8(MACRO, __VA_ARGS__)
+
+#define CO_FRAME1(decl) decl
+#define CO_SAVE1(var) _f->var = var
+#define CO_LOAD1(var) var = _f->var
+#define CO_DECLARE1(var) typeof(_f->var) var
+#define CO_ARG1(var) typeof(_f->var) var = _f->var
+
+#define CO_SAVE(...) CO_DO(CO_SAVE1, __VA_ARGS__)
+#define CO_LOAD(...) CO_DO(CO_LOAD1, __VA_ARGS__)
+#define CO_DECLARE(...) CO_DO(CO_DECLARE1, __VA_ARGS__)
+#define CO_ARG(...) CO_DO(CO_ARG1, __VA_ARGS__)
+
+#define CO_DECLARE_FRAME(func, ...) \
+    struct FRAME__##func { \
+        CoroutineFrame common; \
+        uint32_t _step; \
+        CO_DO(CO_FRAME1, __VA_ARGS__); \
+    }
+
+#define CO_INIT_FRAME(func, ...) \
+    co__##func(({ \
+        struct FRAME__##func *_f; \
+        _f = stack_alloc(co__##func, sizeof(*_f)); \
+        __VA_OPT__(CO_SAVE(__VA_ARGS__);) \
+        _f->_step = 0; \
+        _f; \
+    }))
+
 #endif /* QEMU_COROUTINE_H */
-- 
2.35.1





reply via email to

[Prev in Thread] Current Thread [Next in Thread]