ARGOBOTS  36a41b57298ad4e16b5ada8c95c81f00dfed4d3c
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 
42 int ABT_eventual_create(int nbytes, ABT_eventual *neweventual)
43 {
44  ABTI_UB_ASSERT(ABTI_initialized());
45  ABTI_UB_ASSERT(neweventual);
46 
47  /* Check if the size of ABT_eventual_memory is okay. */
48  ABTI_STATIC_ASSERT(sizeof(ABTI_eventual) <= sizeof(ABT_eventual_memory));
49 
50  int abt_errno;
51  ABTI_eventual *p_eventual;
52  ABTI_CHECK_TRUE(nbytes >= 0, ABT_ERR_INV_ARG);
53  size_t arg_nbytes = nbytes;
54 
55  abt_errno = ABTU_malloc(sizeof(ABTI_eventual), (void **)&p_eventual);
56  ABTI_CHECK_ERROR(abt_errno);
57 
58  ABTD_spinlock_clear(&p_eventual->lock);
59  p_eventual->ready = ABT_FALSE;
60  p_eventual->nbytes = arg_nbytes;
61  if (arg_nbytes == 0) {
62  p_eventual->value = NULL;
63  } else {
64  abt_errno = ABTU_malloc(arg_nbytes, &p_eventual->value);
65  if (ABTI_IS_ERROR_CHECK_ENABLED && abt_errno != ABT_SUCCESS) {
66  ABTU_free(p_eventual);
67  ABTI_HANDLE_ERROR(abt_errno);
68  }
69  }
70  ABTI_waitlist_init(&p_eventual->waitlist);
71 
72  *neweventual = ABTI_eventual_get_handle(p_eventual);
73  return ABT_SUCCESS;
74 }
75 
103 {
104  ABTI_UB_ASSERT(ABTI_initialized());
105  ABTI_UB_ASSERT(eventual);
106 
107  ABTI_eventual *p_eventual = ABTI_eventual_get_ptr(*eventual);
108  ABTI_CHECK_NULL_EVENTUAL_PTR(p_eventual);
109 
110  /* The lock needs to be acquired to safely free the eventual structure.
111  * However, we do not have to unlock it because the entire structure is
112  * freed here. */
113  ABTD_spinlock_acquire(&p_eventual->lock);
114  ABTI_UB_ASSERT(ABTI_waitlist_is_empty(&p_eventual->waitlist));
115 
116  if (p_eventual->value)
117  ABTU_free(p_eventual->value);
118  ABTU_free(p_eventual);
119 
120  *eventual = ABT_EVENTUAL_NULL;
121  return ABT_SUCCESS;
122 }
123 
173 int ABT_eventual_wait(ABT_eventual eventual, void **value)
174 {
175  ABTI_UB_ASSERT(ABTI_initialized());
176 
177  ABTI_local *p_local = ABTI_local_get_local();
178  ABTI_eventual *p_eventual = ABTI_eventual_get_ptr(eventual);
179  ABTI_CHECK_NULL_EVENTUAL_PTR(p_eventual);
180 
181 #ifndef ABT_CONFIG_ENABLE_VER_20_API
182  /* This routine cannot be called by a tasklet. */
183  if (ABTI_IS_ERROR_CHECK_ENABLED && p_local) {
184  ABTI_xstream *p_local_xstream = ABTI_local_get_xstream(p_local);
185  ABTI_CHECK_TRUE(p_local_xstream->p_thread->type &
186  ABTI_THREAD_TYPE_YIELDABLE,
188  }
189 #endif
190 
191  ABTD_spinlock_acquire(&p_eventual->lock);
192  if (p_eventual->ready == ABT_FALSE) {
193  ABTI_waitlist_wait_and_unlock(&p_local, &p_eventual->waitlist,
194  &p_eventual->lock,
196  (void *)p_eventual);
197  } else {
198  ABTD_spinlock_release(&p_eventual->lock);
199  }
200  /* This value is updated outside the critical section, but it is okay since
201  * the "pointer" to the memory buffer is constant and there is no way to
202  * avoid updating this memory buffer by ABT_eventual_set() etc. */
203  if (value)
204  *value = p_eventual->value;
205  return ABT_SUCCESS;
206 }
207 
248 int ABT_eventual_test(ABT_eventual eventual, void **value, ABT_bool *is_ready)
249 {
250  ABTI_UB_ASSERT(ABTI_initialized());
251  ABTI_UB_ASSERT(is_ready);
252 
253  ABTI_eventual *p_eventual = ABTI_eventual_get_ptr(eventual);
254  ABTI_CHECK_NULL_EVENTUAL_PTR(p_eventual);
255  ABT_bool flag = ABT_FALSE;
256 
257  ABTD_spinlock_acquire(&p_eventual->lock);
258  if (p_eventual->ready != ABT_FALSE) {
259  if (value)
260  *value = p_eventual->value;
261  flag = ABT_TRUE;
262  }
263  ABTD_spinlock_release(&p_eventual->lock);
264 
265  *is_ready = flag;
266  return ABT_SUCCESS;
267 }
268 
315 int ABT_eventual_set(ABT_eventual eventual, void *value, int nbytes)
316 {
317  ABTI_UB_ASSERT(ABTI_initialized());
318  ABTI_UB_ASSERT(value || nbytes <= 0);
319 
320  ABTI_local *p_local = ABTI_local_get_local();
321  ABTI_eventual *p_eventual = ABTI_eventual_get_ptr(eventual);
322  ABTI_CHECK_NULL_EVENTUAL_PTR(p_eventual);
323  ABTI_CHECK_TRUE(nbytes >= 0, ABT_ERR_INV_ARG);
324  size_t arg_nbytes = nbytes;
325 #ifndef ABT_CONFIG_ENABLE_VER_20_API
326  /* Argobots 1.x */
327  ABTI_CHECK_TRUE(arg_nbytes <= p_eventual->nbytes, ABT_ERR_INV_EVENTUAL);
328 #else
329  /* Argobots 2.0 */
330  ABTI_CHECK_TRUE(arg_nbytes <= p_eventual->nbytes, ABT_ERR_INV_ARG);
331 #endif
332 
333  ABTD_spinlock_acquire(&p_eventual->lock);
334 
335  ABT_bool ready = p_eventual->ready;
336  if (ready == ABT_FALSE) {
337  if (p_eventual->value)
338  memcpy(p_eventual->value, value, arg_nbytes);
339  p_eventual->ready = ABT_TRUE;
340  /* Wake up all waiting ULTs */
341  ABTI_waitlist_broadcast(p_local, &p_eventual->waitlist);
342  ABTD_spinlock_release(&p_eventual->lock);
343  } else {
344  ABTD_spinlock_release(&p_eventual->lock);
345  /* It has been ready. Error. */
346  ABTI_HANDLE_ERROR(ABT_ERR_EVENTUAL);
347  }
348 
349  return ABT_SUCCESS;
350 }
351 
377 int ABT_eventual_reset(ABT_eventual eventual)
378 {
379  ABTI_UB_ASSERT(ABTI_initialized());
380 
381  ABTI_eventual *p_eventual = ABTI_eventual_get_ptr(eventual);
382  ABTI_CHECK_NULL_EVENTUAL_PTR(p_eventual);
383 
384  ABTD_spinlock_acquire(&p_eventual->lock);
385  ABTI_UB_ASSERT(ABTI_waitlist_is_empty(&p_eventual->waitlist));
386  p_eventual->ready = ABT_FALSE;
387  ABTD_spinlock_release(&p_eventual->lock);
388  return ABT_SUCCESS;
389 }
ABT_eventual_reset
int ABT_eventual_reset(ABT_eventual eventual)
Reset a readiness of an eventual.
Definition: eventual.c:379
ABT_bool
int ABT_bool
Boolean type.
Definition: abt.h:1043
ABT_eventual_memory
A struct that can be converted to ABT_eventual.
Definition: abt.h:1283
abti.h
ABTU_malloc
static ABTU_ret_err int ABTU_malloc(size_t size, void **p_ptr)
Definition: abtu.h:235
ABT_eventual_free
int ABT_eventual_free(ABT_eventual *eventual)
Free an eventual.
Definition: eventual.c:102
ABT_eventual
struct ABT_eventual_opaque * ABT_eventual
Eventual handle type.
Definition: abt.h:1015
ABT_SUCCESS
#define ABT_SUCCESS
Error code: the routine returns successfully.
Definition: abt.h:92
ABT_SYNC_EVENT_TYPE_EVENTUAL
@ ABT_SYNC_EVENT_TYPE_EVENTUAL
Definition: abt.h:714
ABT_TRUE
#define ABT_TRUE
True constant for ABT_bool.
Definition: abt.h:784
ABT_eventual_wait
int ABT_eventual_wait(ABT_eventual eventual, void **value)
Wait on an eventual.
Definition: eventual.c:173
ABT_FALSE
#define ABT_FALSE
False constant for ABT_bool.
Definition: abt.h:786
ABT_ERR_INV_ARG
#define ABT_ERR_INV_ARG
Error code: invalid user argument.
Definition: abt.h:260
ABTU_free
static void ABTU_free(void *ptr)
Definition: abtu.h:228
ABT_eventual_test
int ABT_eventual_test(ABT_eventual eventual, void **value, ABT_bool *is_ready)
Check if an eventual is ready.
Definition: eventual.c:248
ABT_ERR_EVENTUAL
#define ABT_ERR_EVENTUAL
Error code: error related to an eventual.
Definition: abt.h:350
ABT_eventual_set
int ABT_eventual_set(ABT_eventual eventual, void *value, int nbytes)
Signal an eventual.
Definition: eventual.c:317
ABT_ERR_INV_EVENTUAL
#define ABT_ERR_INV_EVENTUAL
Error code: invalid eventual.
Definition: abt.h:230
ABT_eventual_create
int ABT_eventual_create(int nbytes, ABT_eventual *neweventual)
Create a new eventual.
Definition: eventual.c:42
ABT_EVENTUAL_NULL
#define ABT_EVENTUAL_NULL
Definition: abt.h:1113