@@ -362,6 +362,71 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
362362 interp_ok ( Scalar :: from_i32 ( 0 ) )
363363 }
364364
365+ fn clock_nanosleep (
366+ & mut self ,
367+ clock_id : & OpTy < ' tcx > ,
368+ flags : & OpTy < ' tcx > ,
369+ req_op : & OpTy < ' tcx > ,
370+ _rem : & OpTy < ' tcx > , // Signal handlers are not supported, so rem will never be written to.
371+ ) -> InterpResult < ' tcx , Scalar > {
372+ let this = self . eval_context_mut ( ) ;
373+
374+ let clock_id: libc:: clockid_t = this. read_scalar ( clock_id) ?. to_i32 ( ) ?;
375+ match clock_id {
376+ libc:: CLOCK_MONOTONIC => ( ) ,
377+ libc:: CLOCK_REALTIME
378+ | libc:: CLOCK_TAI
379+ | libc:: CLOCK_BOOTTIME
380+ | libc:: CLOCK_PROCESS_CPUTIME_ID => {
381+ // The standard lib through sleep_until only needs CLOCK_MONOTONIC
382+ panic ! ( "MIRI only supports CLOCK_MONOTONIC for clock_nanosleep" )
383+ }
384+ _other => return this. set_last_error_and_return_i32 ( LibcError ( "EINVAL" ) ) ,
385+ }
386+
387+ let req = this. deref_pointer_as ( req_op, this. libc_ty_layout ( "timespec" ) ) ?;
388+ let duration = match this. read_timespec ( & req) ? {
389+ Some ( duration) => duration,
390+ None => {
391+ return this. set_last_error_and_return_i32 ( LibcError ( "EINVAL" ) ) ;
392+ }
393+ } ;
394+
395+ let flags: libc:: c_int = this. read_scalar ( flags) ?. to_i32 ( ) ?;
396+ if flags == 0 {
397+ this. block_thread (
398+ BlockReason :: Sleep ,
399+ Some ( ( TimeoutClock :: Monotonic , TimeoutAnchor :: Relative , duration) ) ,
400+ callback ! (
401+ @capture<' tcx> { }
402+ |_this, unblock: UnblockKind | {
403+ assert_eq!( unblock, UnblockKind :: TimedOut ) ;
404+ interp_ok( ( ) )
405+ }
406+ ) ,
407+ ) ;
408+ interp_ok ( Scalar :: from_i32 ( 0 ) )
409+ } else if flags == libc:: TIMER_ABSTIME {
410+ this. block_thread (
411+ BlockReason :: Sleep ,
412+ Some ( ( TimeoutClock :: Monotonic , TimeoutAnchor :: Absolute , duration) ) ,
413+ // PR Author review note: no idea what this does, I copied it
414+ // form nanosleep, please check carefully if it is correct
415+ callback ! (
416+ @capture<' tcx> { }
417+ |_this, unblock: UnblockKind | {
418+ assert_eq!( unblock, UnblockKind :: TimedOut ) ;
419+ interp_ok( ( ) )
420+ }
421+ ) ,
422+ ) ;
423+ interp_ok ( Scalar :: from_i32 ( 0 ) )
424+ } else {
425+ // The standard lib through sleep_until only needs TIMER_ABSTIME
426+ panic ! ( "MIRI only supports no flags (0) or flag TIMER_ABSTIME for clock_nanosleep" )
427+ }
428+ }
429+
365430 #[ allow( non_snake_case) ]
366431 fn Sleep ( & mut self , timeout : & OpTy < ' tcx > ) -> InterpResult < ' tcx > {
367432 let this = self . eval_context_mut ( ) ;
0 commit comments