1 /* Licensed under LGPLv2.1+ - see LICENSE file for details */
2 #ifndef CCAN_COROUTINE_H
3 #define CCAN_COROUTINE_H
4 /*#define CCAN_COROUTINE_DEBUG 1*/
12 #include <ccan/compiler/compiler.h>
13 #include <ccan/typesafe_cb/typesafe_cb.h>
16 * struct coroutine_stack
18 * Describes a stack suitable for executing a coroutine. This
19 * structure is always contained within the stack it describes.
21 struct coroutine_stack {
28 * struct coroutine_state
30 * Describes the state of an in-progress coroutine.
32 struct coroutine_state;
39 * COROUTINE_STK_OVERHEAD - internal stack overhead
41 * Number of bytes of a stack which coroutine needs for its own
42 * tracking information.
44 #define COROUTINE_STK_OVERHEAD sizeof(struct coroutine_stack)
47 * COROUTINE_MIN_STKSZ - Minimum coroutine stack size
49 * Contains the minimum size for a coroutine stack (not including
50 * overhead). On systems with MINSTKSZ, guaranteed to be at least as
53 #define COROUTINE_MIN_STKSZ 2048
56 * COROUTINE_STACK_MAGIC_BUF - Magic number for coroutine stacks in a user
59 #define COROUTINE_STACK_MAGIC_BUF 0xc040c040574cb00f
62 * COROUTINE_STACK_MAGIC_ALLOC - Magic number for coroutine stacks
63 * allocated by this module
65 #define COROUTINE_STACK_MAGIC_ALLOC 0xc040c040574ca110
68 * coroutine_stack_init - Prepare a coroutine stack in an existing buffer
69 * @buf: buffer to use for the coroutine stack
70 * @bufsize: size of @buf
71 * @metasize: size of metadata to add to the stack (not including
72 * coroutine internal overhead)
74 * Prepares @buf for use as a coroutine stack, returning a
75 * coroutine_stack *, allocated from within the buffer. Returns NULL
78 * This will fail if the bufsize < (COROUTINE_MIN_STKSZ +
79 * COROUTINE_STK_OVERHEAD + metasize).
81 struct coroutine_stack *coroutine_stack_init(void *buf, size_t bufsize,
85 * coroutine_stack_alloc - Allocate a coroutine stack
86 * @totalsize: total size to allocate
87 * @metasize: size of metadata to add to the stack (not including
88 * coroutine internal overhead)
90 * Allocates a coroutine stack of size @totalsize, including both
91 * internal overhead (COROUTINE_STK_OVERHEAD) and metadata of size
92 * @metasize. Where available this will also create a guard page, so
93 * that overruning the stack will result in an immediate crash, rather
94 * than data corruption.
96 * This will fail if the totalsize < (COROUTINE_MIN_STKSZ +
97 * COROUTINE_STK_OVERHEAD + metasize).
99 struct coroutine_stack *coroutine_stack_alloc(size_t bufsize, size_t metasize);
102 * coroutine_stack_release - Stop using a coroutine stack
103 * @stack: coroutine stack to release
104 * @metasize: size of metadata
106 * This releases @stack, making it no longer suitable for use as a
107 * coroutine stack. @metasize must be equal to the metasize passed to
108 * coroutine_stack_init.
110 void coroutine_stack_release(struct coroutine_stack *stack, size_t metasize);
113 * coroutine_stack_check - Validate and return a coroutine stack
114 * @stack: stack to check
115 * @abortstr: the location to print on aborting, or NULL.
117 * Debugging check if @stack doesn't appear to be a valid coroutine
118 * stack, and @abortstr is non-NULL it will be printed and the
119 * function will abort.
121 * Returns @stack if it appears valid, NULL if not (it can never
122 * return NULL if @abortstr is set).
124 struct coroutine_stack *coroutine_stack_check(struct coroutine_stack *stack,
125 const char *abortstr);
128 * coroutine_stack_to_metadata - Returns pointer to user's metadata
129 * allocated within the stack
130 * @stack: coroutine stack
131 * @metasize: size of metadata
133 * Returns a pointer to the metadata area within @stack. This is of
134 * size given at initialization time, and won't be overwritten by
135 * coroutines executing on the stack. It's up to the caller what to
136 * put in here. @metasize must be equal to the value passed to
137 * coroutine_stack_init().
139 static inline void *coroutine_stack_to_metadata(struct coroutine_stack *stack,
142 #if HAVE_STACK_GROWS_UPWARDS
143 return (char *)stack - metasize;
145 return (char *)stack + COROUTINE_STK_OVERHEAD;
150 * coroutine_stack_from_metadata - Returns pointer to coroutine stack
151 * pointer given pointer to user metadata
152 * @metadat: user metadata within a stack
153 * @metasize: size of metadata
155 * Returns a pointer to the coroutine_stack handle within a stack.
156 * The argument must be a pointer returned by
157 * coroutine_stack_to_metadata() at an earlier time. @metasize must be
158 * equal to the value passed to coroutine_stack_init().
160 static inline struct coroutine_stack *
161 coroutine_stack_from_metadata(void *metadata, size_t metasize)
163 #if HAVE_STACK_GROWS_UPWARDS
164 return (struct coroutine_stack *)((char *)metadata + metasize);
166 return (struct coroutine_stack *)((char *)metadata
167 - COROUTINE_STK_OVERHEAD);
172 * coroutine_stack_size - Return size of a coroutine stack
173 * @stack: coroutine stack
175 * Returns the size of the coroutine stack @stack. This does not
176 * include the overhead of struct coroutine_stack or metdata.
178 size_t coroutine_stack_size(const struct coroutine_stack *stack);
181 * Coroutine switching
185 #include <ucontext.h>
186 #define COROUTINE_AVAILABLE 1
188 #define COROUTINE_AVAILABLE 0
191 struct coroutine_state {
194 #endif /* HAVE_UCONTEXT */
197 #if COROUTINE_AVAILABLE
200 * coroutine_init - Prepare a coroutine for execution
201 * @cs: coroutine_state structure to initialize
202 * @fn: function to start executing in the coroutine
203 * @arg: argument for @fn
204 * @stack: stack to use for the coroutine
206 * Prepares @cs as a new coroutine which will execute starting with
207 * function @fn, using stack @stack.
209 void coroutine_init_(struct coroutine_state *cs,
210 void (*fn)(void *), void *arg,
211 struct coroutine_stack *stack);
212 #define coroutine_init(cs, fn, arg, stack) \
213 coroutine_init_((cs), \
214 typesafe_cb(void, void *, (fn), (arg)), \
218 * coroutine_jump - Irreversibly switch to executing a coroutine
219 * @to: coroutine to switch to
221 * Immediately jump to executing coroutine @to (at whatever point in
222 * execution it was up to). Never returns.
224 void NORETURN coroutine_jump(const struct coroutine_state *to);
227 * coroutine_switch - Switch coroutines
228 * @from: coroutine in which to store current execution state
229 * @to: coroutine to switch to
231 * Stop executing the current routine, saving its state in @from, and
232 * switch to executing the coroutine @to. Returns only when something
233 * switches or jumps back to @from.
235 void coroutine_switch(struct coroutine_state *from,
236 const struct coroutine_state *to);
240 static inline void coroutine_init(struct coroutine_state *cs,
241 void (*fn)(void *), void *arg,
242 struct coroutine_stack *stack)
247 static inline void NORETURN coroutine_jump(const struct coroutine_state *to)
252 static inline void coroutine_switch(struct coroutine_state *from,
253 const struct coroutine_state *to)
258 #endif /* !COROUTINE_AVAILABLE */
260 #endif /* CCAN_COROUTINE_H */