6 #ifndef ABTI_WAITLIST_H_INCLUDED
7 #define ABTI_WAITLIST_H_INCLUDED
11 static inline void ABTI_waitlist_init(ABTI_waitlist *p_waitlist)
13 #ifndef ABT_CONFIG_ACTIVE_WAIT_POLICY
14 ABTD_futex_multiple_init(&p_waitlist->futex);
16 p_waitlist->p_head = NULL;
17 p_waitlist->p_tail = NULL;
21 ABTI_waitlist_wait_and_unlock(ABTI_local **pp_local, ABTI_waitlist *p_waitlist,
22 ABTD_spinlock *p_lock,
25 ABTI_ASSERT(ABTD_spinlock_is_locked(p_lock) ==
ABT_TRUE);
26 ABTI_ythread *p_ythread = NULL;
27 ABTI_xstream *p_local_xstream = ABTI_local_get_xstream_or_null(*pp_local);
28 if (!ABTI_IS_EXT_THREAD_ENABLED || p_local_xstream) {
29 p_ythread = ABTI_thread_get_ythread_or_null(p_local_xstream->p_thread);
34 thread.type = ABTI_THREAD_TYPE_EXT;
39 if (p_waitlist->p_head == NULL) {
40 p_waitlist->p_head = &thread;
42 p_waitlist->p_tail->p_next = &thread;
44 p_waitlist->p_tail = &thread;
47 #ifdef ABT_CONFIG_ACTIVE_WAIT_POLICY
48 ABTD_spinlock_release(p_lock);
49 while (ABTD_atomic_acquire_load_int(&thread.state) !=
56 if (ABTD_atomic_relaxed_load_int(&thread.state) ==
58 ABTD_spinlock_release(p_lock);
61 ABTD_futex_wait_and_unlock(&p_waitlist->futex, p_lock);
64 if (ABTD_atomic_acquire_load_int(&thread.state) ==
69 ABTD_spinlock_acquire(p_lock);
74 p_ythread->thread.p_next = NULL;
75 if (p_waitlist->p_head == NULL) {
76 p_waitlist->p_head = &p_ythread->thread;
78 p_waitlist->p_tail->p_next = &p_ythread->thread;
80 p_waitlist->p_tail = &p_ythread->thread;
83 ABTI_ythread_suspend_unlock(&p_local_xstream, p_ythread, p_lock,
84 sync_event_type, p_sync);
86 *pp_local = ABTI_xstream_get_local(p_local_xstream);
91 static inline ABT_bool ABTI_waitlist_wait_timedout_and_unlock(
92 ABTI_local **pp_local, ABTI_waitlist *p_waitlist, ABTD_spinlock *p_lock,
95 ABTI_ASSERT(ABTD_spinlock_is_locked(p_lock) ==
ABT_TRUE);
96 ABTI_ythread *p_ythread = NULL;
97 ABTI_xstream *p_local_xstream = ABTI_local_get_xstream_or_null(*pp_local);
98 if (!ABTI_IS_EXT_THREAD_ENABLED || p_local_xstream)
99 p_ythread = ABTI_thread_get_ythread_or_null(p_local_xstream->p_thread);
103 thread.type = ABTI_THREAD_TYPE_EXT;
110 thread.p_next = NULL;
111 if (p_waitlist->p_head == NULL) {
112 p_waitlist->p_head = &thread;
113 thread.p_prev = NULL;
115 p_waitlist->p_tail->p_next = &thread;
116 thread.p_prev = p_waitlist->p_tail;
118 p_waitlist->p_tail = &thread;
123 ABTD_spinlock_release(p_lock);
124 while (ABTD_atomic_acquire_load_int(&thread.state) !=
126 double cur_time = ABTI_get_wtime();
127 if (cur_time >= target_time) {
128 ABTD_spinlock_acquire(p_lock);
131 ABTI_ythread_yield(&p_local_xstream, p_ythread,
132 ABTI_YTHREAD_YIELD_KIND_YIELD_LOOP,
133 sync_event_type, p_sync);
134 *pp_local = ABTI_xstream_get_local(p_local_xstream);
138 #ifdef ABT_CONFIG_ACTIVE_WAIT_POLICY
139 ABTD_spinlock_release(p_lock);
140 while (ABTD_atomic_acquire_load_int(&thread.state) !=
142 double cur_time = ABTI_get_wtime();
143 if (cur_time >= target_time) {
144 ABTD_spinlock_acquire(p_lock);
150 double cur_time = ABTI_get_wtime();
151 if (cur_time >= target_time) {
156 if (ABTD_atomic_relaxed_load_int(&thread.state) ==
158 ABTD_spinlock_release(p_lock);
161 ABTD_futex_timedwait_and_unlock(&p_waitlist->futex, p_lock,
162 target_time - cur_time);
164 if (ABTD_atomic_acquire_load_int(&thread.state) ==
168 ABTD_spinlock_acquire(p_lock);
176 ABTI_ASSERT(ABTD_spinlock_is_locked(p_lock) ==
ABT_TRUE);
183 if (p_waitlist->p_head == &thread) {
188 p_waitlist->p_head = thread.p_next;
189 if (!thread.p_next) {
191 ABTI_ASSERT(p_waitlist->p_tail == &thread);
192 p_waitlist->p_tail = NULL;
196 ABTI_ASSERT(thread.p_prev);
197 thread.p_prev->p_next = thread.p_next;
198 if (thread.p_next && thread.type == ABTI_THREAD_TYPE_EXT) {
202 thread.p_next->p_prev = thread.p_prev;
205 ABTI_ASSERT(p_waitlist->p_tail == &thread);
206 p_waitlist->p_tail = thread.p_prev;
212 ABTD_spinlock_release(p_lock);
216 static inline void ABTI_waitlist_signal(ABTI_local *p_local,
217 ABTI_waitlist *p_waitlist)
219 ABTI_thread *p_thread = p_waitlist->p_head;
221 ABTI_thread *p_next = p_thread->p_next;
222 p_thread->p_next = NULL;
224 ABTI_ythread *p_ythread = ABTI_thread_get_ythread_or_null(p_thread);
226 ABTI_ythread_resume_and_push(p_local, p_ythread);
229 ABTD_atomic_release_store_int(&p_thread->state,
231 #ifndef ABT_CONFIG_ACTIVE_WAIT_POLICY
235 ABTD_futex_broadcast(&p_waitlist->futex);
240 p_waitlist->p_head = p_next;
242 p_waitlist->p_tail = NULL;
246 static inline void ABTI_waitlist_broadcast(ABTI_local *p_local,
247 ABTI_waitlist *p_waitlist)
249 ABTI_thread *p_thread = p_waitlist->p_head;
253 ABTI_thread *p_next = p_thread->p_next;
254 p_thread->p_next = NULL;
256 ABTI_ythread *p_ythread = ABTI_thread_get_ythread_or_null(p_thread);
258 ABTI_ythread_resume_and_push(p_local, p_ythread);
262 ABTD_atomic_release_store_int(&p_thread->state,
269 p_waitlist->p_head = NULL;
270 p_waitlist->p_tail = NULL;
271 #ifndef ABT_CONFIG_ACTIVE_WAIT_POLICY
272 if (wakeup_nonyieldable) {
273 ABTD_futex_broadcast(&p_waitlist->futex);
277 (void)wakeup_nonyieldable;
282 static inline ABT_bool ABTI_waitlist_is_empty(ABTI_waitlist *p_waitlist)