ARGOBOTS  1059a7c2eb7e3f99f736a9c3a4f6ea476ac1b804
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups
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 static inline void remove_thread(ABTI_cond *p_cond, ABTI_thread *p_thread);
11 
30 {
31  ABTI_cond *p_newcond;
32  int abt_errno = ABTU_malloc(sizeof(ABTI_cond), (void **)&p_newcond);
33  ABTI_CHECK_ERROR(abt_errno);
34 
35  ABTI_cond_init(p_newcond);
36  /* Return value */
37  *newcond = ABTI_cond_get_handle(p_newcond);
38  return ABT_SUCCESS;
39 }
40 
54 {
55  ABT_cond h_cond = *cond;
56  ABTI_cond *p_cond = ABTI_cond_get_ptr(h_cond);
59 
60  ABTI_cond_fini(p_cond);
61  ABTU_free(p_cond);
62  /* Return value */
63  *cond = ABT_COND_NULL;
64  return ABT_SUCCESS;
65 }
66 
85 {
86  ABTI_local *p_local = ABTI_local_get_local();
87  ABTI_cond *p_cond = ABTI_cond_get_ptr(cond);
89  ABTI_mutex *p_mutex = ABTI_mutex_get_ptr(mutex);
91 
92  int abt_errno = ABTI_cond_wait(&p_local, p_cond, p_mutex);
93  ABTI_CHECK_ERROR(abt_errno);
94  return ABT_SUCCESS;
95 }
96 
120  const struct timespec *abstime)
121 {
122  ABTI_local *p_local = ABTI_local_get_local();
123  ABTI_cond *p_cond = ABTI_cond_get_ptr(cond);
124  ABTI_CHECK_NULL_COND_PTR(p_cond);
125  ABTI_mutex *p_mutex = ABTI_mutex_get_ptr(mutex);
126  ABTI_CHECK_NULL_MUTEX_PTR(p_mutex);
127 
128  double tar_time = convert_timespec_to_sec(abstime);
129 
130  ABTI_thread thread;
131  thread.type = ABTI_THREAD_TYPE_EXT;
133 
134  ABTI_spinlock_acquire(&p_cond->lock);
135 
136  if (p_cond->p_waiter_mutex == NULL) {
137  p_cond->p_waiter_mutex = p_mutex;
138  } else {
139  if (p_cond->p_waiter_mutex != p_mutex) {
140  ABTI_spinlock_release(&p_cond->lock);
142  }
143  }
144 
145  if (p_cond->num_waiters == 0) {
146  thread.p_prev = &thread;
147  thread.p_next = &thread;
148  p_cond->p_head = &thread;
149  p_cond->p_tail = &thread;
150  } else {
151  p_cond->p_tail->p_next = &thread;
152  p_cond->p_head->p_prev = &thread;
153  thread.p_prev = p_cond->p_tail;
154  thread.p_next = p_cond->p_head;
155  p_cond->p_tail = &thread;
156  }
157 
158  p_cond->num_waiters++;
159 
160  ABTI_spinlock_release(&p_cond->lock);
161 
162  /* Unlock the mutex that the calling ULT is holding */
163  ABTI_mutex_unlock(p_local, p_mutex);
164 
165  ABTI_xstream *p_local_xstream = ABTI_local_get_xstream_or_null(p_local);
166  ABTI_ythread *p_ythread = NULL;
167  if (!ABTI_IS_EXT_THREAD_ENABLED || p_local_xstream) {
168  p_ythread = ABTI_thread_get_ythread_or_null(p_local_xstream->p_thread);
169  }
170  while (ABTD_atomic_acquire_load_int(&thread.state) !=
172  double cur_time = ABTI_get_wtime();
173  if (cur_time >= tar_time) {
174  remove_thread(p_cond, &thread);
175  /* Lock the mutex again */
176  ABTI_mutex_lock(&p_local, p_mutex);
177  return ABT_ERR_COND_TIMEDOUT;
178  }
179  if (p_ythread) {
180  ABTI_ythread_yield(&p_local_xstream, p_ythread,
181  ABT_SYNC_EVENT_TYPE_COND, (void *)p_cond);
182  p_local = ABTI_xstream_get_local(p_local_xstream);
183  } else {
185  }
186  }
187  /* Lock the mutex again */
188  ABTI_mutex_lock(&p_local, p_mutex);
189  return ABT_SUCCESS;
190 }
191 
207 {
208  ABTI_local *p_local = ABTI_local_get_local();
209  ABTI_cond *p_cond = ABTI_cond_get_ptr(cond);
210  ABTI_CHECK_NULL_COND_PTR(p_cond);
211 
212  ABTI_spinlock_acquire(&p_cond->lock);
213 
214  if (p_cond->num_waiters == 0) {
215  ABTI_spinlock_release(&p_cond->lock);
216  return ABT_SUCCESS;
217  }
218 
219  /* Wake up the first waiting ULT */
220  ABTI_thread *p_thread = p_cond->p_head;
221 
222  p_cond->num_waiters--;
223  if (p_cond->num_waiters == 0) {
224  p_cond->p_waiter_mutex = NULL;
225  p_cond->p_head = NULL;
226  p_cond->p_tail = NULL;
227  } else {
228  p_thread->p_prev->p_next = p_thread->p_next;
229  p_thread->p_next->p_prev = p_thread->p_prev;
230  p_cond->p_head = p_thread->p_next;
231  }
232  p_thread->p_prev = NULL;
233  p_thread->p_next = NULL;
234 
235  ABTI_ythread *p_ythread = ABTI_thread_get_ythread_or_null(p_thread);
236  if (p_ythread) {
237  ABTI_ythread_set_ready(p_local, p_ythread);
238  } else {
239  /* When the head is an external thread */
241  }
242 
243  ABTI_spinlock_release(&p_cond->lock);
244  return ABT_SUCCESS;
245 }
246 
261 {
262  ABTI_local *p_local = ABTI_local_get_local();
263  ABTI_cond *p_cond = ABTI_cond_get_ptr(cond);
264  ABTI_CHECK_NULL_COND_PTR(p_cond);
265 
266  ABTI_cond_broadcast(p_local, p_cond);
267  return ABT_SUCCESS;
268 }
269 
270 /*****************************************************************************/
271 /* Internal static functions */
272 /*****************************************************************************/
273 
274 static inline double convert_timespec_to_sec(const struct timespec *p_ts)
275 {
276  double secs;
277  secs = ((double)p_ts->tv_sec) + 1.0e-9 * ((double)p_ts->tv_nsec);
278  return secs;
279 }
280 
281 static inline void remove_thread(ABTI_cond *p_cond, ABTI_thread *p_thread)
282 {
283  if (p_thread->p_next == NULL)
284  return;
285 
286  ABTI_spinlock_acquire(&p_cond->lock);
287 
288  if (p_thread->p_next == NULL) {
289  ABTI_spinlock_release(&p_cond->lock);
290  return;
291  }
292 
293  /* If p_thread is still in the queue, we have to remove it. */
294  p_cond->num_waiters--;
295  if (p_cond->num_waiters == 0) {
296  p_cond->p_waiter_mutex = NULL;
297  p_cond->p_head = NULL;
298  p_cond->p_tail = NULL;
299  } else {
300  p_thread->p_prev->p_next = p_thread->p_next;
301  p_thread->p_next->p_prev = p_thread->p_prev;
302  if (p_thread == p_cond->p_head) {
303  p_cond->p_head = p_thread->p_next;
304  } else if (p_thread == p_cond->p_tail) {
305  p_cond->p_tail = p_thread->p_prev;
306  }
307  }
308 
309  ABTI_spinlock_release(&p_cond->lock);
310 
311  p_thread->p_prev = NULL;
312  p_thread->p_next = NULL;
313 }
ABTI_spinlock lock
Definition: abti.h:377
static ABTI_ythread * ABTI_thread_get_ythread_or_null(ABTI_thread *p_thread)
Definition: abti_thread.h:59
#define ABT_ERR_INV_MUTEX
Definition: abt.h:84
static void ABTI_cond_fini(ABTI_cond *p_cond)
Definition: abti_cond.h:22
int ABT_cond_create(ABT_cond *newcond) ABT_API_PUBLIC
Create a new condition variable.
Definition: cond.c:29
ABTI_thread * p_head
Definition: abti.h:380
static ABTI_cond * ABTI_cond_get_ptr(ABT_cond cond)
Definition: abti_cond.h:30
ABTI_thread * p_prev
Definition: abti.h:313
struct ABTI_local ABTI_local
Definition: abti.h:101
int ABT_cond_free(ABT_cond *cond) ABT_API_PUBLIC
Free the condition variable.
Definition: cond.c:53
static void ABTD_atomic_release_store_int(ABTD_atomic_int *ptr, int val)
Definition: abtd_atomic.h:924
ABTI_thread_type type
Definition: abti.h:316
static void ABTI_cond_init(ABTI_cond *p_cond)
Definition: abti_cond.h:13
#define ABT_ERR_COND_TIMEDOUT
Definition: abt.h:107
ABTI_thread * p_thread
Definition: abti.h:251
size_t num_waiters
Definition: abti.h:379
static void ABTI_mutex_lock(ABTI_local **pp_local, ABTI_mutex *p_mutex)
Definition: abti_mutex.h:75
ABTI_thread * p_tail
Definition: abti.h:381
static void ABTI_mutex_unlock(ABTI_local *p_local, ABTI_mutex *p_mutex)
Definition: abti_mutex.h:143
int ABT_cond_timedwait(ABT_cond cond, ABT_mutex mutex, const struct timespec *abstime) ABT_API_PUBLIC
Wait on the condition.
Definition: cond.c:119
int ABT_cond_wait(ABT_cond cond, ABT_mutex mutex) ABT_API_PUBLIC
Wait on the condition.
Definition: cond.c:84
struct ABT_mutex_opaque * ABT_mutex
Definition: abt.h:357
#define ABTI_CHECK_NULL_COND_PTR(p)
Definition: abti_error.h:256
static ABTU_ret_err int ABTU_malloc(size_t size, void **p_ptr)
Definition: abtu.h:129
#define ABTI_CHECK_NULL_MUTEX_PTR(p)
Definition: abti_error.h:238
#define ABTI_CHECK_TRUE(cond, abt_errno)
Definition: abti_error.h:137
ABTD_atomic_int state
Definition: abti.h:322
#define ABTI_IS_EXT_THREAD_ENABLED
Definition: abti.h:28
static ABTU_ret_err int ABTI_cond_wait(ABTI_local **pp_local, ABTI_cond *p_cond, ABTI_mutex *p_mutex)
Definition: abti_cond.h:61
static void ABTI_spinlock_release(ABTI_spinlock *p_lock)
Definition: abti_spinlock.h:31
static ABT_cond ABTI_cond_get_handle(ABTI_cond *p_cond)
Definition: abti_cond.h:45
#define ABT_SUCCESS
Definition: abt.h:64
static void ABTI_cond_broadcast(ABTI_local *p_local, ABTI_cond *p_cond)
Definition: abti_cond.h:139
static void remove_thread(ABTI_cond *p_cond, ABTI_thread *p_thread)
Definition: cond.c:281
static void ABTI_spinlock_acquire(ABTI_spinlock *p_lock)
Definition: abti_spinlock.h:23
static double ABTI_get_wtime(void)
Definition: abti_timer.h:11
ABTI_mutex * p_waiter_mutex
Definition: abti.h:378
#define ABT_ERR_COND
Definition: abt.h:106
static void ABTD_atomic_pause(void)
Definition: abtd_atomic.h:1091
#define ABT_COND_NULL
Definition: abt.h:421
int ABT_cond_broadcast(ABT_cond cond) ABT_API_PUBLIC
Broadcast a condition.
Definition: cond.c:260
#define ABTI_CHECK_ERROR(abt_errno)
Definition: abti_error.h:127
static void ABTD_atomic_relaxed_store_int(ABTD_atomic_int *ptr, int val)
Definition: abtd_atomic.h:865
static double convert_timespec_to_sec(const struct timespec *p_ts)
Definition: cond.c:274
ABTI_thread * p_next
Definition: abti.h:314
static ABTI_mutex * ABTI_mutex_get_ptr(ABT_mutex mutex)
Definition: abti_mutex.h:9
static void ABTI_ythread_yield(ABTI_xstream **pp_local_xstream, ABTI_ythread *p_ythread, ABT_sync_event_type sync_event_type, void *p_sync)
Definition: abti_ythread.h:350
static int ABTD_atomic_acquire_load_int(const ABTD_atomic_int *ptr)
Definition: abtd_atomic.h:763
void ABTI_ythread_set_ready(ABTI_local *p_local, ABTI_ythread *p_ythread)
Definition: ythread.c:50
static ABTI_local * ABTI_xstream_get_local(ABTI_xstream *p_xstream)
Definition: abti_stream.h:67
static ABTI_local * ABTI_local_get_local(void)
Definition: abti_local.h:41
static void ABTU_free(void *ptr)
Definition: abtu.h:122
#define ABTI_THREAD_TYPE_EXT
Definition: abti.h:72
static ABTI_xstream * ABTI_local_get_xstream_or_null(ABTI_local *p_local)
Definition: abti_local.h:77
#define ABTI_HANDLE_ERROR(n)
Definition: abti_error.h:121
int ABT_cond_signal(ABT_cond cond) ABT_API_PUBLIC
Signal a condition.
Definition: cond.c:206
struct ABT_cond_opaque * ABT_cond
Definition: abt.h:361