@@ -4439,18 +4439,34 @@ pid_t getpid() {
44394439
44404440#ifdef INTERCEPT_SYSCALL
44414441#ifdef INTERCEPT_FUTEX
4442- long handle_futex_syscall (long number , uint32_t * uaddr , int futex_op , uint32_t val , struct timespec * timeout , uint32_t * uaddr2 , uint32_t val3 ) {
4442+ static inline long make_futex_syscall (long number , uint32_t * uaddr , int futex_op , uint32_t val , struct timespec * timeout , uint32_t * uaddr2 , uint32_t val3 ) {
44434443 if (timeout == NULL ) {
44444444 // not timeout related, just call the real syscall
4445+ return real_syscall (number , uaddr , futex_op , val , timeout , uaddr2 , val3 );
4446+ }
4447+ if (timeout -> tv_sec < 0 ) {
4448+ // fprintf(stderr, "libfaketime: invalid timeout.tv_sec < 0\n");
4449+ timeout -> tv_sec = 0 ;
4450+ }
4451+ if (timeout -> tv_nsec < 0 ) {
4452+ // fprintf(stderr, "libfaketime: invalid timeout.tv_nsec < 0\n");
4453+ timeout -> tv_nsec = 0 ;
4454+ }
4455+ return real_syscall (number , uaddr , futex_op , val , timeout , uaddr2 , val3 );
4456+ }
4457+
4458+ static inline long handle_futex_syscall (long number , uint32_t * uaddr , int futex_op , uint32_t val , struct timespec * timeout , uint32_t * uaddr2 , uint32_t val3 ) {
4459+ if (timeout == NULL ) {
44454460 goto futex_fallback ;
44464461 }
44474462
4448- // if ((futex_op & FUTEX_CMD_MASK) == FUTEX_WAIT_BITSET) {
4449- if (1 ) {
4450- clockid_t clk_id = CLOCK_MONOTONIC ;
4451- if (futex_op & FUTEX_CLOCK_REALTIME )
4452- clk_id = CLOCK_REALTIME ;
4463+ int futex_cmd = futex_op & FUTEX_CMD_MASK ;
4464+ clockid_t clk_id = CLOCK_MONOTONIC ;
4465+ if (futex_op & FUTEX_CLOCK_REALTIME )
4466+ clk_id = CLOCK_REALTIME ;
44534467
4468+ if (futex_cmd == FUTEX_WAIT_BITSET ) {
4469+ // FUTEX_WAIT_BITSET uses absolute timeout
44544470 struct timespec real_tp , fake_tp ;
44554471
44564472 DONT_FAKE_TIME ((* real_clock_gettime )(clk_id , & real_tp ));
@@ -4463,9 +4479,7 @@ long handle_futex_syscall(long number, uint32_t* uaddr, int futex_op, uint32_t v
44634479 struct timespec adjusted_timeout , time_diff ;
44644480 timespecsub (& fake_tp , & real_tp , & time_diff );
44654481 timespecsub (timeout , & time_diff , & adjusted_timeout );
4466- // fprintf(stdout, "libfaketime: adjusted timeout: %ld.%09ld\n", adjusted_timeout.tv_sec, adjusted_timeout.tv_nsec);
4467- long result ;
4468- result = real_syscall (number , uaddr , futex_op , val , & adjusted_timeout , uaddr2 , val3 );
4482+ long result = make_futex_syscall (number , uaddr , futex_op , val , & adjusted_timeout , uaddr2 , val3 );
44694483 if (result != 0 ) {
44704484 return result ;
44714485 }
@@ -4498,11 +4512,8 @@ long handle_futex_syscall(long number, uint32_t* uaddr, int futex_op, uint32_t v
44984512 struct timespec real_timeout ;
44994513 timespecadd (& real_now , & wait_time , & real_timeout );
45004514
4501- // fprintf(stdout, "libfaketime: recalculated real timeout: %ld.%09ld\n",
4502- // real_timeout.tv_sec, real_timeout.tv_nsec);
4503-
45044515 // Call the real syscall with the recalculated timeout
4505- result = real_syscall (number , uaddr , futex_op , val , & real_timeout , uaddr2 , val3 );
4516+ result = make_futex_syscall (number , uaddr , futex_op , val , & real_timeout , uaddr2 , val3 );
45064517 if (result != 0 ) {
45074518 return result ;
45084519 }
@@ -4513,12 +4524,24 @@ long handle_futex_syscall(long number, uint32_t* uaddr, int futex_op, uint32_t v
45134524 }
45144525 }
45154526 return 0 ;
4527+ } else if (futex_cmd == FUTEX_WAIT ) {
4528+ // FUTEX_WAIT uses relative timeout - scale by time rate
4529+ struct timespec adjusted_timeout ;
4530+
4531+ if (user_rate_set && !dont_fake && ((clk_id == CLOCK_REALTIME ) || (clk_id == CLOCK_MONOTONIC ))) {
4532+ timespecmul (timeout , 1.0 / user_rate , & adjusted_timeout );
4533+ } else {
4534+ adjusted_timeout = * timeout ;
4535+ }
4536+
4537+ return make_futex_syscall (number , uaddr , futex_op , val , & adjusted_timeout , uaddr2 , val3 );
45164538 } else {
4517- return real_syscall (number , uaddr , futex_op , val , timeout , uaddr2 , val3 );
4539+ // Other futex operations - pass through unchanged
4540+ goto futex_fallback ;
45184541 }
45194542
45204543 futex_fallback :
4521- return real_syscall (number , uaddr , futex_op , val , timeout , uaddr2 , val3 );
4544+ return make_futex_syscall (number , uaddr , futex_op , val , timeout , uaddr2 , val3 );
45224545}
45234546#endif
45244547
0 commit comments