From 709594f0fb29d4f860b99cda264ea3e74c635a72 Mon Sep 17 00:00:00 2001 From: Gedare Bloom Date: Mon, 1 Aug 2016 16:54:18 -0400 Subject: posix: nanosleep: adjust elapsed time calculation Use clock_gettime before and after sleep to calculate the time spent asleep, and the amount of time remaining. updates #2732 --- cpukit/posix/src/nanosleep.c | 78 ++++++++++++++++++++++---------------------- 1 file changed, 39 insertions(+), 39 deletions(-) (limited to 'cpukit/posix/src') diff --git a/cpukit/posix/src/nanosleep.c b/cpukit/posix/src/nanosleep.c index 05d559a83a..38a6b8d6c8 100644 --- a/cpukit/posix/src/nanosleep.c +++ b/cpukit/posix/src/nanosleep.c @@ -33,21 +33,19 @@ static Thread_queue_Control _Nanosleep_Pseudo_queue = THREAD_QUEUE_INITIALIZER( "Nanosleep" ); static inline int nanosleep_helper( + clockid_t clock_id, uint64_t ticks, - Watchdog_Interval relative_interval, + struct timespec *timeout, struct timespec *rmtp, Watchdog_Discipline discipline ) { Thread_Control *executing; - - Watchdog_Interval start; - Watchdog_Interval elapsed; + struct timespec stop; + int err = 0; executing = _Thread_Get_executing(); - start = _Watchdog_Ticks_since_boot; - /* * Block for the desired amount of time */ @@ -61,35 +59,24 @@ static inline int nanosleep_helper( 1 ); - /* - * Calculate the time that passed while we were sleeping and how - * much remains from what we requested. - */ - elapsed = _Watchdog_Ticks_since_boot - start; - if ( elapsed >= relative_interval ) - relative_interval = 0; - else - relative_interval -= elapsed; - + clock_gettime( clock_id, &stop ); /* * If the user wants the time remaining, do the conversion. */ - if ( rmtp ) { - _Timespec_From_ticks( relative_interval, rmtp ); - } - - /* - * Only when POSIX is enabled, can a sleep be interrupted. - */ - #if defined(RTEMS_POSIX_API) + if ( _Timespec_Less_than( &stop, timeout ) ) { /* * If there is time remaining, then we were interrupted by a signal. */ - if ( relative_interval ) - return EINTR; - #endif + err = EINTR; + if ( rmtp != NULL ) { + _Timespec_Subtract( &stop, timeout, rmtp ); + } + } else if ( rmtp != NULL ) { + /* no time remaining */ + _Timespec_Set_to_zero( rmtp ); + } - return 0; + return err; } /* @@ -152,7 +139,12 @@ int nanosleep( return -1; _Timespec_Add_to( &now, rqtp ); ticks = _Watchdog_Ticks_from_timespec( &now ); - err = nanosleep_helper(ticks, relative_interval, rmtp, WATCHDOG_ABSOLUTE ); + err = nanosleep_helper( CLOCK_REALTIME, + ticks, + &now, + rmtp, + WATCHDOG_ABSOLUTE + ); if ( err != 0 ) { rtems_set_errno_and_return_minus_one( err ); } @@ -170,10 +162,9 @@ int clock_nanosleep( ) { int err = 0; - struct timespec now; + struct timespec timeout; uint64_t ticks; Watchdog_Interval relative_interval; - struct timespec relative_ts; TOD_Absolute_timeout_conversion_results status; if ( !_Timespec_Is_valid( rqtp ) ) @@ -190,25 +181,34 @@ int clock_nanosleep( if ( status == TOD_ABSOLUTE_TIMEOUT_IS_NOW ) return nanosleep_yield( NULL ); rmtp = NULL; /* Do not touch rmtp when using absolute time */ + timeout.tv_sec = 0; + timeout.tv_nsec = 0; } else { + /* prepare to convert relative ticks to absolute timeout */ + err = clock_gettime( clock_id, &timeout ); + if ( err != 0 ) + return EINVAL; relative_interval = _Timespec_To_ticks( rqtp ); } if ( relative_interval == 0 ) return nanosleep_yield( rmtp ); + _Timespec_Add_to( &timeout, rqtp ); if ( clock_id == CLOCK_REALTIME ) { - /* convert relative ticks to absolute timeout */ - err = clock_gettime( CLOCK_REALTIME, &now ); - if ( err != 0 ) - return EINVAL; - _Timespec_Add_to( &now, rqtp ); - ticks = _Watchdog_Ticks_from_timespec( &now ); - err = nanosleep_helper( ticks, relative_interval, rmtp, WATCHDOG_ABSOLUTE ); + ticks = _Watchdog_Ticks_from_timespec( &timeout ); + err = nanosleep_helper( + clock_id, + ticks, + &timeout, + rmtp, + WATCHDOG_ABSOLUTE + ); } else if ( clock_id == CLOCK_MONOTONIC ) { /* use the WATCHDOG_RELATIVE to ignore changes in wall time */ err = nanosleep_helper( + clock_id, relative_interval, - relative_interval, + &timeout, rmtp, WATCHDOG_RELATIVE ); -- cgit v1.2.3