ARGOBOTS  dce6e727ffc4ca5b3ffc04cb9517c6689be51ec5
abtd_ucontext.h
Go to the documentation of this file.
1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
2 /*
3  * See COPYRIGHT in top-level directory.
4  */
5 
6 #ifndef ABTD_UCONTEXT_H_INCLUDED
7 #define ABTD_UCONTEXT_H_INCLUDED
8 
10  void *p_ctx; /* actual context of fcontext, or a
11  * pointer to uctx */
12  ABTD_ythread_context_atomic_ptr p_link; /* pointer to scheduler context */
13  ucontext_t uctx; /* ucontext pointed by p_ctx */
14  void *p_stacktop; /* Stack pointer (top). */
15  size_t stacksize; /* Stack size. */
16  /* Call-back functions. */
17  void (*f_cb)(void *);
18  void *cb_arg;
19  /* Peek functions. */
20  void (*peek_func)(void *);
21  void *peek_arg;
22  ucontext_t *p_peek_uctx;
24 };
25 
27 {
28  /* Check if this thread is called only for peeked */
29  while (ABTU_unlikely(p_self->is_peeked)) {
30  p_self->peek_func(p_self->peek_arg);
31  /* Reset the flag. */
32  p_self->is_peeked = ABT_FALSE;
33  int ret = swapcontext(&p_self->uctx, p_self->p_peek_uctx);
34  ABTI_ASSERT(ret == 0); /* Fatal. */
35  if (p_self->f_cb) {
36  p_self->f_cb(p_self->cb_arg);
37  p_self->f_cb = NULL;
38  }
39  }
40 }
41 
42 static void ABTD_ucontext_wrapper(int arg1, int arg2)
43 {
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);
50 #else
51 #error "Unknown pointer size."
52 #endif
53 
54  if (p_self->f_cb) {
55  p_self->f_cb(p_self->cb_arg);
56  p_self->f_cb = NULL;
57  }
61 }
62 
64  void *p_stacktop, size_t stacksize)
65 {
66  p_ctx->p_ctx = NULL;
67  p_ctx->p_stacktop = p_stacktop;
68  p_ctx->stacksize = stacksize;
69  int ret = getcontext(&p_ctx->uctx);
70  ABTI_ASSERT(ret == 0); /* getcontext() should not return an error. */
72 }
73 
75  size_t stacksize)
76 {
77  ABTD_ythread_context_init(p_ctx, NULL, stacksize);
78 }
79 
80 static inline void
82  void *p_stacktop)
83 {
84  p_ctx->p_stacktop = p_stacktop;
85 }
86 
87 static inline void
89 {
90  p_ctx->p_stacktop = NULL;
91 }
92 
94 {
95  p_ctx->p_ctx = NULL;
96  int ret = getcontext(&p_ctx->uctx);
97  ABTI_ASSERT(ret == 0); /* getcontext() should not return an error. */
99 }
100 
101 static inline void *
103 {
104  return p_ctx->p_stacktop;
105 }
106 
107 static inline ABT_bool
109 {
110  return p_ctx->p_stacktop ? ABT_TRUE : ABT_FALSE;
111 }
112 
113 static inline size_t
115 {
116  return p_ctx->stacksize;
117 }
118 
120 {
121  p_ctx->p_ctx = &p_ctx->uctx;
122  /* uc_link is not used. */
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;
127 
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,
132  arg_lower);
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);
136 #else
137 #error "Unknown pointer size."
138 #endif
139  p_ctx->is_peeked = ABT_FALSE;
140 }
141 
142 static inline ABT_bool
144 {
145  return p_ctx->p_ctx ? ABT_TRUE : ABT_FALSE;
146 }
147 
149  ABTD_ythread_context *p_new)
150 {
152  p_old->is_peeked = ABT_FALSE;
153  p_old->p_ctx = &p_old->uctx;
154  p_new->f_cb = NULL;
155  int ret = swapcontext(&p_old->uctx, &p_new->uctx);
156  /* Fatal. This out-of-stack error is not recoverable. */
157  ABTI_ASSERT(ret == 0);
158  if (p_old->f_cb) {
159  p_old->f_cb(p_old->cb_arg);
160  p_old->f_cb = NULL;
161  }
163 }
164 
165 static inline void
167  ABTD_ythread_context *p_new)
168 {
171  ABTD_ythread_context_switch(p_old, p_new);
172 }
173 
174 ABTU_noreturn static inline void
176 {
178  int ret = setcontext(&p_new->uctx);
179  ABTI_ASSERT(ret == 0); /* setcontext() should not return an error. */
181 }
182 
183 ABTU_noreturn static inline void
185 {
190 }
191 
192 static inline void
194  ABTD_ythread_context *p_new,
195  void (*f_cb)(void *), void *cb_arg)
196 {
198  p_old->is_peeked = ABT_FALSE;
199  p_old->p_ctx = &p_old->uctx;
200  p_new->f_cb = f_cb;
201  p_new->cb_arg = cb_arg;
202  int ret = swapcontext(&p_old->uctx, &p_new->uctx);
203  /* Fatal. This out-of-stack error is not recoverable. */
204  ABTI_ASSERT(ret == 0);
205  if (p_old->f_cb) {
206  p_old->f_cb(p_old->cb_arg);
207  p_old->f_cb = NULL;
208  }
210 }
211 
214  void (*f_cb)(void *), void *cb_arg)
215 {
218  ABTD_ythread_context_switch_with_call(p_old, p_new, f_cb, cb_arg);
219 }
220 
221 ABTU_noreturn static inline void
223  void (*f_cb)(void *), void *cb_arg)
224 {
226  p_new->f_cb = f_cb;
227  p_new->cb_arg = cb_arg;
228  int ret = setcontext(&p_new->uctx);
229  ABTI_ASSERT(ret == 0); /* setcontext() should not return an error. */
231 }
232 
234  ABTD_ythread_context *p_new, void (*f_cb)(void *), void *cb_arg)
235 {
238  ABTD_ythread_context_jump_with_call(p_new, f_cb, cb_arg);
240 }
241 
243  void (*peek_func)(void *),
244  void *arg)
245 {
246  if (p_ctx->p_ctx) {
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;
251  p_ctx->is_peeked = ABT_TRUE;
252  int ret = swapcontext(&self_uctx, &p_ctx->uctx);
253  if (p_ctx->f_cb) {
254  p_ctx->f_cb(p_ctx->cb_arg);
255  p_ctx->f_cb = NULL;
256  }
257  ABTI_ASSERT(ret == 0);
258  return ABT_TRUE;
259  } else {
260  return ABT_FALSE;
261  }
262 }
263 
264 #endif /* ABTD_UCONTEXT_H_INCLUDED */
ABTD_ythread_context::p_ctx
void * p_ctx
Definition: abtd_ucontext.h:10
ABT_bool
int ABT_bool
Boolean type.
Definition: abt.h:1043
ABTD_ythread_context::stacksize
size_t stacksize
Definition: abtd_fcontext.h:59
ABTD_ythread_context_start_and_jump
static ABTU_noreturn void ABTD_ythread_context_start_and_jump(ABTD_ythread_context *p_new)
Definition: abtd_ucontext.h:184
ABTD_ythread_context_jump
static ABTU_noreturn void ABTD_ythread_context_jump(ABTD_ythread_context *p_new)
Definition: abtd_ucontext.h:175
ABTD_ythread_context_start_and_jump_with_call
static ABTU_noreturn void ABTD_ythread_context_start_and_jump_with_call(ABTD_ythread_context *p_new, void(*f_cb)(void *), void *cb_arg)
Definition: abtd_ucontext.h:233
ABTD_ythread_context_get_stacktop
static void * ABTD_ythread_context_get_stacktop(ABTD_ythread_context *p_ctx)
Definition: abtd_ucontext.h:102
ABTD_ythread_context_start_and_switch
static void ABTD_ythread_context_start_and_switch(ABTD_ythread_context *p_old, ABTD_ythread_context *p_new)
Definition: abtd_ucontext.h:166
ABTD_atomic_relaxed_store_ythread_context_ptr
static void ABTD_atomic_relaxed_store_ythread_context_ptr(ABTD_ythread_context_atomic_ptr *ptr, ABTD_ythread_context *p_ctx)
Definition: abtd_context.h:38
ABTU_noreturn
#define ABTU_noreturn
Definition: abtu.h:127
ABTD_ythread_context::peek_func
void(* peek_func)(void *)
Definition: abtd_ucontext.h:20
ABTD_ythread_context::p_link
ABTD_ythread_context_atomic_ptr p_link
Definition: abtd_fcontext.h:61
ABTD_ythread_context
Definition: abtd_fcontext.h:56
ABTU_unreachable
#define ABTU_unreachable()
Definition: abtu.h:133
ABTD_ythread_context_is_started
static ABT_bool ABTD_ythread_context_is_started(const ABTD_ythread_context *p_ctx)
Definition: abtd_ucontext.h:143
ABTD_ythread_context_lazy_unset_stack
static void ABTD_ythread_context_lazy_unset_stack(ABTD_ythread_context *p_ctx)
Definition: abtd_ucontext.h:88
ABTD_ythread_context::is_peeked
ABT_bool is_peeked
Definition: abtd_ucontext.h:23
ABTD_ythread_context_start_and_switch_with_call
static void ABTD_ythread_context_start_and_switch_with_call(ABTD_ythread_context *p_old, ABTD_ythread_context *p_new, void(*f_cb)(void *), void *cb_arg)
Definition: abtd_ucontext.h:212
ABTD_ythread_context_switch_with_call
static void ABTD_ythread_context_switch_with_call(ABTD_ythread_context *p_old, ABTD_ythread_context *p_new, void(*f_cb)(void *), void *cb_arg)
Definition: abtd_ucontext.h:193
ABTD_ythread_context::p_peek_uctx
ucontext_t * p_peek_uctx
Definition: abtd_ucontext.h:22
ABTD_ythread_context_reinit
static void ABTD_ythread_context_reinit(ABTD_ythread_context *p_ctx)
Definition: abtd_ucontext.h:93
ABTD_ythread_context_lazy_set_stack
static void ABTD_ythread_context_lazy_set_stack(ABTD_ythread_context *p_ctx, void *p_stacktop)
Definition: abtd_ucontext.h:81
ABTI_ASSERT
#define ABTI_ASSERT(cond)
Definition: abti_error.h:12
ABTDI_ythread_context_make
static void ABTDI_ythread_context_make(ABTD_ythread_context *p_ctx)
Definition: abtd_ucontext.h:119
ABTD_ythread_context::f_cb
void(* f_cb)(void *)
Definition: abtd_ucontext.h:17
ABTD_ythread_context::peek_arg
void * peek_arg
Definition: abtd_ucontext.h:21
ABTD_ythread_context_atomic_ptr
Definition: abtd_context.h:20
ABTD_ythread_context::uctx
ucontext_t uctx
Definition: abtd_ucontext.h:13
ABTD_ythread_context_switch
static void ABTD_ythread_context_switch(ABTD_ythread_context *p_old, ABTD_ythread_context *p_new)
Definition: abtd_ucontext.h:148
ABTD_ythread_context::p_stacktop
void * p_stacktop
Definition: abtd_fcontext.h:58
ABTD_ythread_context_jump_with_call
static ABTU_noreturn void ABTD_ythread_context_jump_with_call(ABTD_ythread_context *p_new, void(*f_cb)(void *), void *cb_arg)
Definition: abtd_ucontext.h:222
ABTU_unlikely
#define ABTU_unlikely(cond)
Definition: abtu.h:120
ABT_TRUE
#define ABT_TRUE
True constant for ABT_bool.
Definition: abt.h:784
ABT_FALSE
#define ABT_FALSE
False constant for ABT_bool.
Definition: abt.h:786
ABTI_UB_ASSERT
#define ABTI_UB_ASSERT(cond)
Definition: abti_error.h:19
ABTD_ythread_context_init_lazy
static void ABTD_ythread_context_init_lazy(ABTD_ythread_context *p_ctx, size_t stacksize)
Definition: abtd_ucontext.h:74
ABTD_ythread_context_init
static void ABTD_ythread_context_init(ABTD_ythread_context *p_ctx, void *p_stacktop, size_t stacksize)
Definition: abtd_ucontext.h:63
ABTDI_ucontext_check_peeked
static void ABTDI_ucontext_check_peeked(ABTD_ythread_context *p_self)
Definition: abtd_ucontext.h:26
ABTD_ythread_context_get_stacksize
static size_t ABTD_ythread_context_get_stacksize(ABTD_ythread_context *p_ctx)
Definition: abtd_ucontext.h:114
ABTD_ythread_func_wrapper
void ABTD_ythread_func_wrapper(ABTD_ythread_context *p_arg)
Definition: abtd_ythread.c:8
ABTD_ucontext_wrapper
static void ABTD_ucontext_wrapper(int arg1, int arg2)
Definition: abtd_ucontext.h:42
ABTD_ythread_context_peek
static ABT_bool ABTD_ythread_context_peek(ABTD_ythread_context *p_ctx, void(*peek_func)(void *), void *arg)
Definition: abtd_ucontext.h:242
ABTD_ythread_context::cb_arg
void * cb_arg
Definition: abtd_ucontext.h:18
ABTD_ythread_context_has_stack
static ABT_bool ABTD_ythread_context_has_stack(const ABTD_ythread_context *p_ctx)
Definition: abtd_ucontext.h:108