ARGOBOTS  1.1
stream_barrier.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 
44 int ABT_xstream_barrier_create(uint32_t num_waiters,
45  ABT_xstream_barrier *newbarrier)
46 {
47 #ifndef ABT_CONFIG_ENABLE_VER_20_API
48  /* Argobots 1.x sets newbarrier to NULL on error. */
49  *newbarrier = ABT_XSTREAM_BARRIER_NULL;
50 #endif
51  int abt_errno;
52  ABTI_xstream_barrier *p_newbarrier;
53  ABTI_CHECK_TRUE(num_waiters != 0, ABT_ERR_INV_ARG);
54 
55  abt_errno =
56  ABTU_malloc(sizeof(ABTI_xstream_barrier), (void **)&p_newbarrier);
57  ABTI_CHECK_ERROR(abt_errno);
58 
59  p_newbarrier->num_waiters = num_waiters;
60 #ifdef HAVE_PTHREAD_BARRIER_INIT
61  abt_errno = ABTD_xstream_barrier_init(num_waiters, &p_newbarrier->bar);
62  if (ABTI_IS_ERROR_CHECK_ENABLED && abt_errno != ABT_SUCCESS) {
63  ABTU_free(p_newbarrier);
64  ABTI_HANDLE_ERROR(abt_errno);
65  }
66 #else
67  ABTD_spinlock_clear(&p_newbarrier->lock);
68  p_newbarrier->counter = 0;
69  ABTD_atomic_relaxed_store_uint64(&p_newbarrier->tag, 0);
70 #endif
71 
72  /* Return value */
73  *newbarrier = ABTI_xstream_barrier_get_handle(p_newbarrier);
74  return ABT_SUCCESS;
75 }
76 
102 {
103  ABT_xstream_barrier h_barrier = *barrier;
104  ABTI_xstream_barrier *p_barrier = ABTI_xstream_barrier_get_ptr(h_barrier);
106 
107 #ifdef HAVE_PTHREAD_BARRIER_INIT
108  ABTD_xstream_barrier_destroy(&p_barrier->bar);
109 #endif
110  ABTU_free(p_barrier);
111 
112  /* Return value */
113  *barrier = ABT_XSTREAM_BARRIER_NULL;
114  return ABT_SUCCESS;
115 }
116 
141 {
144 
145  if (p_barrier->num_waiters > 1) {
146 #ifdef HAVE_PTHREAD_BARRIER_INIT
147  ABTD_xstream_barrier_wait(&p_barrier->bar);
148 #else
149  /* The following implementation is a simple sense-reversal barrier
150  * implementation while it uses uint64_t instead of boolean to prevent
151  * a sense variable from wrapping around. */
152  ABTD_spinlock_acquire(&p_barrier->lock);
153  p_barrier->counter++;
154  if (p_barrier->counter == p_barrier->num_waiters) {
155  /* Wake up the other waiters. */
156  p_barrier->counter = 0;
157  /* Updating tag wakes up other waiters. Note that this tag is
158  * sufficiently large, so it will not wrap around. */
159  uint64_t cur_tag = ABTD_atomic_relaxed_load_uint64(&p_barrier->tag);
160  uint64_t new_tag = (cur_tag + 1) & (UINT64_MAX >> 1);
161  ABTD_atomic_release_store_uint64(&p_barrier->tag, new_tag);
162  ABTD_spinlock_release(&p_barrier->lock);
163  } else {
164  /* Wait until the tag is updated by the last waiter */
165  uint64_t cur_tag = ABTD_atomic_relaxed_load_uint64(&p_barrier->tag);
166  ABTD_spinlock_release(&p_barrier->lock);
167  while (cur_tag == ABTD_atomic_acquire_load_uint64(&p_barrier->tag))
169  }
170 #endif
171  }
172  return ABT_SUCCESS;
173 }
ABTD_atomic_relaxed_load_uint64
static uint64_t ABTD_atomic_relaxed_load_uint64(const ABTD_atomic_uint64 *ptr)
Definition: abtd_atomic.h:832
ABT_xstream_barrier_free
int ABT_xstream_barrier_free(ABT_xstream_barrier *barrier)
Free an execution-stream barrier.
Definition: stream_barrier.c:101
ABTD_atomic_relaxed_store_uint64
static void ABTD_atomic_relaxed_store_uint64(ABTD_atomic_uint64 *ptr, uint64_t val)
Definition: abtd_atomic.h:1045
ABTI_xstream_barrier::lock
ABTD_spinlock lock
Definition: abti.h:477
ABTI_xstream_barrier_get_ptr
static ABTI_xstream_barrier * ABTI_xstream_barrier_get_ptr(ABT_xstream_barrier barrier)
Definition: abti_stream_barrier.h:10
ABTI_xstream_barrier
Definition: abti.h:472
ABTI_CHECK_ERROR
#define ABTI_CHECK_ERROR(abt_errno)
Definition: abti_error.h:120
ABT_xstream_barrier_wait
int ABT_xstream_barrier_wait(ABT_xstream_barrier barrier)
Wait on an execution-stream barrier.
Definition: stream_barrier.c:140
ABTI_IS_ERROR_CHECK_ENABLED
#define ABTI_IS_ERROR_CHECK_ENABLED
Definition: abti.h:20
ABTD_atomic_acquire_load_uint64
static uint64_t ABTD_atomic_acquire_load_uint64(const ABTD_atomic_uint64 *ptr)
Definition: abtd_atomic.h:962
ABTI_xstream_barrier_get_handle
static ABT_xstream_barrier ABTI_xstream_barrier_get_handle(ABTI_xstream_barrier *p_barrier)
Definition: abti_stream_barrier.h:26
ABTI_xstream_barrier::num_waiters
uint32_t num_waiters
Definition: abti.h:473
ABTD_atomic_release_store_uint64
static void ABTD_atomic_release_store_uint64(ABTD_atomic_uint64 *ptr, uint64_t val)
Definition: abtd_atomic.h:1124
abti.h
ABTD_spinlock_acquire
static void ABTD_spinlock_acquire(ABTD_spinlock *p_lock)
Definition: abtd_spinlock.h:28
ABTI_CHECK_NULL_XSTREAM_BARRIER_PTR
#define ABTI_CHECK_NULL_XSTREAM_BARRIER_PTR(p)
Definition: abti_error.h:303
ABTI_HANDLE_ERROR
#define ABTI_HANDLE_ERROR(n)
Definition: abti_error.h:114
ABTD_atomic_pause
static void ABTD_atomic_pause(void)
Definition: abtd_atomic.h:1257
ABTU_malloc
static ABTU_ret_err int ABTU_malloc(size_t size, void **p_ptr)
Definition: abtu.h:262
ABTI_xstream_barrier::counter
uint32_t counter
Definition: abti.h:478
ABT_SUCCESS
#define ABT_SUCCESS
Error code: the routine returns successfully.
Definition: abt.h:92
ABT_XSTREAM_BARRIER_NULL
#define ABT_XSTREAM_BARRIER_NULL
Definition: abt.h:1056
ABT_xstream_barrier
struct ABT_xstream_barrier_opaque * ABT_xstream_barrier
Execution-stream barrier handle type.
Definition: abt.h:801
ABTD_spinlock_clear
static void ABTD_spinlock_clear(ABTD_spinlock *p_lock)
Definition: abtd_spinlock.h:23
ABT_ERR_INV_ARG
#define ABT_ERR_INV_ARG
Error code: invalid user argument.
Definition: abt.h:250
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_xstream_barrier::tag
ABTD_atomic_uint64 tag
Definition: abti.h:479
ABTI_CHECK_TRUE
#define ABTI_CHECK_TRUE(cond, abt_errno)
Definition: abti_error.h:130
ABT_xstream_barrier_create
int ABT_xstream_barrier_create(uint32_t num_waiters, ABT_xstream_barrier *newbarrier)
Create a new execution-stream barrier.
Definition: stream_barrier.c:44