ARGOBOTS
cond.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 #include <sys/time.h>
8 
27 {
28  int abt_errno = ABT_SUCCESS;
29  ABTI_cond *p_newcond;
30 
31  p_newcond = (ABTI_cond *)ABTU_malloc(sizeof(ABTI_cond));
32  ABTI_cond_init(p_newcond);
33 
34  /* Return value */
35  *newcond = ABTI_cond_get_handle(p_newcond);
36 
37  return abt_errno;
38 }
39 
53 {
54  int abt_errno = ABT_SUCCESS;
55  ABT_cond h_cond = *cond;
56  ABTI_cond *p_cond = ABTI_cond_get_ptr(h_cond);
57  ABTI_CHECK_NULL_COND_PTR(p_cond);
58 
59  ABTI_CHECK_TRUE(p_cond->num_waiters == 0, ABT_ERR_COND);
60 
61  ABTI_cond_fini(p_cond);
62  ABTU_free(p_cond);
63 
64  /* Return value */
65  *cond = ABT_COND_NULL;
66 
67 fn_exit:
68  return abt_errno;
69 
70 fn_fail:
71  HANDLE_ERROR_FUNC_WITH_CODE(abt_errno);
72  goto fn_exit;
73 }
74 
93 {
94  int abt_errno = ABT_SUCCESS;
95  ABTI_local *p_local = ABTI_local_get_local();
96  ABTI_cond *p_cond = ABTI_cond_get_ptr(cond);
97  ABTI_CHECK_NULL_COND_PTR(p_cond);
98  ABTI_mutex *p_mutex = ABTI_mutex_get_ptr(mutex);
99  ABTI_CHECK_NULL_MUTEX_PTR(p_mutex);
100 
101  abt_errno = ABTI_cond_wait(&p_local, p_cond, p_mutex);
102  if (abt_errno != ABT_SUCCESS)
103  goto fn_fail;
104 
105 fn_exit:
106  return abt_errno;
107 
108 fn_fail:
109  HANDLE_ERROR_FUNC_WITH_CODE(abt_errno);
110  goto fn_exit;
111 }
112 
113 static inline double convert_timespec_to_sec(const struct timespec *p_ts)
114 {
115  double secs;
116  secs = ((double)p_ts->tv_sec) + 1.0e-9 * ((double)p_ts->tv_nsec);
117  return secs;
118 }
119 
120 static inline void remove_unit(ABTI_cond *p_cond, ABTI_unit *p_unit)
121 {
122  if (p_unit->p_next == NULL)
123  return;
124 
125  ABTI_spinlock_acquire(&p_cond->lock);
126 
127  if (p_unit->p_next == NULL) {
128  ABTI_spinlock_release(&p_cond->lock);
129  return;
130  }
131 
132  /* If p_unit is still in the queue, we have to remove it. */
133  p_cond->num_waiters--;
134  if (p_cond->num_waiters == 0) {
135  p_cond->p_waiter_mutex = NULL;
136  p_cond->p_head = NULL;
137  p_cond->p_tail = NULL;
138  } else {
139  p_unit->p_prev->p_next = p_unit->p_next;
140  p_unit->p_next->p_prev = p_unit->p_prev;
141  if (p_unit == p_cond->p_head) {
142  p_cond->p_head = p_unit->p_next;
143  } else if (p_unit == p_cond->p_tail) {
144  p_cond->p_tail = p_unit->p_prev;
145  }
146  }
147 
148  ABTI_spinlock_release(&p_cond->lock);
149 
150  p_unit->p_prev = NULL;
151  p_unit->p_next = NULL;
152 }
153 
177  const struct timespec *abstime)
178 {
179  int abt_errno = ABT_SUCCESS;
180  ABTI_local *p_local = ABTI_local_get_local();
181  ABTI_cond *p_cond = ABTI_cond_get_ptr(cond);
182  ABTI_CHECK_NULL_COND_PTR(p_cond);
183  ABTI_mutex *p_mutex = ABTI_mutex_get_ptr(mutex);
184  ABTI_CHECK_NULL_MUTEX_PTR(p_mutex);
185 
186  double tar_time = convert_timespec_to_sec(abstime);
187 
188  ABTI_unit *p_unit;
189  ABTD_atomic_int32 ext_signal = ABTD_ATOMIC_INT32_STATIC_INITIALIZER(0);
190 
191  p_unit = (ABTI_unit *)ABTU_calloc(1, sizeof(ABTI_unit));
192  /* Check size if ext_signal can be stored in p_unit->handle.thread. */
193  ABTI_STATIC_ASSERT(sizeof(ext_signal) <= sizeof(p_unit->handle.thread));
194  p_unit->handle.thread = (ABT_thread)&ext_signal;
195  p_unit->type = ABT_UNIT_TYPE_EXT;
196 
197  ABTI_spinlock_acquire(&p_cond->lock);
198 
199  if (p_cond->p_waiter_mutex == NULL) {
200  p_cond->p_waiter_mutex = p_mutex;
201  } else {
202  ABT_bool result = ABTI_mutex_equal(p_cond->p_waiter_mutex, p_mutex);
203  if (result == ABT_FALSE) {
204  ABTI_spinlock_release(&p_cond->lock);
205  abt_errno = ABT_ERR_INV_MUTEX;
206  ABTU_free(p_unit);
207  goto fn_fail;
208  }
209  }
210 
211  if (p_cond->num_waiters == 0) {
212  p_unit->p_prev = p_unit;
213  p_unit->p_next = p_unit;
214  p_cond->p_head = p_unit;
215  p_cond->p_tail = p_unit;
216  } else {
217  p_cond->p_tail->p_next = p_unit;
218  p_cond->p_head->p_prev = p_unit;
219  p_unit->p_prev = p_cond->p_tail;
220  p_unit->p_next = p_cond->p_head;
221  p_cond->p_tail = p_unit;
222  }
223 
224  p_cond->num_waiters++;
225 
226  ABTI_spinlock_release(&p_cond->lock);
227 
228  /* Unlock the mutex that the calling ULT is holding */
229  ABTI_mutex_unlock(p_local, p_mutex);
230 
231  while (!ABTD_atomic_acquire_load_int32(&ext_signal)) {
232  double cur_time = ABTI_get_wtime();
233  if (cur_time >= tar_time) {
234  remove_unit(p_cond, p_unit);
235  abt_errno = ABT_ERR_COND_TIMEDOUT;
236  break;
237  }
238 #ifndef ABT_CONFIG_DISABLE_EXT_THREAD
239  if (ABTI_self_get_type(p_local) != ABT_UNIT_TYPE_THREAD) {
240  ABTD_atomic_pause();
241  continue;
242  }
243 #endif
244  ABTI_thread_yield(&p_local, p_local->p_thread);
245  }
246  ABTU_free(p_unit);
247 
248  /* Lock the mutex again */
249  ABTI_mutex_lock(&p_local, p_mutex);
250 
251 fn_exit:
252  return abt_errno;
253 
254 fn_fail:
255  HANDLE_ERROR_FUNC_WITH_CODE(abt_errno);
256  goto fn_exit;
257 }
258 
274 {
275  int abt_errno = ABT_SUCCESS;
276  ABTI_local *p_local = ABTI_local_get_local();
277  ABTI_cond *p_cond = ABTI_cond_get_ptr(cond);
278  ABTI_CHECK_NULL_COND_PTR(p_cond);
279 
280  ABTI_spinlock_acquire(&p_cond->lock);
281 
282  if (p_cond->num_waiters == 0) {
283  ABTI_spinlock_release(&p_cond->lock);
284  goto fn_exit;
285  }
286 
287  /* Wake up the first waiting ULT */
288  ABTI_unit *p_unit = p_cond->p_head;
289 
290  p_cond->num_waiters--;
291  if (p_cond->num_waiters == 0) {
292  p_cond->p_waiter_mutex = NULL;
293  p_cond->p_head = NULL;
294  p_cond->p_tail = NULL;
295  } else {
296  p_unit->p_prev->p_next = p_unit->p_next;
297  p_unit->p_next->p_prev = p_unit->p_prev;
298  p_cond->p_head = p_unit->p_next;
299  }
300  p_unit->p_prev = NULL;
301  p_unit->p_next = NULL;
302 
303  if (p_unit->type == ABT_UNIT_TYPE_THREAD) {
304  ABTI_thread *p_thread = ABTI_thread_get_ptr(p_unit->handle.thread);
305  ABTI_thread_set_ready(p_local, p_thread);
306  } else {
307  /* When the head is an external thread */
308  ABTD_atomic_int32 *p_ext_signal =
309  (ABTD_atomic_int32 *)p_unit->handle.thread;
310  ABTD_atomic_release_store_int32(p_ext_signal, 1);
311  }
312 
313  ABTI_spinlock_release(&p_cond->lock);
314 
315 fn_exit:
316  return abt_errno;
317 
318 fn_fail:
319  HANDLE_ERROR_FUNC_WITH_CODE(abt_errno);
320  goto fn_exit;
321 }
322 
337 {
338  int abt_errno = ABT_SUCCESS;
339  ABTI_local *p_local = ABTI_local_get_local();
340  ABTI_cond *p_cond = ABTI_cond_get_ptr(cond);
341  ABTI_CHECK_NULL_COND_PTR(p_cond);
342 
343  ABTI_cond_broadcast(p_local, p_cond);
344 
345 fn_exit:
346  return abt_errno;
347 
348 fn_fail:
349  HANDLE_ERROR_FUNC_WITH_CODE(abt_errno);
350  goto fn_exit;
351 }
#define ABT_ERR_INV_MUTEX
Definition: abt.h:84
int ABT_cond_create(ABT_cond *newcond)
Create a new condition variable.
Definition: cond.c:26
int ABT_cond_free(ABT_cond *cond)
Free the condition variable.
Definition: cond.c:52
#define ABT_ERR_COND_TIMEDOUT
Definition: abt.h:106
static void * ABTU_malloc(size_t size)
Definition: abtu.h:39
int ABT_bool
Definition: abt.h:309
int ABT_cond_timedwait(ABT_cond cond, ABT_mutex mutex, const struct timespec *abstime)
Wait on the condition.
Definition: cond.c:176
int ABT_cond_wait(ABT_cond cond, ABT_mutex mutex)
Wait on the condition.
Definition: cond.c:92
struct ABT_mutex_opaque * ABT_mutex
Definition: abt.h:293
#define ABT_FALSE
Definition: abt.h:224
struct ABT_thread_opaque * ABT_thread
Definition: abt.h:279
static void remove_unit(ABTI_cond *p_cond, ABTI_unit *p_unit)
Definition: cond.c:120
#define HANDLE_ERROR_FUNC_WITH_CODE(n)
Definition: abti_error.h:241
#define ABT_SUCCESS
Definition: abt.h:64
#define ABT_ERR_COND
Definition: abt.h:105
#define ABT_COND_NULL
Definition: abt.h:350
int ABT_cond_broadcast(ABT_cond cond)
Broadcast a condition.
Definition: cond.c:336
static double convert_timespec_to_sec(const struct timespec *p_ts)
Definition: cond.c:113
static void ABTU_free(void *ptr)
Definition: abtu.h:32
int ABT_cond_signal(ABT_cond cond)
Signal a condition.
Definition: cond.c:273
static void * ABTU_calloc(size_t num, size_t size)
Definition: abtu.h:49
struct ABT_cond_opaque * ABT_cond
Definition: abt.h:297