ARGOBOTS  dce6e727ffc4ca5b3ffc04cb9517c6689be51ec5
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 {
45  ABTI_UB_ASSERT(neweventual);
46 
47  /* Check if the size of ABT_eventual_memory is okay. */
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 {
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);
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 {
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 &
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 {
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 {
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. */
347  }
348 
349  return ABT_SUCCESS;
350 }
351 
377 int ABT_eventual_reset(ABT_eventual eventual)
378 {
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);
386  p_eventual->ready = ABT_FALSE;
387  ABTD_spinlock_release(&p_eventual->lock);
388  return ABT_SUCCESS;
389 }
ABTI_eventual::ready
ABT_bool ready
Definition: abti.h:498
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
ABTI_waitlist_broadcast
static void ABTI_waitlist_broadcast(ABTI_local *p_local, ABTI_waitlist *p_waitlist)
Definition: abti_waitlist.h:246
ABTI_eventual_get_handle
static ABT_eventual ABTI_eventual_get_handle(ABTI_eventual *p_eventual)
Definition: abti_eventual.h:26
ABTI_eventual
Definition: abti.h:496
ABTI_CHECK_ERROR
#define ABTI_CHECK_ERROR(abt_errno)
Definition: abti_error.h:136
ABTI_xstream::type
ABTI_xstream_type type
Definition: abti.h:300
ABTI_THREAD_TYPE_YIELDABLE
#define ABTI_THREAD_TYPE_YIELDABLE
Definition: abti.h:87
ABT_eventual_memory
A struct that can be converted to ABT_eventual.
Definition: abt.h:1283
ABTI_IS_ERROR_CHECK_ENABLED
#define ABTI_IS_ERROR_CHECK_ENABLED
Definition: abti.h:20
ABTI_xstream
Definition: abti.h:294
ABTI_eventual_get_ptr
static ABTI_eventual * ABTI_eventual_get_ptr(ABT_eventual eventual)
Definition: abti_eventual.h:11
ABTI_waitlist_is_empty
static ABT_bool ABTI_waitlist_is_empty(ABTI_waitlist *p_waitlist)
Definition: abti_waitlist.h:282
abti.h
ABTD_spinlock_acquire
static void ABTD_spinlock_acquire(ABTD_spinlock *p_lock)
Definition: abtd_spinlock.h:28
ABTI_HANDLE_ERROR
#define ABTI_HANDLE_ERROR(n)
Definition: abti_error.h:130
ABTU_malloc
static ABTU_ret_err int ABTU_malloc(size_t size, void **p_ptr)
Definition: abtu.h:235
ABTI_eventual::lock
ABTD_spinlock lock
Definition: abti.h:497
ABTI_initialized
ABT_bool ABTI_initialized(void)
Definition: global.c:187
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
ABTI_local_get_local
static ABTI_local * ABTI_local_get_local(void)
Definition: abti_local.h:41
ABTI_STATIC_ASSERT
#define ABTI_STATIC_ASSERT(cond)
Definition: abti_error.h:35
ABT_SUCCESS
#define ABT_SUCCESS
Error code: the routine returns successfully.
Definition: abt.h:92
ABTI_CHECK_NULL_EVENTUAL_PTR
#define ABTI_CHECK_NULL_EVENTUAL_PTR(p)
Definition: abti_error.h:319
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
ABTD_spinlock_clear
static void ABTD_spinlock_clear(ABTD_spinlock *p_lock)
Definition: abtd_spinlock.h:23
ABT_FALSE
#define ABT_FALSE
False constant for ABT_bool.
Definition: abt.h:786
ABTI_eventual::value
void * value
Definition: abti.h:499
ABTI_UB_ASSERT
#define ABTI_UB_ASSERT(cond)
Definition: abti_error.h:19
ABT_ERR_INV_ARG
#define ABT_ERR_INV_ARG
Error code: invalid user argument.
Definition: abt.h:260
ABTI_eventual::waitlist
ABTI_waitlist waitlist
Definition: abti.h:501
ABTU_free
static void ABTU_free(void *ptr)
Definition: abtu.h:228
ABTD_spinlock_release
static void ABTD_spinlock_release(ABTD_spinlock *p_lock)
Definition: abtd_spinlock.h:42
ABTI_local
struct ABTI_local ABTI_local
Definition: abti.h:132
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
ABTI_CHECK_TRUE
#define ABTI_CHECK_TRUE(cond, abt_errno)
Definition: abti_error.h:146
ABTI_waitlist_init
static void ABTI_waitlist_init(ABTI_waitlist *p_waitlist)
Definition: abti_waitlist.h:11
ABTI_local_get_xstream
static ABTI_xstream * ABTI_local_get_xstream(ABTI_local *p_local)
Definition: abti_local.h:86
ABTI_waitlist_wait_and_unlock
static void ABTI_waitlist_wait_and_unlock(ABTI_local **pp_local, ABTI_waitlist *p_waitlist, ABTD_spinlock *p_lock, ABT_sync_event_type sync_event_type, void *p_sync)
Definition: abti_waitlist.h:21
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