diff --git a/musl_src.gni b/musl_src.gni index 0c4e0182aad699f696c27fdda54635a2e7ac982c..4a953dded4108ce83c4d1b1de55fdac74217c9bb 100644 --- a/musl_src.gni +++ b/musl_src.gni @@ -2223,6 +2223,7 @@ musl_src_porting_file = [ "src/aio/aio.c", "src/misc/aarch64/syscall.s", "src/stdlib/strtod.c", + "src/thread/sem_timedwait.c", "src/stdio/vfscanf.c", "src/stdio/fileno.c", ] diff --git a/porting/linux/user/src/thread/sem_timedwait.c b/porting/linux/user/src/thread/sem_timedwait.c new file mode 100644 index 0000000000000000000000000000000000000000..a17dd96bd3165cb476eda0c0cd66ea833939c703 --- /dev/null +++ b/porting/linux/user/src/thread/sem_timedwait.c @@ -0,0 +1,34 @@ +#include +#include "pthread_impl.h" + +static void cleanup(void *p) +{ + a_dec(p); +} +int __sem_timedwait(sem_t *restrict sem, const struct timespec *restrict at) +{ + 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) { + errno = r; + return -1; + } + } + return 0; +} +int sem_timedwait(sem_t *restrict sem, const struct timespec *restrict at) +{ + pthread_testcancel(); + + if (!sem_trywait(sem)) return 0; + + return __sem_timedwait(sem, at); +}