Index: fusl/src/thread/sem_timedwait.c |
diff --git a/fusl/src/thread/sem_timedwait.c b/fusl/src/thread/sem_timedwait.c |
new file mode 100644 |
index 0000000000000000000000000000000000000000..8132eb1bf7a276d9b2dd2c9c978bbc0f0b29b7f4 |
--- /dev/null |
+++ b/fusl/src/thread/sem_timedwait.c |
@@ -0,0 +1,31 @@ |
+#include <semaphore.h> |
+#include "pthread_impl.h" |
+ |
+static void cleanup(void *p) |
+{ |
+ a_dec(p); |
+} |
+ |
+int sem_timedwait(sem_t *restrict sem, const struct timespec *restrict at) |
+{ |
+ pthread_testcancel(); |
+ |
+ if (!sem_trywait(sem)) return 0; |
+ |
+ int spins = 100; |
+ while (spins-- && sem->__val[0] <= 0 && !sem->__val[1]) a_spin(); |
+ |
+ while (sem_trywait(sem)) { |
+ int r; |
+ a_inc(sem->__val+1); |
+ a_cas(sem->__val, 0, -1); |
+ pthread_cleanup_push(cleanup, (void *)(sem->__val+1)); |
+ r = __timedwait_cp(sem->__val, -1, CLOCK_REALTIME, at, sem->__val[2]); |
+ pthread_cleanup_pop(1); |
+ if (r && r != EINTR) { |
+ errno = r; |
+ return -1; |
+ } |
+ } |
+ return 0; |
+} |