ARGOBOTS  4dc37e16e1b227a480715ab67dae1dcfb4d2d4e0
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 
9 static inline double convert_timespec_to_sec(const struct timespec *p_ts);
10 
43 {
44  ABTI_UB_ASSERT(ABTI_initialized());
45  ABTI_UB_ASSERT(newcond);
46 
47  /* Check if the size of ABT_cond_memory is okay. */
48  ABTI_STATIC_ASSERT(sizeof(ABTI_cond) <= sizeof(ABT_cond_memory));
49 
50 #ifndef ABT_CONFIG_ENABLE_VER_20_API
51  /* Argobots 1.x sets newcond to NULL on error. */
52  *newcond = ABT_COND_NULL;
53 #endif
54  ABTI_cond *p_newcond;
55  int abt_errno = ABTU_malloc(sizeof(ABTI_cond), (void **)&p_newcond);
56  ABTI_CHECK_ERROR(abt_errno);
57 
58  ABTI_cond_init(p_newcond);
59  /* Return value */
60  *newcond = ABTI_cond_get_handle(p_newcond);
61  return ABT_SUCCESS;
62 }
63 
93 {
94  ABTI_UB_ASSERT(ABTI_initialized());
95  ABTI_UB_ASSERT(cond);
96 
97  ABT_cond h_cond = *cond;
98  ABTI_cond *p_cond = ABTI_cond_get_ptr(h_cond);
99  ABTI_CHECK_NULL_COND_PTR(p_cond);
100 #ifndef ABT_CONFIG_ENABLE_VER_20_API
101  /* This check will be removed in Argobots 2.0 */
102  ABTI_CHECK_TRUE(ABTI_waitlist_is_empty(&p_cond->waitlist), ABT_ERR_COND);
103 #else
104  ABTI_UB_ASSERT(ABTI_waitlist_is_empty(&p_cond->waitlist));
105 #endif
106 
107  ABTI_cond_fini(p_cond);
108  ABTU_free(p_cond);
109  /* Return value */
110  *cond = ABT_COND_NULL;
111  return ABT_SUCCESS;
112 }
113 
160 {
161  ABTI_local *p_local = ABTI_local_get_local();
162 #ifndef ABT_CONFIG_ENABLE_VER_20_API
163  /* Argobots 1.x does not allow a tasklet to call this routine. */
164  if (ABTI_IS_ERROR_CHECK_ENABLED && p_local) {
165  ABTI_xstream *p_local_xstream = ABTI_local_get_xstream(p_local);
166  ABTI_CHECK_TRUE(p_local_xstream->p_thread->type &
167  ABTI_THREAD_TYPE_YIELDABLE,
168  ABT_ERR_COND);
169  }
170 #endif
171  ABTI_cond *p_cond = ABTI_cond_get_ptr(cond);
172  ABTI_CHECK_NULL_COND_PTR(p_cond);
173  ABTI_mutex *p_mutex = ABTI_mutex_get_ptr(mutex);
174  ABTI_CHECK_NULL_MUTEX_PTR(p_mutex);
175 
176  /* Check if a given mutex is valid. */
177  /* p_mutex must be locked. */
178  ABTI_UB_ASSERT(ABTI_mutex_is_locked(p_mutex));
179  /* If p_mutex is recursive, the caller of this function must be an owner. */
180  ABTI_UB_ASSERT(!((p_mutex->attrs & ABTI_MUTEX_ATTR_RECURSIVE) &&
181  p_mutex->owner_id != ABTI_self_get_thread_id(p_local)));
182  /* If p_mutex is recursive, p_mutex must not be locked more than once. */
183  ABTI_UB_ASSERT(!((p_mutex->attrs & ABTI_MUTEX_ATTR_RECURSIVE) &&
184  p_mutex->nesting_cnt > 1));
185 
186  int abt_errno = ABTI_cond_wait(&p_local, p_cond, p_mutex);
187  ABTI_CHECK_ERROR(abt_errno);
188  return ABT_SUCCESS;
189 }
190 
246  const struct timespec *abstime)
247 {
248  ABTI_UB_ASSERT(abstime);
249 
250  ABTI_local *p_local = ABTI_local_get_local();
251  ABTI_cond *p_cond = ABTI_cond_get_ptr(cond);
252  ABTI_CHECK_NULL_COND_PTR(p_cond);
253  ABTI_mutex *p_mutex = ABTI_mutex_get_ptr(mutex);
254  ABTI_CHECK_NULL_MUTEX_PTR(p_mutex);
255 
256  /* Check if a given mutex is valid. */
257  /* p_mutex must be locked. */
258  ABTI_UB_ASSERT(ABTI_mutex_is_locked(p_mutex));
259  /* If p_mutex is recursive, the caller of this function must be an owner. */
260  ABTI_UB_ASSERT(!((p_mutex->attrs & ABTI_MUTEX_ATTR_RECURSIVE) &&
261  p_mutex->owner_id != ABTI_self_get_thread_id(p_local)));
262  /* If p_mutex is recursive, p_mutex must not be locked more than once. */
263  ABTI_UB_ASSERT(!((p_mutex->attrs & ABTI_MUTEX_ATTR_RECURSIVE) &&
264  p_mutex->nesting_cnt > 1));
265 
266  double tar_time = convert_timespec_to_sec(abstime);
267 
268  ABTI_thread thread;
269  thread.type = ABTI_THREAD_TYPE_EXT;
270  ABTD_atomic_relaxed_store_int(&thread.state, ABT_THREAD_STATE_BLOCKED);
271 
272  ABTD_spinlock_acquire(&p_cond->lock);
273 
274  if (p_cond->p_waiter_mutex == NULL) {
275  p_cond->p_waiter_mutex = p_mutex;
276  } else {
277  if (p_cond->p_waiter_mutex != p_mutex) {
278  ABTD_spinlock_release(&p_cond->lock);
279  ABTI_HANDLE_ERROR(ABT_ERR_INV_MUTEX);
280  }
281  }
282 
283  /* Unlock the mutex that the calling ULT is holding */
284  ABTI_mutex_unlock(p_local, p_mutex);
285  ABT_bool is_timedout =
286  ABTI_waitlist_wait_timedout_and_unlock(&p_local, &p_cond->waitlist,
287  &p_cond->lock, tar_time,
289  (void *)p_cond);
290  /* Lock the mutex again */
291  ABTI_mutex_lock(&p_local, p_mutex);
292  return is_timedout ? ABT_ERR_COND_TIMEDOUT : ABT_SUCCESS;
293 }
294 
315 {
316  ABTI_local *p_local = ABTI_local_get_local();
317  ABTI_cond *p_cond = ABTI_cond_get_ptr(cond);
318  ABTI_CHECK_NULL_COND_PTR(p_cond);
319 
320  ABTD_spinlock_acquire(&p_cond->lock);
321  ABTI_waitlist_signal(p_local, &p_cond->waitlist);
322  ABTD_spinlock_release(&p_cond->lock);
323 
324  return ABT_SUCCESS;
325 }
326 
347 {
348  ABTI_local *p_local = ABTI_local_get_local();
349  ABTI_cond *p_cond = ABTI_cond_get_ptr(cond);
350  ABTI_CHECK_NULL_COND_PTR(p_cond);
351 
352  ABTI_cond_broadcast(p_local, p_cond);
353  return ABT_SUCCESS;
354 }
355 
356 /*****************************************************************************/
357 /* Internal static functions */
358 /*****************************************************************************/
359 
360 static inline double convert_timespec_to_sec(const struct timespec *p_ts)
361 {
362  double secs;
363  secs = ((double)p_ts->tv_sec) + 1.0e-9 * ((double)p_ts->tv_nsec);
364  return secs;
365 }
ABT_bool
int ABT_bool
Boolean type.
Definition: abt.h:1043
ABT_cond_free
int ABT_cond_free(ABT_cond *cond)
Free a condition variable.
Definition: cond.c:92
ABT_cond_timedwait
int ABT_cond_timedwait(ABT_cond cond, ABT_mutex mutex, const struct timespec *abstime)
Wait on a condition variable with a timeout limit.
Definition: cond.c:245
ABT_COND_NULL
#define ABT_COND_NULL
Definition: abt.h:1111
ABT_ERR_COND
#define ABT_ERR_COND
Error code: error related to a condition variable.
Definition: abt.h:333
ABT_mutex
struct ABT_mutex_opaque * ABT_mutex
Mutex handle type.
Definition: abt.h:987
ABT_cond_memory
A struct that can be converted to ABT_cond.
Definition: abt.h:1216
ABT_ERR_INV_MUTEX
#define ABT_ERR_INV_MUTEX
Error code: invalid mutex.
Definition: abt.h:210
ABT_THREAD_STATE_BLOCKED
@ ABT_THREAD_STATE_BLOCKED
Definition: abt.h:431
abti.h
ABTU_malloc
static ABTU_ret_err int ABTU_malloc(size_t size, void **p_ptr)
Definition: abtu.h:235
ABT_SYNC_EVENT_TYPE_COND
@ ABT_SYNC_EVENT_TYPE_COND
Definition: abt.h:710
ABT_cond_create
int ABT_cond_create(ABT_cond *newcond)
Create a new condition variable.
Definition: cond.c:42
ABT_SUCCESS
#define ABT_SUCCESS
Error code: the routine returns successfully.
Definition: abt.h:92
ABT_cond_broadcast
int ABT_cond_broadcast(ABT_cond cond)
Broadcast a condition.
Definition: cond.c:346
convert_timespec_to_sec
static double convert_timespec_to_sec(const struct timespec *p_ts)
Definition: cond.c:360
ABT_cond_wait
int ABT_cond_wait(ABT_cond cond, ABT_mutex mutex)
Wait on a condition variable.
Definition: cond.c:159
ABT_ERR_COND_TIMEDOUT
#define ABT_ERR_COND_TIMEDOUT
Error code: a return value when a condition variable is timed out.
Definition: abt.h:340
ABTU_free
static void ABTU_free(void *ptr)
Definition: abtu.h:228
ABT_cond
struct ABT_cond_opaque * ABT_cond
Condition variable handle type.
Definition: abt.h:1001
ABT_cond_signal
int ABT_cond_signal(ABT_cond cond)
Signal a condition.
Definition: cond.c:314