ARGOBOTS  c6511494322293e01714f56f341b8d2b22c1e3c1
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups
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 
26 int ABT_barrier_create(uint32_t num_waiters, ABT_barrier *newbarrier)
27 {
28  int abt_errno;
29  ABTI_barrier *p_newbarrier;
30 
31  abt_errno = ABTU_malloc(sizeof(ABTI_barrier), (void **)&p_newbarrier);
32  ABTI_CHECK_ERROR(abt_errno);
33 
34  ABTI_spinlock_clear(&p_newbarrier->lock);
35  p_newbarrier->num_waiters = num_waiters;
36  p_newbarrier->counter = 0;
37  abt_errno = ABTU_malloc(num_waiters * sizeof(ABTI_ythread *),
38  (void **)&p_newbarrier->waiters);
39  if (ABTI_IS_ERROR_CHECK_ENABLED && abt_errno != ABT_SUCCESS) {
40  ABTU_free(p_newbarrier);
41  ABTI_HANDLE_ERROR(abt_errno);
42  }
43  abt_errno = ABTU_malloc(num_waiters * sizeof(ABT_unit_type),
44  (void **)&p_newbarrier->waiter_type);
45  if (ABTI_IS_ERROR_CHECK_ENABLED && abt_errno != ABT_SUCCESS) {
46  ABTU_free(p_newbarrier->waiters);
47  ABTU_free(p_newbarrier);
48  ABTI_HANDLE_ERROR(abt_errno);
49  }
50 
51  /* Return value */
52  *newbarrier = ABTI_barrier_get_handle(p_newbarrier);
53  return ABT_SUCCESS;
54 }
55 
69 int ABT_barrier_reinit(ABT_barrier barrier, uint32_t num_waiters)
70 {
71  ABTI_barrier *p_barrier = ABTI_barrier_get_ptr(barrier);
72  ABTI_CHECK_NULL_BARRIER_PTR(p_barrier);
73  ABTI_ASSERT(p_barrier->counter == 0);
74 
75  /* Only when num_waiters is different from p_barrier->num_waiters, we
76  * change p_barrier. */
77  if (num_waiters < p_barrier->num_waiters) {
78  /* We can reuse waiters and waiter_type arrays */
79  p_barrier->num_waiters = num_waiters;
80  } else if (num_waiters > p_barrier->num_waiters) {
81  /* Free existing arrays and reallocate them */
82  int abt_errno;
83  ABTI_ythread **new_waiters;
84  ABT_unit_type *new_waiter_types;
85  abt_errno = ABTU_malloc(num_waiters * sizeof(ABTI_ythread *),
86  (void **)&new_waiters);
87  ABTI_CHECK_ERROR(abt_errno);
88  abt_errno = ABTU_malloc(num_waiters * sizeof(ABT_unit_type),
89  (void **)&new_waiter_types);
90  if (ABTI_IS_ERROR_CHECK_ENABLED && abt_errno != ABT_SUCCESS) {
91  ABTU_free(new_waiters);
92  ABTI_HANDLE_ERROR(abt_errno);
93  }
94  p_barrier->num_waiters = num_waiters;
95  ABTU_free(p_barrier->waiters);
96  ABTU_free(p_barrier->waiter_type);
97  p_barrier->waiters = new_waiters;
98  p_barrier->waiter_type = new_waiter_types;
99  }
100  return ABT_SUCCESS;
101 }
102 
116 {
117  ABT_barrier h_barrier = *barrier;
118  ABTI_barrier *p_barrier = ABTI_barrier_get_ptr(h_barrier);
119  ABTI_CHECK_NULL_BARRIER_PTR(p_barrier);
120 
121  ABTI_ASSERT(p_barrier->counter == 0);
122 
123  /* The lock needs to be acquired to safely free the barrier structure.
124  * However, we do not have to unlock it because the entire structure is
125  * freed here. */
126  ABTI_spinlock_acquire(&p_barrier->lock);
127 
128  ABTU_free(p_barrier->waiters);
129  ABTU_free(p_barrier->waiter_type);
130  ABTU_free(p_barrier);
131 
132  /* Return value */
133  *barrier = ABT_BARRIER_NULL;
134  return ABT_SUCCESS;
135 }
136 
149 {
150  ABTI_local *p_local = ABTI_local_get_local();
151  ABTI_barrier *p_barrier = ABTI_barrier_get_ptr(barrier);
152  ABTI_CHECK_NULL_BARRIER_PTR(p_barrier);
153  uint32_t pos;
154 
155  ABTI_spinlock_acquire(&p_barrier->lock);
156 
157  ABTI_ASSERT(p_barrier->counter < p_barrier->num_waiters);
158  pos = p_barrier->counter++;
159 
160  /* If we do not have all the waiters yet */
161  if (p_barrier->counter < p_barrier->num_waiters) {
162  ABTI_ythread *p_ythread = NULL;
163  ABT_unit_type type;
164  ABTD_atomic_int32 ext_signal = ABTD_ATOMIC_INT32_STATIC_INITIALIZER(0);
165 
166  ABTI_xstream *p_local_xstream = ABTI_local_get_xstream_or_null(p_local);
167  if (!ABTI_IS_EXT_THREAD_ENABLED || p_local_xstream) {
168  p_ythread =
169  ABTI_thread_get_ythread_or_null(p_local_xstream->p_thread);
170  }
171  if (p_ythread) {
172  /* yieldable thread */
173  type = ABT_UNIT_TYPE_THREAD;
174  } else {
175  /* external thread or non-yieldable thread */
176  /* Check size if ext_signal can be stored in p_thread. */
177  ABTI_STATIC_ASSERT(sizeof(ext_signal) <= sizeof(p_ythread));
178  p_ythread = (ABTI_ythread *)&ext_signal;
179  type = ABT_UNIT_TYPE_EXT;
180  }
181 
182  /* Keep the waiter's information */
183  p_barrier->waiters[pos] = p_ythread;
184  p_barrier->waiter_type[pos] = type;
185 
186  if (type == ABT_UNIT_TYPE_THREAD) {
187  /* Change the ULT's state to BLOCKED */
188  ABTI_ythread_set_blocked(p_ythread);
189  }
190 
191  ABTI_spinlock_release(&p_barrier->lock);
192 
193  if (type == ABT_UNIT_TYPE_THREAD) {
194  /* Suspend the current ULT */
195  ABTI_ythread_suspend(&p_local_xstream, p_ythread,
197  (void *)p_barrier);
198  } else {
199  /* External thread is waiting here polling ext_signal. */
200  /* FIXME: need a better implementation */
201  while (!ABTD_atomic_acquire_load_int32(&ext_signal))
202  ;
203  }
204  } else {
205  /* Signal all the waiting ULTs */
206  int i;
207  for (i = 0; i < p_barrier->num_waiters - 1; i++) {
208  ABTI_ythread *p_ythread = p_barrier->waiters[i];
209  if (p_barrier->waiter_type[i] == ABT_UNIT_TYPE_THREAD) {
210  ABTI_ythread_set_ready(p_local, p_ythread);
211  } else {
212  /* When p_cur is an external thread */
213  ABTD_atomic_int32 *p_ext_signal =
214  (ABTD_atomic_int32 *)p_ythread;
215  ABTD_atomic_release_store_int32(p_ext_signal, 1);
216  }
217 
218  p_barrier->waiters[i] = NULL;
219  }
220 
221  /* Reset counter */
222  p_barrier->counter = 0;
223 
224  ABTI_spinlock_release(&p_barrier->lock);
225  }
226  return ABT_SUCCESS;
227 }
228 
242 int ABT_barrier_get_num_waiters(ABT_barrier barrier, uint32_t *num_waiters)
243 {
244  ABTI_barrier *p_barrier = ABTI_barrier_get_ptr(barrier);
245  ABTI_CHECK_NULL_BARRIER_PTR(p_barrier);
246 
247  *num_waiters = p_barrier->num_waiters;
248  return ABT_SUCCESS;
249 }
struct ABT_barrier_opaque * ABT_barrier
Definition: abt.h:369
int ABT_barrier_free(ABT_barrier *barrier) ABT_API_PUBLIC
Free the barrier.
Definition: barrier.c:115
int ABT_barrier_create(uint32_t num_waiters, ABT_barrier *newbarrier) ABT_API_PUBLIC
Create a new barrier.
Definition: barrier.c:26
static ABTU_ret_err int ABTU_malloc(size_t size, void **p_ptr)
Definition: abtu.h:129
int ABT_barrier_reinit(ABT_barrier barrier, uint32_t num_waiters) ABT_API_PUBLIC
Reinitialize the barrier.
Definition: barrier.c:69
#define ABT_SUCCESS
Definition: abt.h:64
ABT_unit_type
Definition: abt.h:169
int ABT_barrier_wait(ABT_barrier barrier) ABT_API_PUBLIC
Wait on the barrier.
Definition: barrier.c:148
int ABT_barrier_get_num_waiters(ABT_barrier barrier, uint32_t *num_waiters) ABT_API_PUBLIC
Get the number of waiters for the barrier.
Definition: barrier.c:242
static void ABTU_free(void *ptr)
Definition: abtu.h:122
#define ABT_BARRIER_NULL
Definition: abt.h:425