summaryrefslogtreecommitdiffstats
path: root/cpukit/posix/src
diff options
context:
space:
mode:
authorGedare Bloom <gedare@rtems.org>2016-08-01 16:54:18 -0400
committerGedare Bloom <gedare@rtems.org>2016-08-10 12:09:50 -0400
commit709594f0fb29d4f860b99cda264ea3e74c635a72 (patch)
treed2ed983575614bb50c5d38e4b16895b00017aa6a /cpukit/posix/src
parentsptests/splinkersets01: Fix for small-data area (diff)
downloadrtems-709594f0fb29d4f860b99cda264ea3e74c635a72.tar.bz2
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
Diffstat (limited to 'cpukit/posix/src')
-rw-r--r--cpukit/posix/src/nanosleep.c78
1 files changed, 39 insertions, 39 deletions
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
);