8 #ifndef ABT_CONFIG_ACTIVE_WAIT_POLICY
10 #ifdef ABT_CONFIG_USE_LINUX_FUTEX
14 #include <linux/futex.h>
17 void ABTD_futex_wait_and_unlock(ABTD_futex_multiple *p_futex,
18 ABTD_spinlock *p_lock)
20 const int original_val = ABTD_atomic_relaxed_load_int(&p_futex->val);
21 ABTD_spinlock_release(p_lock);
23 syscall(SYS_futex, &p_futex->val.val, FUTEX_WAIT_PRIVATE, original_val,
25 }
while (ABTD_atomic_relaxed_load_int(&p_futex->val) == original_val);
28 void ABTD_futex_timedwait_and_unlock(ABTD_futex_multiple *p_futex,
29 ABTD_spinlock *p_lock,
32 const int original_val = ABTD_atomic_relaxed_load_int(&p_futex->val);
33 ABTD_spinlock_release(p_lock);
34 struct timespec wait_time;
35 wait_time.tv_sec = (time_t)wait_time_sec;
37 (long)((wait_time_sec - (
double)(time_t)wait_time_sec) * 1.0e9);
38 syscall(SYS_futex, &p_futex->val.val, FUTEX_WAIT_PRIVATE, original_val,
42 void ABTD_futex_broadcast(ABTD_futex_multiple *p_futex)
44 int current_val = ABTD_atomic_relaxed_load_int(&p_futex->val);
45 ABTD_atomic_relaxed_store_int(&p_futex->val, current_val + 1);
46 syscall(SYS_futex, &p_futex->val.val, FUTEX_WAKE_PRIVATE, INT_MAX, NULL,
50 void ABTD_futex_suspend(ABTD_futex_single *p_futex)
53 while (ABTD_atomic_acquire_load_int(&p_futex->val) == 0) {
54 syscall(SYS_futex, &p_futex->val.val, FUTEX_WAIT_PRIVATE, 0, NULL, NULL,
60 void ABTD_futex_resume(ABTD_futex_single *p_futex)
62 ABTI_ASSERT(ABTD_atomic_relaxed_load_int(&p_futex->val) == 0);
64 ABTD_atomic_release_store_int(&p_futex->val, 1);
65 syscall(SYS_futex, &p_futex->val.val, FUTEX_WAKE_PRIVATE, 1, NULL, NULL, 0);
81 #define PTHREAD_SYNC_STATIC_INITIALIZER \
83 PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, NULL, NULL, \
84 ABTD_ATOMIC_INT_STATIC_INITIALIZER(0), \
87 void ABTD_futex_wait_and_unlock(ABTD_futex_multiple *p_futex,
88 ABTD_spinlock *p_lock)
91 pthread_mutex_lock(&sync_obj.
mutex);
98 p_futex->
p_next = (
void *)&sync_obj;
99 ABTD_spinlock_release(p_lock);
100 while (ABTD_atomic_relaxed_load_int(&sync_obj.
val) == 0) {
101 pthread_cond_wait(&sync_obj.
cond, &sync_obj.
mutex);
105 pthread_mutex_unlock(&sync_obj.
mutex);
113 pthread_cond_destroy(&sync_obj.
cond);
114 pthread_mutex_destroy(&sync_obj.
mutex);
117 void ABTD_futex_timedwait_and_unlock(ABTD_futex_multiple *p_futex,
118 ABTD_spinlock *p_lock,
119 double wait_time_sec)
123 struct timespec wait_time;
124 clock_gettime(CLOCK_REALTIME, &wait_time);
125 wait_time.tv_sec += (time_t)wait_time_sec;
127 (long)((wait_time_sec - (
double)(time_t)wait_time_sec) * 1.0e9);
128 if (wait_time.tv_nsec >= 1e9) {
129 wait_time.tv_sec += 1;
130 wait_time.tv_nsec -= 1e9;
132 pthread_mutex_lock(&sync_obj.
mutex);
137 p_next->
p_prev = &sync_obj;
139 p_futex->
p_next = (
void *)&sync_obj;
140 ABTD_spinlock_release(p_lock);
141 pthread_cond_timedwait(&sync_obj.
cond, &sync_obj.
mutex, &wait_time);
145 pthread_mutex_unlock(&sync_obj.
mutex);
147 if (ABTD_atomic_acquire_load_int(&sync_obj.
val) != 0) {
154 ABTD_spinlock_acquire(p_lock);
156 if (ABTD_atomic_acquire_load_int(&sync_obj.
val) == 0) {
159 if (p_futex->p_next == (
void *)&sync_obj) {
160 p_futex->p_next = (
void *)sync_obj.p_next;
162 ABTI_ASSERT(sync_obj.p_prev);
163 sync_obj.p_prev->p_next = sync_obj.p_next;
164 sync_obj.p_next->p_prev = sync_obj.p_prev;
167 ABTD_spinlock_release(p_lock);
170 pthread_cond_destroy(&sync_obj.
cond);
171 pthread_mutex_destroy(&sync_obj.
mutex);
174 void ABTD_futex_broadcast(ABTD_futex_multiple *p_futex)
180 pthread_mutex_lock(&p_cur->
mutex);
181 ABTD_atomic_relaxed_store_int(&p_cur->
val, 1);
182 pthread_cond_broadcast(&p_cur->
cond);
183 pthread_mutex_unlock(&p_cur->
mutex);
191 void ABTD_futex_suspend(ABTD_futex_single *p_futex)
193 if (ABTD_atomic_acquire_load_ptr(&p_futex->p_sync_obj) != NULL) {
198 pthread_mutex_lock(&sync_obj.
mutex);
201 if (ABTD_atomic_bool_cas_strong_ptr(&p_futex->p_sync_obj, NULL,
202 (
void *)&sync_obj)) {
205 while (ABTD_atomic_relaxed_load_int(&sync_obj.val) == 0)
206 pthread_cond_wait(&sync_obj.cond, &sync_obj.mutex);
210 pthread_mutex_unlock(&sync_obj.mutex);
212 pthread_cond_destroy(&sync_obj.cond);
213 pthread_mutex_destroy(&sync_obj.mutex);
216 void ABTD_futex_resume(ABTD_futex_single *p_futex)
219 (
pthread_sync *)ABTD_atomic_acquire_load_ptr(&p_futex->p_sync_obj);
222 void *invalid_ptr = (
void *)((intptr_t)1);
223 void *ret_val = ABTD_atomic_val_cas_strong_ptr(&p_futex->p_sync_obj,
225 if (ret_val == NULL) {
233 pthread_mutex_lock(&p_sync_obj->
mutex);
236 ABTD_atomic_relaxed_store_int(&p_sync_obj->
val, 1);
237 pthread_cond_signal(&p_sync_obj->
cond);
238 pthread_mutex_unlock(&p_sync_obj->
mutex);