_WCRTLINK int sem_timedwait( sem_t *sem, const struct timespec *abstime ) { int ret; struct timespec reltime; if( sem == NULL ) { _RWD_errno = EINVAL; return( -1 ); } if( __decrement_if_positive( &sem->value ) ) return( 0 ); do { clock_gettime( CLOCK_MONOTONIC, &reltime ); reltime.tv_sec = abstime->tv_sec - reltime.tv_sec; reltime.tv_nsec = abstime->tv_nsec - reltime.tv_nsec; if(reltime.tv_nsec < 0) { reltime.tv_sec--; reltime.tv_nsec += 1E+9; } ret = __futex( &sem->value, FUTEX_WAIT_PRIVATE, 0, &reltime ); if(ret == -ETIMEDOUT) { _RWD_errno = ETIMEDOUT; return( -1 ); } } while( !__decrement_if_positive( &sem->value ) ); return( 0 ); }
_WCRTLINK int sem_wait( sem_t *sem ) { if( sem == NULL ) { _RWD_errno = EINVAL; return( -1 ); } if( __decrement_if_positive( &sem->value ) ) return( 0 ); do { __futex( &sem->value, FUTEX_WAIT_PRIVATE, 0, NULL ); } while( !__decrement_if_positive( &sem->value ) ); return( 0 ); }
_WCRTLINK int sem_trywait( sem_t *sem ) { struct timespec timer; int ret; if( sem == NULL ) { _RWD_errno = EINVAL; return( -1 ); } timer.tv_sec = 0; timer.tv_nsec = 0; if( __decrement_if_positive( &sem->value ) ) return( 0 ); do { ret = __futex( &sem->value, FUTEX_WAIT_PRIVATE, 0, &timer ); } while( ret == 0 && !__decrement_if_positive( &sem->value ) ); if( ret == 0 ) return( 0 ); _RWD_errno = EAGAIN; return( -1 ); }
int __futex_wake(volatile void *ftx, int count) { return __futex(ftx, FUTEX_WAKE, count, 0); }
// This used to be in <sys/atomics.h>. extern "C" int __futex_wait(volatile void* ftx, int value, const struct timespec* timeout) { return __futex(ftx, FUTEX_WAIT, value, timeout); }
// This used to be in <sys/atomics.h>. extern "C" int __futex_wake(volatile void* ftx, int count) { return __futex(ftx, FUTEX_WAKE, count, NULL); }