3030#include <stdfil.h>
3131#include <pizlonated_syscalls.h>
3232#include <pizlonated_runtime.h>
33+ #include <linux/futex.h>
34+ #include <linux/time.h>
3335
3436unsigned zversion (void )
3537{
@@ -465,15 +467,11 @@ struct futex_args {
465467 volatile void * uaddr ;
466468 long futex_op ;
467469 unsigned long val ;
468- const void * timeout ;
470+ const struct timespec * timeout ;
469471 volatile void * uaddr2 ;
470472 unsigned long val3 ;
471473};
472474
473- #define FUTEX_WAIT 0
474- #define FUTEX_WAKE 1
475- #define FUTEX_PRIVATE 128
476-
477475long zsys_syscall (long n , ...)
478476{
479477 /* The goal is to have this code support all syscalls, but it doesn't do that, yet. So,
@@ -493,13 +491,38 @@ long zsys_syscall(long n, ...)
493491 struct futex_args * args = (struct futex_args * )syscall_args ;
494492 switch (args -> futex_op ) {
495493 case FUTEX_WAIT :
496- case FUTEX_WAIT | FUTEX_PRIVATE :
497- ZASSERT (!args -> timeout );
498- zsys_futex_wait (args -> uaddr , args -> val , args -> futex_op & FUTEX_PRIVATE );
494+ case FUTEX_WAIT | FUTEX_PRIVATE_FLAG :
495+ case FUTEX_WAIT | FUTEX_CLOCK_REALTIME :
496+ case FUTEX_WAIT | FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME :
497+ case FUTEX_WAIT_BITSET :
498+ case FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG :
499+ case FUTEX_WAIT_BITSET | FUTEX_CLOCK_REALTIME :
500+ case FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME : {
501+ if (args -> futex_op & FUTEX_WAIT_BITSET )
502+ ZASSERT (args -> val3 == FUTEX_BITSET_MATCH_ANY );
503+ int clock_id = (args -> futex_op & FUTEX_CLOCK_REALTIME ) ? CLOCK_REALTIME : CLOCK_MONOTONIC ;
504+ struct timespec timeout = {};
505+ if (args -> timeout ) {
506+ if (!(args -> futex_op & FUTEX_WAIT_BITSET ))
507+ zsys_clock_gettime (clock_id , & timeout );
508+ timeout .tv_sec += args -> timeout -> tv_sec ;
509+ timeout .tv_nsec += args -> timeout -> tv_nsec ;
510+ if (timeout .tv_nsec >= 1000000000 ) {
511+ timeout .tv_sec ++ ;
512+ timeout .tv_nsec -= 1000000000 ;
513+ }
514+ }
515+ int err = zsys_futex_timedwait (args -> uaddr , args -> val , clock_id ,
516+ args -> timeout ? & timeout : 0 , args -> futex_op & FUTEX_PRIVATE_FLAG );
517+ if (err > 0 ) {
518+ zset_errno (err );
519+ return -1 ;
520+ }
499521 return 0 ;
522+ }
500523 case FUTEX_WAKE :
501- case FUTEX_WAKE | FUTEX_PRIVATE :
502- zsys_futex_wake (args -> uaddr , args -> val , args -> futex_op & FUTEX_PRIVATE );
524+ case FUTEX_WAKE | FUTEX_PRIVATE_FLAG :
525+ zsys_futex_wake (args -> uaddr , args -> val , args -> futex_op & FUTEX_PRIVATE_FLAG );
503526 return 0 ;
504527 default :
505528 zerrorf ("unsupported futex op: %d." , args -> futex_op );
0 commit comments