summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2017-10-29 20:29:05 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2017-11-02 14:08:32 +0100
commit3e81d52e27ea030fc93580c610c40616ab2b0559 (patch)
tree5fe2bbc0217d90328a9c6d8ad43fb9bb3cbb0ddf
parenttests: Use printf() instead of fprintf() (diff)
downloadrtems-3e81d52e27ea030fc93580c610c40616ab2b0559.tar.bz2
posix: Use far future for very long timeouts
Close #3205.
-rw-r--r--cpukit/posix/src/nanosleep.c14
-rw-r--r--cpukit/posix/src/sigtimedwait.c16
-rw-r--r--cpukit/score/include/rtems/score/watchdogimpl.h30
-rw-r--r--testsuites/psxtests/psxclock/init.c59
4 files changed, 90 insertions, 29 deletions
diff --git a/cpukit/posix/src/nanosleep.c b/cpukit/posix/src/nanosleep.c
index f65c91bc17..5bd1b00aa9 100644
--- a/cpukit/posix/src/nanosleep.c
+++ b/cpukit/posix/src/nanosleep.c
@@ -63,7 +63,7 @@ int clock_nanosleep(
)
{
Thread_queue_Context queue_context;
- struct timespec spare_end;
+ struct timespec uptime;
const struct timespec *end;
Thread_Control *executing;
int eno;
@@ -93,16 +93,8 @@ int clock_nanosleep(
);
}
} else {
- if ( !_Watchdog_Is_valid_interval_timespec( rqtp ) ) {
- return EINVAL;
- }
-
- _TOD_Get_zero_based_uptime_as_timespec( &spare_end );
-
- /* In case this overflows, then the enqueue callout will reject it */
- _Timespec_Add_to( &spare_end, rqtp );
-
- end = &spare_end;
+ _TOD_Get_zero_based_uptime_as_timespec( &uptime );
+ end = _Watchdog_Future_timespec( &uptime, rqtp );
_Thread_queue_Context_set_enqueue_timeout_monotonic_timespec(
&queue_context,
end
diff --git a/cpukit/posix/src/sigtimedwait.c b/cpukit/posix/src/sigtimedwait.c
index a0e18adef0..72f4919be9 100644
--- a/cpukit/posix/src/sigtimedwait.c
+++ b/cpukit/posix/src/sigtimedwait.c
@@ -76,6 +76,7 @@ int sigtimedwait(
siginfo_t signal_information;
siginfo_t *the_info;
int signo;
+ struct timespec uptime;
Thread_queue_Context queue_context;
int error;
@@ -92,20 +93,13 @@ int sigtimedwait(
*/
if ( timeout != NULL ) {
- struct timespec end;
-
- if ( !_Watchdog_Is_valid_interval_timespec( timeout ) ) {
- return EINVAL;
- }
-
- _TOD_Get_zero_based_uptime_as_timespec( &end );
-
- /* In case this overflows, then the enqueue callout will reject it */
- _Timespec_Add_to( &end, timeout );
+ const struct timespec *end;
+ _TOD_Get_zero_based_uptime_as_timespec( &uptime );
+ end = _Watchdog_Future_timespec( &uptime, timeout );
_Thread_queue_Context_set_enqueue_timeout_monotonic_timespec(
&queue_context,
- &end
+ end
);
} else {
_Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
diff --git a/cpukit/score/include/rtems/score/watchdogimpl.h b/cpukit/score/include/rtems/score/watchdogimpl.h
index 7866c0ce44..f219a70768 100644
--- a/cpukit/score/include/rtems/score/watchdogimpl.h
+++ b/cpukit/score/include/rtems/score/watchdogimpl.h
@@ -324,6 +324,36 @@ RTEMS_INLINE_ROUTINE bool _Watchdog_Is_valid_interval_timespec(
return _Watchdog_Is_valid_timespec( ts ) && ts->tv_sec >= 0;
}
+RTEMS_INLINE_ROUTINE const struct timespec * _Watchdog_Future_timespec(
+ struct timespec *now,
+ const struct timespec *delta
+)
+{
+ uint64_t sec;
+
+ if ( !_Watchdog_Is_valid_interval_timespec( delta ) ) {
+ return NULL;
+ }
+
+ sec = (uint64_t) now->tv_sec;
+ sec += (uint64_t) delta->tv_sec;
+ now->tv_nsec += delta->tv_nsec;
+
+ /* We have 2 * (2**63 - 1) + 1 == UINT64_MAX */
+ if ( now->tv_nsec >= WATCHDOG_NANOSECONDS_PER_SECOND ) {
+ now->tv_nsec -= WATCHDOG_NANOSECONDS_PER_SECOND;
+ ++sec;
+ }
+
+ if ( sec <= INT64_MAX ) {
+ now->tv_sec = sec;
+ } else {
+ now->tv_sec = INT64_MAX;
+ }
+
+ return now;
+}
+
RTEMS_INLINE_ROUTINE bool _Watchdog_Is_far_future_monotonic_timespec(
const struct timespec *ts
)
diff --git a/testsuites/psxtests/psxclock/init.c b/testsuites/psxtests/psxclock/init.c
index 669f4bb0c4..1e7dae7bde 100644
--- a/testsuites/psxtests/psxclock/init.c
+++ b/testsuites/psxtests/psxclock/init.c
@@ -13,19 +13,17 @@
#include <time.h>
#include <errno.h>
+#include <stdint.h>
#include "pmacros.h"
#include "pritime.h"
+#include <rtems.h>
#include <rtems/score/todimpl.h>
const char rtems_test_name[] = "PSXCLOCK";
-/* forward declarations to avoid warnings */
-rtems_task Init(rtems_task_argument argument);
-void check_enosys(int status);
-
-void check_enosys(int status)
+static void check_enosys(int status)
{
if ( (status == -1) && (errno == ENOSYS) )
return;
@@ -33,7 +31,52 @@ void check_enosys(int status)
rtems_test_exit(0);
}
-rtems_task Init(
+typedef struct {
+ int counter;
+ struct timespec delta;
+} nanosleep_contex;
+
+static void task_nanosleep( rtems_task_argument arg )
+{
+ nanosleep_contex *ctx;
+
+ ctx = (nanosleep_contex *) arg;
+ ++ctx->counter;
+ nanosleep( &ctx->delta, NULL );
+}
+
+static void test_far_future_nanosleep( void )
+{
+ rtems_status_code sc;
+ rtems_id id;
+ nanosleep_contex ctx;
+
+ sc = rtems_task_create(
+ rtems_build_name( 'N', 'A', 'N', 'O' ),
+ 1,
+ RTEMS_MINIMUM_STACK_SIZE,
+ RTEMS_DEFAULT_MODES,
+ RTEMS_DEFAULT_ATTRIBUTES,
+ &id
+ );
+ rtems_test_assert( sc == RTEMS_SUCCESSFUL );
+
+ ctx.counter = 0;
+ ctx.delta.tv_sec = INT64_MAX;
+ ctx.delta.tv_nsec = 999999999;
+ sc = rtems_task_start( id, task_nanosleep, (rtems_task_argument) &ctx );
+ rtems_test_assert( sc == RTEMS_SUCCESSFUL );
+
+ sc = rtems_task_wake_after( RTEMS_YIELD_PROCESSOR );
+ rtems_test_assert( sc == RTEMS_SUCCESSFUL );
+
+ rtems_test_assert( ctx.counter == 1 );
+
+ sc = rtems_task_delete( id );
+ rtems_test_assert( sc == RTEMS_SUCCESSFUL );
+}
+
+static rtems_task Init(
rtems_task_argument argument
)
{
@@ -140,6 +183,8 @@ rtems_task Init(
printf( "Init: seconds remaining (%d)\n", (int)remaining );
rtems_test_assert( !remaining );
+ test_far_future_nanosleep();
+
/* error cases in nanosleep */
empty_line();
@@ -267,7 +312,7 @@ rtems_task Init(
#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
-#define CONFIGURE_MAXIMUM_TASKS 1
+#define CONFIGURE_MAXIMUM_TASKS 2
#define CONFIGURE_INIT
#include <rtems/confdefs.h>