posix: Use far future for very long timeouts

Close #3205.
This commit is contained in:
Sebastian Huber
2017-11-02 14:08:32 +01:00
parent 8c1f4064ad
commit 3e81d52e27
4 changed files with 90 additions and 29 deletions
+3 -11
View File
@@ -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
+5 -11
View File
@@ -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 );
@@ -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
)
+52 -7
View File
@@ -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>