ARGOBOTS  be805649b56a69fc4df1b6bc4efbc8911b854459
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  int abt_errno;
48  ABTI_eventual *p_eventual;
49  ABTI_CHECK_TRUE(nbytes >= 0, ABT_ERR_INV_ARG);
50  size_t arg_nbytes = nbytes;
51 
52  abt_errno = ABTU_malloc(sizeof(ABTI_eventual), (void **)&p_eventual);
53  ABTI_CHECK_ERROR(abt_errno);
54 
55  ABTD_spinlock_clear(&p_eventual->lock);
56  p_eventual->ready = ABT_FALSE;
57  p_eventual->nbytes = arg_nbytes;
58  if (arg_nbytes == 0) {
59  p_eventual->value = NULL;
60  } else {
61  abt_errno = ABTU_malloc(arg_nbytes, &p_eventual->value);
62  if (ABTI_IS_ERROR_CHECK_ENABLED && abt_errno != ABT_SUCCESS) {
63  ABTU_free(p_eventual);
64  ABTI_HANDLE_ERROR(abt_errno);
65  }
66  }
67  ABTI_waitlist_init(&p_eventual->waitlist);
68 
69  *neweventual = ABTI_eventual_get_handle(p_eventual);
70  return ABT_SUCCESS;
71 }
72 
100 {
102  ABTI_UB_ASSERT(eventual);
103 
104  ABTI_eventual *p_eventual = ABTI_eventual_get_ptr(*eventual);
105  ABTI_CHECK_NULL_EVENTUAL_PTR(p_eventual);
106 
107  /* The lock needs to be acquired to safely free the eventual structure.
108  * However, we do not have to unlock it because the entire structure is
109  * freed here. */
110  ABTD_spinlock_acquire(&p_eventual->lock);
112 
113  if (p_eventual->value)
114  ABTU_free(p_eventual->value);
115  ABTU_free(p_eventual);
116 
117  *eventual = ABT_EVENTUAL_NULL;
118  return ABT_SUCCESS;
119 }
120 
170 int ABT_eventual_wait(ABT_eventual eventual, void **value)
171 {
173 
174  ABTI_local *p_local = ABTI_local_get_local();
175  ABTI_eventual *p_eventual = ABTI_eventual_get_ptr(eventual);
176  ABTI_CHECK_NULL_EVENTUAL_PTR(p_eventual);
177 
178 #ifndef ABT_CONFIG_ENABLE_VER_20_API
179  /* This routine cannot be called by a tasklet. */
180  if (ABTI_IS_ERROR_CHECK_ENABLED && p_local) {
181  ABTI_xstream *p_local_xstream = ABTI_local_get_xstream(p_local);
182  ABTI_CHECK_TRUE(p_local_xstream->p_thread->type &
185  }
186 #endif
187 
188  ABTD_spinlock_acquire(&p_eventual->lock);
189  if (p_eventual->ready == ABT_FALSE) {
190  ABTI_waitlist_wait_and_unlock(&p_local, &p_eventual->waitlist,
191  &p_eventual->lock,
193  (void *)p_eventual);
194  } else {
195  ABTD_spinlock_release(&p_eventual->lock);
196  }
197  /* This value is updated outside the critical section, but it is okay since
198  * the "pointer" to the memory buffer is constant and there is no way to
199  * avoid updating this memory buffer by ABT_eventual_set() etc. */
200  if (value)
201  *value = p_eventual->value;
202  return ABT_SUCCESS;
203 }
204 
245 int ABT_eventual_test(ABT_eventual eventual, void **value, ABT_bool *is_ready)
246 {
248  ABTI_UB_ASSERT(is_ready);
249 
250  ABTI_eventual *p_eventual = ABTI_eventual_get_ptr(eventual);
251  ABTI_CHECK_NULL_EVENTUAL_PTR(p_eventual);
252  ABT_bool flag = ABT_FALSE;
253 
254  ABTD_spinlock_acquire(&p_eventual->lock);
255  if (p_eventual->ready != ABT_FALSE) {
256  if (value)
257  *value = p_eventual->value;
258  flag = ABT_TRUE;
259  }
260  ABTD_spinlock_release(&p_eventual->lock);
261 
262  *is_ready = flag;
263  return ABT_SUCCESS;
264 }
265 
312 int ABT_eventual_set(ABT_eventual eventual, void *value, int nbytes)
313 {
315  ABTI_UB_ASSERT(value || nbytes <= 0);
316 
317  ABTI_local *p_local = ABTI_local_get_local();
318  ABTI_eventual *p_eventual = ABTI_eventual_get_ptr(eventual);
319  ABTI_CHECK_NULL_EVENTUAL_PTR(p_eventual);
320  ABTI_CHECK_TRUE(nbytes >= 0, ABT_ERR_INV_ARG);
321  size_t arg_nbytes = nbytes;
322 #ifndef ABT_CONFIG_ENABLE_VER_20_API
323  /* Argobots 1.x */
324  ABTI_CHECK_TRUE(arg_nbytes <= p_eventual->nbytes, ABT_ERR_INV_EVENTUAL);
325 #else
326  /* Argobots 2.0 */
327  ABTI_CHECK_TRUE(arg_nbytes <= p_eventual->nbytes, ABT_ERR_INV_ARG);
328 #endif
329 
330  ABTD_spinlock_acquire(&p_eventual->lock);
331 
332  ABT_bool ready = p_eventual->ready;
333  if (ready == ABT_FALSE) {
334  if (p_eventual->value)
335  memcpy(p_eventual->value, value, arg_nbytes);
336  p_eventual->ready = ABT_TRUE;
337  /* Wake up all waiting ULTs */
338  ABTI_waitlist_broadcast(p_local, &p_eventual->waitlist);
339  ABTD_spinlock_release(&p_eventual->lock);
340  } else {
341  ABTD_spinlock_release(&p_eventual->lock);
342  /* It has been ready. Error. */
344  }
345 
346  return ABT_SUCCESS;
347 }
348 
374 int ABT_eventual_reset(ABT_eventual eventual)
375 {
377 
378  ABTI_eventual *p_eventual = ABTI_eventual_get_ptr(eventual);
379  ABTI_CHECK_NULL_EVENTUAL_PTR(p_eventual);
380 
381  ABTD_spinlock_acquire(&p_eventual->lock);
383  p_eventual->ready = ABT_FALSE;
384  ABTD_spinlock_release(&p_eventual->lock);
385  return ABT_SUCCESS;
386 }
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:376
ABT_bool
int ABT_bool
Boolean type.
Definition: abt.h:1019
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
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:99
ABT_eventual
struct ABT_eventual_opaque * ABT_eventual
Eventual handle type.
Definition: abt.h:991
ABTI_local_get_local
static ABTI_local * ABTI_local_get_local(void)
Definition: abti_local.h:41
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:690
ABT_TRUE
#define ABT_TRUE
True constant for ABT_bool.
Definition: abt.h:760
ABT_eventual_wait
int ABT_eventual_wait(ABT_eventual eventual, void **value)
Wait on an eventual.
Definition: eventual.c:170
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:762
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:245
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:314
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:1089