ARGOBOTS  66b1c39742507d8df30e8d28c54839b961a14814
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups
eventual.c
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 #include "abti.h"
7 
32 int ABT_eventual_create(int nbytes, ABT_eventual *neweventual)
33 {
34  int abt_errno;
35  ABTI_eventual *p_eventual;
36 
37  abt_errno = ABTU_malloc(sizeof(ABTI_eventual), (void **)&p_eventual);
38  ABTI_CHECK_ERROR(abt_errno);
39 
40  ABTI_spinlock_clear(&p_eventual->lock);
41  p_eventual->ready = ABT_FALSE;
42  p_eventual->nbytes = nbytes;
43  if (nbytes == 0) {
44  p_eventual->value = NULL;
45  } else {
46  abt_errno = ABTU_malloc(nbytes, &p_eventual->value);
47  if (ABTI_IS_ERROR_CHECK_ENABLED && abt_errno != ABT_SUCCESS) {
48  ABTU_free(p_eventual);
49  ABTI_HANDLE_ERROR(abt_errno);
50  }
51  }
52  p_eventual->p_head = NULL;
53  p_eventual->p_tail = NULL;
54 
55  *neweventual = ABTI_eventual_get_handle(p_eventual);
56  return ABT_SUCCESS;
57 }
58 
72 {
73  ABTI_eventual *p_eventual = ABTI_eventual_get_ptr(*eventual);
74  ABTI_CHECK_NULL_EVENTUAL_PTR(p_eventual);
75 
76  /* The lock needs to be acquired to safely free the eventual structure.
77  * However, we do not have to unlock it because the entire structure is
78  * freed here. */
79  ABTI_spinlock_acquire(&p_eventual->lock);
80 
81  if (p_eventual->value)
82  ABTU_free(p_eventual->value);
83  ABTU_free(p_eventual);
84 
85  *eventual = ABT_EVENTUAL_NULL;
86  return ABT_SUCCESS;
87 }
88 
106 int ABT_eventual_wait(ABT_eventual eventual, void **value)
107 {
108  ABTI_local *p_local = ABTI_local_get_local();
109  ABTI_eventual *p_eventual = ABTI_eventual_get_ptr(eventual);
110  ABTI_CHECK_NULL_EVENTUAL_PTR(p_eventual);
111 
112  ABTI_spinlock_acquire(&p_eventual->lock);
113  if (p_eventual->ready == ABT_FALSE) {
114  ABTI_ythread *p_ythread = NULL;
115  ABTI_thread *p_thread;
116 
117  ABTI_xstream *p_local_xstream = ABTI_local_get_xstream_or_null(p_local);
118  if (!ABTI_IS_EXT_THREAD_ENABLED || p_local_xstream) {
119  p_thread = p_local_xstream->p_thread;
120  p_ythread = ABTI_thread_get_ythread_or_null(p_thread);
121  }
122  if (!p_ythread) {
123  /* external thread or non-yieldable thread */
124  int abt_errno =
125  ABTU_calloc(1, sizeof(ABTI_thread), (void **)&p_thread);
126  if (ABTI_IS_ERROR_CHECK_ENABLED && abt_errno != ABT_SUCCESS) {
127  ABTI_spinlock_release(&p_eventual->lock);
128  ABTI_HANDLE_ERROR(abt_errno);
129  }
130  p_thread->type = ABTI_THREAD_TYPE_EXT;
131  /* use state for synchronization */
134  }
135 
136  p_thread->p_next = NULL;
137  if (p_eventual->p_head == NULL) {
138  p_eventual->p_head = p_thread;
139  p_eventual->p_tail = p_thread;
140  } else {
141  p_eventual->p_tail->p_next = p_thread;
142  p_eventual->p_tail = p_thread;
143  }
144 
145  if (p_ythread) {
146  ABTI_ythread_set_blocked(p_ythread);
147 
148  ABTI_spinlock_release(&p_eventual->lock);
149 
150  /* Suspend the current ULT */
151  ABTI_ythread_suspend(&p_local_xstream, p_ythread,
153  (void *)p_eventual);
154  } else {
155  ABTI_spinlock_release(&p_eventual->lock);
156 
157  /* External thread is waiting here. */
158  while (ABTD_atomic_acquire_load_int(&p_thread->state) !=
160  ;
161  if (p_thread->type == ABTI_THREAD_TYPE_EXT)
162  ABTU_free(p_thread);
163  }
164  } else {
165  ABTI_spinlock_release(&p_eventual->lock);
166  }
167  if (value)
168  *value = p_eventual->value;
169  return ABT_SUCCESS;
170 }
171 
187 int ABT_eventual_test(ABT_eventual eventual, void **value, int *is_ready)
188 {
189  ABTI_eventual *p_eventual = ABTI_eventual_get_ptr(eventual);
190  ABTI_CHECK_NULL_EVENTUAL_PTR(p_eventual);
191  int flag = ABT_FALSE;
192 
193  ABTI_spinlock_acquire(&p_eventual->lock);
194  if (p_eventual->ready != ABT_FALSE) {
195  if (value)
196  *value = p_eventual->value;
197  flag = ABT_TRUE;
198  }
199  ABTI_spinlock_release(&p_eventual->lock);
200 
201  *is_ready = flag;
202  return ABT_SUCCESS;
203 }
204 
222 int ABT_eventual_set(ABT_eventual eventual, void *value, int nbytes)
223 {
224  ABTI_local *p_local = ABTI_local_get_local();
225  ABTI_eventual *p_eventual = ABTI_eventual_get_ptr(eventual);
226  ABTI_CHECK_NULL_EVENTUAL_PTR(p_eventual);
227  ABTI_CHECK_TRUE(nbytes <= p_eventual->nbytes, ABT_ERR_INV_EVENTUAL);
228 
229  ABTI_spinlock_acquire(&p_eventual->lock);
230 
231  p_eventual->ready = ABT_TRUE;
232  if (p_eventual->value)
233  memcpy(p_eventual->value, value, nbytes);
234 
235  if (p_eventual->p_head == NULL) {
236  ABTI_spinlock_release(&p_eventual->lock);
237  return ABT_SUCCESS;
238  }
239 
240  /* Wake up all waiting ULTs */
241  ABTI_thread *p_head = p_eventual->p_head;
242  ABTI_thread *p_thread = p_head;
243  while (1) {
244  ABTI_thread *p_next = p_thread->p_next;
245  p_thread->p_next = NULL;
246 
247  ABTI_ythread *p_ythread = ABTI_thread_get_ythread_or_null(p_thread);
248  if (p_ythread) {
249  ABTI_ythread_set_ready(p_local, p_ythread);
250  } else {
251  /* When the head is an external thread */
254  }
255 
256  /* Next ULT */
257  if (p_next != NULL) {
258  p_thread = p_next;
259  } else {
260  break;
261  }
262  }
263 
264  p_eventual->p_head = NULL;
265  p_eventual->p_tail = NULL;
266 
267  ABTI_spinlock_release(&p_eventual->lock);
268  return ABT_SUCCESS;
269 }
270 
284 {
285  ABTI_eventual *p_eventual = ABTI_eventual_get_ptr(eventual);
286  ABTI_CHECK_NULL_EVENTUAL_PTR(p_eventual);
287 
288  ABTI_spinlock_acquire(&p_eventual->lock);
289  p_eventual->ready = ABT_FALSE;
290  ABTI_spinlock_release(&p_eventual->lock);
291  return ABT_SUCCESS;
292 }
static ABTI_ythread * ABTI_thread_get_ythread_or_null(ABTI_thread *p_thread)
Definition: abti_thread.h:59
static ABTI_eventual * ABTI_eventual_get_ptr(ABT_eventual eventual)
Definition: abti_eventual.h:11
int ABT_eventual_reset(ABT_eventual eventual) ABT_API_PUBLIC
Reset the readiness of the target eventual.
Definition: eventual.c:283
ABT_bool ready
Definition: abti.h:393
struct ABTI_local ABTI_local
Definition: abti.h:101
static void ABTD_atomic_release_store_int(ABTD_atomic_int *ptr, int val)
Definition: abtd_atomic.h:924
ABTI_thread_type type
Definition: abti.h:316
ABTI_thread * p_thread
Definition: abti.h:251
#define ABT_ERR_INV_EVENTUAL
Definition: abt.h:88
static ABT_eventual ABTI_eventual_get_handle(ABTI_eventual *p_eventual)
Definition: abti_eventual.h:26
static void ABTI_spinlock_clear(ABTI_spinlock *p_lock)
Definition: abti_spinlock.h:18
static ABTU_ret_err int ABTU_malloc(size_t size, void **p_ptr)
Definition: abtu.h:142
#define ABT_FALSE
Definition: abt.h:285
#define ABTI_CHECK_TRUE(cond, abt_errno)
Definition: abti_error.h:137
#define ABT_EVENTUAL_NULL
Definition: abt.h:423
ABTD_atomic_int state
Definition: abti.h:322
#define ABTI_IS_EXT_THREAD_ENABLED
Definition: abti.h:28
static void ABTI_spinlock_release(ABTI_spinlock *p_lock)
Definition: abti_spinlock.h:31
#define ABT_SUCCESS
Definition: abt.h:64
int ABT_eventual_free(ABT_eventual *eventual) ABT_API_PUBLIC
Free the eventual object.
Definition: eventual.c:71
#define ABT_TRUE
Definition: abt.h:284
ABTI_thread * p_head
Definition: abti.h:396
#define ABTI_CHECK_NULL_EVENTUAL_PTR(p)
Definition: abti_error.h:283
struct ABT_eventual_opaque * ABT_eventual
Definition: abt.h:365
static void ABTI_spinlock_acquire(ABTI_spinlock *p_lock)
Definition: abti_spinlock.h:23
int ABT_eventual_wait(ABT_eventual eventual, void **value) ABT_API_PUBLIC
Wait on the eventual.
Definition: eventual.c:106
ABTI_thread * p_tail
Definition: abti.h:397
#define ABTI_CHECK_ERROR(abt_errno)
Definition: abti_error.h:127
static void ABTD_atomic_relaxed_store_int(ABTD_atomic_int *ptr, int val)
Definition: abtd_atomic.h:865
ABTI_thread * p_next
Definition: abti.h:314
int ABT_eventual_test(ABT_eventual eventual, void **value, int *is_ready) ABT_API_PUBLIC
Test the readiness of an eventual.
Definition: eventual.c:187
static int ABTD_atomic_acquire_load_int(const ABTD_atomic_int *ptr)
Definition: abtd_atomic.h:763
void ABTI_ythread_set_ready(ABTI_local *p_local, ABTI_ythread *p_ythread)
Definition: ythread.c:50
ABTI_spinlock lock
Definition: abti.h:392
void ABTI_ythread_set_blocked(ABTI_ythread *p_ythread)
Definition: ythread.c:8
int nbytes
Definition: abti.h:395
static ABTI_local * ABTI_local_get_local(void)
Definition: abti_local.h:41
#define ABTI_IS_ERROR_CHECK_ENABLED
Definition: abti.h:20
static ABTU_ret_err int ABTU_calloc(size_t num, size_t size, void **p_ptr)
Definition: abtu.h:152
static void ABTU_free(void *ptr)
Definition: abtu.h:135
int ABT_eventual_create(int nbytes, ABT_eventual *neweventual) ABT_API_PUBLIC
Create an eventual.
Definition: eventual.c:32
#define ABTI_THREAD_TYPE_EXT
Definition: abti.h:72
void * value
Definition: abti.h:394
void ABTI_ythread_suspend(ABTI_xstream **pp_local_xstream, ABTI_ythread *p_ythread, ABT_sync_event_type sync_event_type, void *p_sync)
Definition: ythread.c:30
static ABTI_xstream * ABTI_local_get_xstream_or_null(ABTI_local *p_local)
Definition: abti_local.h:77
int ABT_eventual_set(ABT_eventual eventual, void *value, int nbytes) ABT_API_PUBLIC
Signal the eventual.
Definition: eventual.c:222
#define ABTI_HANDLE_ERROR(n)
Definition: abti_error.h:121