ARGOBOTS  1.1
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  int abt_errno;
45  ABTI_eventual *p_eventual;
46  ABTI_CHECK_TRUE(nbytes >= 0, ABT_ERR_INV_ARG);
47  size_t arg_nbytes = nbytes;
48 
49  abt_errno = ABTU_malloc(sizeof(ABTI_eventual), (void **)&p_eventual);
50  ABTI_CHECK_ERROR(abt_errno);
51 
52  ABTD_spinlock_clear(&p_eventual->lock);
53  p_eventual->ready = ABT_FALSE;
54  p_eventual->nbytes = arg_nbytes;
55  if (arg_nbytes == 0) {
56  p_eventual->value = NULL;
57  } else {
58  abt_errno = ABTU_malloc(arg_nbytes, &p_eventual->value);
59  if (ABTI_IS_ERROR_CHECK_ENABLED && abt_errno != ABT_SUCCESS) {
60  ABTU_free(p_eventual);
61  ABTI_HANDLE_ERROR(abt_errno);
62  }
63  }
64  ABTI_waitlist_init(&p_eventual->waitlist);
65 
66  *neweventual = ABTI_eventual_get_handle(p_eventual);
67  return ABT_SUCCESS;
68 }
69 
97 {
98  ABTI_eventual *p_eventual = ABTI_eventual_get_ptr(*eventual);
99  ABTI_CHECK_NULL_EVENTUAL_PTR(p_eventual);
100 
101  /* The lock needs to be acquired to safely free the eventual structure.
102  * However, we do not have to unlock it because the entire structure is
103  * freed here. */
104  ABTD_spinlock_acquire(&p_eventual->lock);
105 
106  if (p_eventual->value)
107  ABTU_free(p_eventual->value);
108  ABTU_free(p_eventual);
109 
110  *eventual = ABT_EVENTUAL_NULL;
111  return ABT_SUCCESS;
112 }
113 
163 int ABT_eventual_wait(ABT_eventual eventual, void **value)
164 {
165  ABTI_local *p_local = ABTI_local_get_local();
166  ABTI_eventual *p_eventual = ABTI_eventual_get_ptr(eventual);
167  ABTI_CHECK_NULL_EVENTUAL_PTR(p_eventual);
168 
169 #ifndef ABT_CONFIG_ENABLE_VER_20_API
170  /* This routine cannot be called by a tasklet. */
171  if (ABTI_IS_ERROR_CHECK_ENABLED && p_local) {
172  ABTI_xstream *p_local_xstream = ABTI_local_get_xstream(p_local);
173  ABTI_CHECK_TRUE(p_local_xstream->p_thread->type &
176  }
177 #endif
178 
179  ABTD_spinlock_acquire(&p_eventual->lock);
180  if (p_eventual->ready == ABT_FALSE) {
181  ABTI_waitlist_wait_and_unlock(&p_local, &p_eventual->waitlist,
182  &p_eventual->lock,
184  (void *)p_eventual);
185  } else {
186  ABTD_spinlock_release(&p_eventual->lock);
187  }
188  /* This value is updated outside the critical section, but it is okay since
189  * the "pointer" to the memory buffer is constant and there is no way to
190  * avoid updating this memory buffer by ABT_eventual_set() etc. */
191  if (value)
192  *value = p_eventual->value;
193  return ABT_SUCCESS;
194 }
195 
236 int ABT_eventual_test(ABT_eventual eventual, void **value, ABT_bool *is_ready)
237 {
238  ABTI_eventual *p_eventual = ABTI_eventual_get_ptr(eventual);
239  ABTI_CHECK_NULL_EVENTUAL_PTR(p_eventual);
240  ABT_bool flag = ABT_FALSE;
241 
242  ABTD_spinlock_acquire(&p_eventual->lock);
243  if (p_eventual->ready != ABT_FALSE) {
244  if (value)
245  *value = p_eventual->value;
246  flag = ABT_TRUE;
247  }
248  ABTD_spinlock_release(&p_eventual->lock);
249 
250  *is_ready = flag;
251  return ABT_SUCCESS;
252 }
253 
300 int ABT_eventual_set(ABT_eventual eventual, void *value, int nbytes)
301 {
303  ABTI_eventual *p_eventual = ABTI_eventual_get_ptr(eventual);
304  ABTI_CHECK_NULL_EVENTUAL_PTR(p_eventual);
305  ABTI_CHECK_TRUE(nbytes >= 0, ABT_ERR_INV_ARG);
306  size_t arg_nbytes = nbytes;
307 #ifndef ABT_CONFIG_ENABLE_VER_20_API
308  /* Argobots 1.x */
309  ABTI_CHECK_TRUE(arg_nbytes <= p_eventual->nbytes, ABT_ERR_INV_EVENTUAL);
310 #else
311  /* Argobots 2.0 */
312  ABTI_CHECK_TRUE(arg_nbytes <= p_eventual->nbytes, ABT_ERR_INV_ARG);
313 #endif
314 
315  ABTD_spinlock_acquire(&p_eventual->lock);
316 
317  ABT_bool ready = p_eventual->ready;
318  if (ready == ABT_FALSE) {
319  if (p_eventual->value)
320  memcpy(p_eventual->value, value, arg_nbytes);
321  p_eventual->ready = ABT_TRUE;
322  /* Wake up all waiting ULTs */
323  ABTI_waitlist_broadcast(p_local, &p_eventual->waitlist);
324  ABTD_spinlock_release(&p_eventual->lock);
325  } else {
326  ABTD_spinlock_release(&p_eventual->lock);
327  /* It has been ready. Error. */
329  }
330 
331  return ABT_SUCCESS;
332 }
333 
359 int ABT_eventual_reset(ABT_eventual eventual)
360 {
361  ABTI_eventual *p_eventual = ABTI_eventual_get_ptr(eventual);
362  ABTI_CHECK_NULL_EVENTUAL_PTR(p_eventual);
363 
364  ABTD_spinlock_acquire(&p_eventual->lock);
365  p_eventual->ready = ABT_FALSE;
366  ABTD_spinlock_release(&p_eventual->lock);
367  return ABT_SUCCESS;
368 }
ABTI_eventual::ready
ABT_bool ready
Definition: abti.h:450
ABT_eventual_reset
int ABT_eventual_reset(ABT_eventual eventual)
Reset a readiness of an eventual.
Definition: eventual.c:361
ABT_bool
int ABT_bool
Boolean type.
Definition: abt.h:1001
ABTI_waitlist_broadcast
static void ABTI_waitlist_broadcast(ABTI_local *p_local, ABTI_waitlist *p_waitlist)
Definition: abti_waitlist.h:247
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:448
ABTI_CHECK_ERROR
#define ABTI_CHECK_ERROR(abt_errno)
Definition: abti_error.h:120
ABTI_xstream::type
ABTI_xstream_type type
Definition: abti.h:270
ABTI_THREAD_TYPE_YIELDABLE
#define ABTI_THREAD_TYPE_YIELDABLE
Definition: abti.h:86
ABTI_IS_ERROR_CHECK_ENABLED
#define ABTI_IS_ERROR_CHECK_ENABLED
Definition: abti.h:20
ABTI_xstream
Definition: abti.h:264
ABTI_eventual_get_ptr
static ABTI_eventual * ABTI_eventual_get_ptr(ABT_eventual eventual)
Definition: abti_eventual.h:11
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:114
ABTU_malloc
static ABTU_ret_err int ABTU_malloc(size_t size, void **p_ptr)
Definition: abtu.h:262
ABTI_eventual::lock
ABTD_spinlock lock
Definition: abti.h:449
ABT_eventual_free
int ABT_eventual_free(ABT_eventual *eventual)
Free an eventual.
Definition: eventual.c:96
ABT_eventual
struct ABT_eventual_opaque * ABT_eventual
Eventual handle type.
Definition: abt.h:973
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:285
ABT_SYNC_EVENT_TYPE_EVENTUAL
@ ABT_SYNC_EVENT_TYPE_EVENTUAL
Definition: abt.h:678
ABT_TRUE
#define ABT_TRUE
True constant for ABT_bool.
Definition: abt.h:748
ABT_eventual_wait
int ABT_eventual_wait(ABT_eventual eventual, void **value)
Wait on an eventual.
Definition: eventual.c:163
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:750
ABTI_eventual::value
void * value
Definition: abti.h:451
ABT_ERR_INV_ARG
#define ABT_ERR_INV_ARG
Error code: invalid user argument.
Definition: abt.h:250
ABTI_eventual::waitlist
ABTI_waitlist waitlist
Definition: abti.h:453
ABTU_free
static void ABTU_free(void *ptr)
Definition: abtu.h:217
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:110
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:236
ABTI_CHECK_TRUE
#define ABTI_CHECK_TRUE(cond, abt_errno)
Definition: abti_error.h:130
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:340
ABT_eventual_set
int ABT_eventual_set(ABT_eventual eventual, void *value, int nbytes)
Signal an eventual.
Definition: eventual.c:302
ABT_ERR_INV_EVENTUAL
#define ABT_ERR_INV_EVENTUAL
Error code: invalid eventual.
Definition: abt.h:220
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:1070