6 #ifndef ABTD_UCONTEXT_H_INCLUDED
7 #define ABTD_UCONTEXT_H_INCLUDED
9 struct ABTD_ythread_context {
12 ABTD_ythread_context_atomic_ptr p_link;
20 void (*peek_func)(
void *);
22 ucontext_t *p_peek_uctx;
30 p_self->peek_func(p_self->peek_arg);
33 int ret = swapcontext(&p_self->uctx, p_self->p_peek_uctx);
34 ABTI_ASSERT(ret == 0);
36 p_self->f_cb(p_self->cb_arg);
42 static void ABTD_ucontext_wrapper(
int arg1,
int arg2)
44 ABTD_ythread_context *p_self;
45 #if SIZEOF_VOID_P == 8
46 p_self = (ABTD_ythread_context *)(((uintptr_t)((uint32_t)arg1) << 32) |
47 ((uintptr_t)((uint32_t)arg2)));
48 #elif SIZEOF_VOID_P == 4
49 p_self = (ABTD_ythread_context *)((uintptr_t)arg1);
51 #error "Unknown pointer size."
55 p_self->f_cb(p_self->cb_arg);
59 ABTD_ythread_func_wrapper(p_self);
63 static inline void ABTD_ythread_context_init(ABTD_ythread_context *p_ctx,
64 void *p_stacktop,
size_t stacksize)
67 p_ctx->p_stacktop = p_stacktop;
68 p_ctx->stacksize = stacksize;
69 int ret = getcontext(&p_ctx->uctx);
70 ABTI_ASSERT(ret == 0);
71 ABTD_atomic_relaxed_store_ythread_context_ptr(&p_ctx->p_link, NULL);
74 static inline void ABTD_ythread_context_init_lazy(ABTD_ythread_context *p_ctx,
77 ABTD_ythread_context_init(p_ctx, NULL, stacksize);
81 ABTD_ythread_context_lazy_set_stack(ABTD_ythread_context *p_ctx,
84 p_ctx->p_stacktop = p_stacktop;
88 ABTD_ythread_context_lazy_unset_stack(ABTD_ythread_context *p_ctx)
90 p_ctx->p_stacktop = NULL;
93 static inline void ABTD_ythread_context_reinit(ABTD_ythread_context *p_ctx)
96 int ret = getcontext(&p_ctx->uctx);
97 ABTI_ASSERT(ret == 0);
98 ABTD_atomic_relaxed_store_ythread_context_ptr(&p_ctx->p_link, NULL);
102 ABTD_ythread_context_get_stacktop(ABTD_ythread_context *p_ctx)
104 return p_ctx->p_stacktop;
108 ABTD_ythread_context_has_stack(
const ABTD_ythread_context *p_ctx)
114 ABTD_ythread_context_get_stacksize(ABTD_ythread_context *p_ctx)
116 return p_ctx->stacksize;
121 p_ctx->p_ctx = &p_ctx->uctx;
123 p_ctx->uctx.uc_link = NULL;
124 void *p_stack = (
void *)(((
char *)p_ctx->p_stacktop) - p_ctx->stacksize);
125 p_ctx->uctx.uc_stack.ss_sp = p_stack;
126 p_ctx->uctx.uc_stack.ss_size = p_ctx->stacksize;
128 #if SIZEOF_VOID_P == 8
129 int arg_upper = (int)(((uintptr_t)p_ctx) >> 32);
130 int arg_lower = (int)(((uintptr_t)p_ctx) >> 0);
131 makecontext(&p_ctx->uctx, (void (*)())ABTD_ucontext_wrapper, 2, arg_upper,
133 #elif SIZEOF_VOID_P == 4
134 int arg = (int)((uintptr_t)p_ctx);
135 makecontext(&p_ctx->uctx, (void (*)())ABTD_ucontext_wrapper, 1, arg);
137 #error "Unknown pointer size."
143 ABTD_ythread_context_is_started(
const ABTD_ythread_context *p_ctx)
148 static inline void ABTD_ythread_context_switch(ABTD_ythread_context *p_old,
149 ABTD_ythread_context *p_new)
151 ABTI_UB_ASSERT(ABTD_ythread_context_is_started(p_new));
153 p_old->p_ctx = &p_old->uctx;
155 int ret = swapcontext(&p_old->uctx, &p_new->uctx);
157 ABTI_ASSERT(ret == 0);
159 p_old->f_cb(p_old->cb_arg);
166 ABTD_ythread_context_start_and_switch(ABTD_ythread_context *p_old,
167 ABTD_ythread_context *p_new)
169 ABTI_UB_ASSERT(!ABTD_ythread_context_is_started(p_new));
171 ABTD_ythread_context_switch(p_old, p_new);
175 ABTD_ythread_context_jump(ABTD_ythread_context *p_new)
177 ABTI_UB_ASSERT(ABTD_ythread_context_is_started(p_new));
178 int ret = setcontext(&p_new->uctx);
179 ABTI_ASSERT(ret == 0);
184 ABTD_ythread_context_start_and_jump(ABTD_ythread_context *p_new)
186 ABTI_UB_ASSERT(!ABTD_ythread_context_is_started(p_new));
188 ABTD_ythread_context_jump(p_new);
193 ABTD_ythread_context_switch_with_call(ABTD_ythread_context *p_old,
194 ABTD_ythread_context *p_new,
195 void (*f_cb)(
void *),
void *cb_arg)
197 ABTI_UB_ASSERT(ABTD_ythread_context_is_started(p_new));
199 p_old->p_ctx = &p_old->uctx;
201 p_new->cb_arg = cb_arg;
202 int ret = swapcontext(&p_old->uctx, &p_new->uctx);
204 ABTI_ASSERT(ret == 0);
206 p_old->f_cb(p_old->cb_arg);
212 static inline void ABTD_ythread_context_start_and_switch_with_call(
213 ABTD_ythread_context *p_old, ABTD_ythread_context *p_new,
214 void (*f_cb)(
void *),
void *cb_arg)
216 ABTI_UB_ASSERT(!ABTD_ythread_context_is_started(p_new));
218 ABTD_ythread_context_switch_with_call(p_old, p_new, f_cb, cb_arg);
222 ABTD_ythread_context_jump_with_call(ABTD_ythread_context *p_new,
223 void (*f_cb)(
void *),
void *cb_arg)
225 ABTI_UB_ASSERT(ABTD_ythread_context_is_started(p_new));
227 p_new->cb_arg = cb_arg;
228 int ret = setcontext(&p_new->uctx);
229 ABTI_ASSERT(ret == 0);
233 ABTU_noreturn static inline void ABTD_ythread_context_start_and_jump_with_call(
234 ABTD_ythread_context *p_new,
void (*f_cb)(
void *),
void *cb_arg)
236 ABTI_UB_ASSERT(!ABTD_ythread_context_is_started(p_new));
238 ABTD_ythread_context_jump_with_call(p_new, f_cb, cb_arg);
242 static inline ABT_bool ABTD_ythread_context_peek(ABTD_ythread_context *p_ctx,
243 void (*peek_func)(
void *),
247 ucontext_t self_uctx;
248 p_ctx->peek_arg = arg;
249 p_ctx->peek_func = peek_func;
250 p_ctx->p_peek_uctx = &self_uctx;
252 int ret = swapcontext(&self_uctx, &p_ctx->uctx);
254 p_ctx->f_cb(p_ctx->cb_arg);
257 ABTI_ASSERT(ret == 0);