ARGOBOTS  1059a7c2eb7e3f99f736a9c3a4f6ea476ac1b804
 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  /* The lock needs to be acquired to safely free the barrier structure.
122  * However, we do not have to unlock it because the entire structure is
123  * freed here. */
124  ABTI_spinlock_acquire(&p_barrier->lock);
125 
126  /* p_barrier->counter must be checked after taking a lock. */
127  ABTI_ASSERT(p_barrier->counter == 0);
128 
129  ABTU_free(p_barrier->waiters);
130  ABTU_free(p_barrier->waiter_type);
131  ABTU_free(p_barrier);
132 
133  /* Return value */
134  *barrier = ABT_BARRIER_NULL;
135  return ABT_SUCCESS;
136 }
137 
150 {
151  ABTI_local *p_local = ABTI_local_get_local();
152  ABTI_barrier *p_barrier = ABTI_barrier_get_ptr(barrier);
153  ABTI_CHECK_NULL_BARRIER_PTR(p_barrier);
154  uint32_t pos;
155 
156  ABTI_spinlock_acquire(&p_barrier->lock);
157 
158  ABTI_ASSERT(p_barrier->counter < p_barrier->num_waiters);
159  pos = p_barrier->counter++;
160 
161  /* If we do not have all the waiters yet */
162  if (p_barrier->counter < p_barrier->num_waiters) {
163  ABTI_ythread *p_ythread = NULL;
164  ABT_unit_type type;
165  ABTD_atomic_int32 ext_signal = ABTD_ATOMIC_INT32_STATIC_INITIALIZER(0);
166 
167  ABTI_xstream *p_local_xstream = ABTI_local_get_xstream_or_null(p_local);
168  if (!ABTI_IS_EXT_THREAD_ENABLED || p_local_xstream) {
169  p_ythread =
170  ABTI_thread_get_ythread_or_null(p_local_xstream->p_thread);
171  }
172  if (p_ythread) {
173  /* yieldable thread */
174  type = ABT_UNIT_TYPE_THREAD;
175  } else {
176  /* external thread or non-yieldable thread */
177  /* Check size if ext_signal can be stored in p_thread. */
178  ABTI_STATIC_ASSERT(sizeof(ext_signal) <= sizeof(p_ythread));
179  p_ythread = (ABTI_ythread *)&ext_signal;
180  type = ABT_UNIT_TYPE_EXT;
181  }
182 
183  /* Keep the waiter's information */
184  p_barrier->waiters[pos] = p_ythread;
185  p_barrier->waiter_type[pos] = type;
186 
187  if (type == ABT_UNIT_TYPE_THREAD) {
188  /* Change the ULT's state to BLOCKED */
189  ABTI_ythread_set_blocked(p_ythread);
190  }
191 
192  ABTI_spinlock_release(&p_barrier->lock);
193 
194  if (type == ABT_UNIT_TYPE_THREAD) {
195  /* Suspend the current ULT */
196  ABTI_ythread_suspend(&p_local_xstream, p_ythread,
198  (void *)p_barrier);
199  } else {
200  /* External thread is waiting here polling ext_signal. */
201  /* FIXME: need a better implementation */
202  while (!ABTD_atomic_acquire_load_int32(&ext_signal))
203  ;
204  }
205  } else {
206  /* Signal all the waiting ULTs */
207  int i;
208  for (i = 0; i < p_barrier->num_waiters - 1; i++) {
209  ABTI_ythread *p_ythread = p_barrier->waiters[i];
210  if (p_barrier->waiter_type[i] == ABT_UNIT_TYPE_THREAD) {
211  ABTI_ythread_set_ready(p_local, p_ythread);
212  } else {
213  /* When p_cur is an external thread */
214  ABTD_atomic_int32 *p_ext_signal =
215  (ABTD_atomic_int32 *)p_ythread;
216  ABTD_atomic_release_store_int32(p_ext_signal, 1);
217  }
218 
219  p_barrier->waiters[i] = NULL;
220  }
221 
222  /* Reset counter */
223  p_barrier->counter = 0;
224 
225  ABTI_spinlock_release(&p_barrier->lock);
226  }
227  return ABT_SUCCESS;
228 }
229 
243 int ABT_barrier_get_num_waiters(ABT_barrier barrier, uint32_t *num_waiters)
244 {
245  ABTI_barrier *p_barrier = ABTI_barrier_get_ptr(barrier);
246  ABTI_CHECK_NULL_BARRIER_PTR(p_barrier);
247 
248  *num_waiters = p_barrier->num_waiters;
249  return ABT_SUCCESS;
250 }
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:149
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:243
static void ABTU_free(void *ptr)
Definition: abtu.h:122
#define ABT_BARRIER_NULL
Definition: abt.h:425