ARGOBOTS  1.1
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 entity pointed by p_ctx */
14  void (*f_uctx_thread)(void *); /* root function called by ucontext */
15  void *p_uctx_arg; /* argument for root function */
16 #ifdef ABT_CONFIG_ENABLE_PEEK_CONTEXT
17  void (*peek_func)(void *);
18  void *peek_arg;
19  ucontext_t *p_peek_uctx;
20  ABT_bool is_peeked;
21 #endif
22 };
23 
24 #ifdef ABT_CONFIG_ENABLE_PEEK_CONTEXT
25 static inline void ABTDI_ucontext_check_peeked(ABTD_ythread_context *p_self)
26 {
27  /* Check if this thread is called only for peeked */
28  while (ABTU_unlikely(p_self->is_peeked)) {
29  p_self->peek_func(p_self->peek_arg);
30  /* Reset the flag. */
31  p_self->is_peeked = ABT_FALSE;
32  int ret = swapcontext(&p_self->uctx, p_self->p_peek_uctx);
33  ABTI_ASSERT(ret == 0); /* Fatal. */
34  }
35 }
36 #endif
37 
38 static void ABTD_ucontext_wrapper(int arg1, int arg2)
39 {
40  ABTD_ythread_context *p_self;
41 #if SIZEOF_VOID_P == 8
42  p_self = (ABTD_ythread_context *)(((uintptr_t)((uint32_t)arg1) << 32) |
43  ((uintptr_t)((uint32_t)arg2)));
44 #elif SIZEOF_VOID_P == 4
45  p_self = (ABTD_ythread_context *)((uintptr_t)arg1);
46 #else
47 #error "Unknown pointer size."
48 #endif
49 
50 #ifdef ABT_CONFIG_ENABLE_PEEK_CONTEXT
51  ABTDI_ucontext_check_peeked(p_self);
52 #endif
53 
54  p_self->f_uctx_thread(p_self->p_uctx_arg);
55  /* ABTD_ythread_context_jump or take must be called at the end of
56  * f_uctx_thread, */
57  ABTI_ASSERT(0);
59 }
60 
62  void *sp, size_t size,
63  void (*thread_func)(void *))
64 {
65  int ret = getcontext(&p_ctx->uctx);
66  ABTI_ASSERT(ret == 0); /* getcontext() should not return an error. */
67  p_ctx->p_ctx = &p_ctx->uctx;
68 
69  /* uc_link is not used. */
70  p_ctx->uctx.uc_link = NULL;
71  p_ctx->uctx.uc_stack.ss_sp = (void *)(((char *)sp) - size);
72  p_ctx->uctx.uc_stack.ss_size = size;
73  p_ctx->f_uctx_thread = thread_func;
74 
75 #if SIZEOF_VOID_P == 8
76  int arg_upper = (int)(((uintptr_t)p_ctx) >> 32);
77  int arg_lower = (int)(((uintptr_t)p_ctx) >> 0);
78  makecontext(&p_ctx->uctx, (void (*)())ABTD_ucontext_wrapper, 2, arg_upper,
79  arg_lower);
80 #elif SIZEOF_VOID_P == 4
81  int arg = (int)((uintptr_t)p_ctx);
82  makecontext(&p_ctx->uctx, (void (*)())ABTD_ucontext_wrapper, 1, arg);
83 #else
84 #error "Unknown pointer size."
85 #endif
86 #ifdef ABT_CONFIG_ENABLE_PEEK_CONTEXT
87  p_ctx->is_peeked = ABT_FALSE;
88 #endif
89 }
90 
92  ABTD_ythread_context *p_new,
93  void *arg)
94 {
95 #ifdef ABT_CONFIG_ENABLE_PEEK_CONTEXT
96  p_old->is_peeked = ABT_FALSE;
97 #endif
98  p_new->p_uctx_arg = arg;
99  int ret = swapcontext(&p_old->uctx, &p_new->uctx);
100  /* Fatal. This out-of-stack error is not recoverable. */
101  ABTI_ASSERT(ret == 0);
102 #ifdef ABT_CONFIG_ENABLE_PEEK_CONTEXT
103  ABTDI_ucontext_check_peeked(p_old);
104 #endif
105 }
106 
107 ABTU_noreturn static inline void
109  ABTD_ythread_context *p_new, void *arg)
110 {
111  p_new->p_uctx_arg = arg;
112  int ret = setcontext(&p_new->uctx);
113  ABTI_ASSERT(ret == 0); /* setcontext() should not return an error. */
115 }
116 
117 #ifdef ABT_CONFIG_ENABLE_PEEK_CONTEXT
118 static inline void ABTD_ythread_context_peek(ABTD_ythread_context *p_ctx,
119  void (*peek_func)(void *),
120  void *arg)
121 {
122  ucontext_t self_uctx;
123  p_ctx->peek_arg = arg;
124  p_ctx->peek_func = peek_func;
125  p_ctx->p_peek_uctx = &self_uctx;
126  p_ctx->is_peeked = ABT_TRUE;
127  int ret = swapcontext(&self_uctx, &p_ctx->uctx);
128  ABTI_ASSERT(ret == 0);
129 }
130 #endif
131 
132 #if ABT_CONFIG_THREAD_TYPE == ABT_THREAD_TYPE_DYNAMIC_PROMOTION
133 #error "ABTD_ythread_context_make_and_call is not implemented."
134 #endif
135 
136 #endif /* ABTD_UCONTEXT_H_INCLUDED */
ABT_bool
int ABT_bool
Boolean type.
Definition: abt.h:1001
ABTD_ythread_context_take
static ABTU_noreturn void ABTD_ythread_context_take(ABTD_ythread_context *p_old, ABTD_ythread_context *p_new, void *arg)
Definition: abtd_ucontext.h:108
ABTU_noreturn
#define ABTU_noreturn
Definition: abtu.h:118
ABTD_ythread_context::p_link
ABTD_ythread_context_atomic_ptr p_link
Definition: abtd_fcontext.h:36
ABTD_ythread_context
Definition: abtd_fcontext.h:33
ABTD_ythread_context::p_uctx_arg
void * p_uctx_arg
Definition: abtd_ucontext.h:15
ABTI_ASSERT
#define ABTI_ASSERT(cond)
Definition: abti_error.h:12
ABTD_ythread_context_make
static void ABTD_ythread_context_make(ABTD_ythread_context *p_ctx, void *sp, size_t size, void(*thread_func)(void *))
Definition: abtd_ucontext.h:61
ABTD_ythread_context::p_ctx
void * p_ctx
Definition: abtd_fcontext.h:34
ABTD_ythread_context_atomic_ptr
Definition: abtd_context.h:25
ABTD_ythread_context::uctx
ucontext_t uctx
Definition: abtd_ucontext.h:13
ABTU_unlikely
#define ABTU_unlikely(cond)
Definition: abtu.h:112
ABT_TRUE
#define ABT_TRUE
True constant for ABT_bool.
Definition: abt.h:748
ABT_FALSE
#define ABT_FALSE
False constant for ABT_bool.
Definition: abt.h:750
ABTD_ucontext_wrapper
static void ABTD_ucontext_wrapper(int arg1, int arg2)
Definition: abtd_ucontext.h:38
ABTU_unreachable
static ABTU_noreturn void ABTU_unreachable(void)
Definition: abtu.h:126
ABTD_ythread_context_jump
static void ABTD_ythread_context_jump(ABTD_ythread_context *p_old, ABTD_ythread_context *p_new, void *arg)
Definition: abtd_ucontext.h:91
ABTD_ythread_context::f_uctx_thread
void(* f_uctx_thread)(void *)
Definition: abtd_ucontext.h:14