summaryrefslogtreecommitdiffstats
path: root/testsuites/psxtests/psxclock/init.c
diff options
context:
space:
mode:
Diffstat (limited to 'testsuites/psxtests/psxclock/init.c')
-rw-r--r--testsuites/psxtests/psxclock/init.c197
1 files changed, 193 insertions, 4 deletions
diff --git a/testsuites/psxtests/psxclock/init.c b/testsuites/psxtests/psxclock/init.c
index 66d938868b..eb2f1d130c 100644
--- a/testsuites/psxtests/psxclock/init.c
+++ b/testsuites/psxtests/psxclock/init.c
@@ -1,10 +1,29 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/*
* COPYRIGHT (c) 1989-2012.
* On-Line Applications Research Corporation (OAR).
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CONFIG_H
@@ -31,6 +50,174 @@ static void check_enosys(int status)
rtems_test_exit(0);
}
+static void wait_ticks( rtems_interval ticks )
+{
+ /*
+ * Avoid any clock related sleep calls
+ */
+ rtems_test_assert( rtems_task_wake_after( ticks ) == RTEMS_SUCCESSFUL );
+}
+
+struct clock_context;
+typedef struct clock_context clock_context;
+typedef void (*clock_sleeper)(clock_context* ctx);
+struct clock_context {
+ const char* name;
+ int instance;
+ rtems_id tid;
+ int counter;
+ int result;
+ rtems_interval ticks;
+ struct timespec tspec;
+ clock_sleeper sleeper;
+};
+
+static void clock_context_init(
+ clock_context* ctx, const char* name, int instance,
+ time_t secs, long nsecs, clock_sleeper sleeper)
+{
+ memset( ctx, 0, sizeof( *ctx ) );
+ ctx->name = name;
+ ctx->instance = instance;
+ ctx->tspec.tv_sec = secs;
+ ctx->tspec.tv_nsec = nsecs;
+ ctx->sleeper = sleeper;
+}
+
+static void test_nanosleep( clock_context* ctx )
+{
+ if ( nanosleep ( &ctx->tspec, NULL ) < 0 )
+ {
+ ctx->result = errno;
+ }
+}
+
+static void test_clock_nanosleep_realtime( clock_context* ctx )
+{
+ if ( clock_nanosleep ( CLOCK_REALTIME, 0, &ctx->tspec, NULL ) < 0 )
+ {
+ ctx->result = errno;
+ }
+}
+
+static void test_clock_nanosleep_monotonic( clock_context* ctx )
+{
+ if ( clock_nanosleep ( CLOCK_MONOTONIC, 0, &ctx->tspec, NULL ) < 0 )
+ {
+ ctx->result = errno;
+ }
+}
+
+static void test_clock_check( clock_context* ctx, const rtems_interval ticks_per_sec )
+{
+ const long tick_period_nsec = 1000000000LLU / ticks_per_sec;
+ rtems_interval ticks =
+ (((ctx->tspec.tv_sec * 1000000000LLU) + ctx->tspec.tv_nsec) / tick_period_nsec) + 1;
+ rtems_test_assert( ctx->result == 0 );
+ printf(
+ "clock: %s: sec=%" PRIdtime_t" nsec=%li ticks=%u expected-ticks=%u\n",
+ ctx->name, ctx->tspec.tv_sec, ctx->tspec.tv_nsec, ctx->ticks, ticks);
+ rtems_test_assert( ctx->ticks == ticks );
+}
+
+static void task_clock( rtems_task_argument arg )
+{
+ clock_context* ctx = (clock_context*) arg;
+ rtems_interval start = rtems_clock_get_ticks_since_boot();
+ rtems_interval end;
+ ctx->result = 0;
+ ctx->sleeper( ctx );
+ end = rtems_clock_get_ticks_since_boot();
+ ctx->ticks = end - start;
+ ++ctx->counter;
+ rtems_task_delete( RTEMS_SELF );
+}
+
+static void test_start_task( clock_context* ctx )
+{
+ rtems_status_code sc;
+ sc = rtems_task_create(
+ rtems_build_name( 'C', 'R', 'T', '0' + ctx->instance ),
+ 1,
+ RTEMS_MINIMUM_STACK_SIZE,
+ RTEMS_DEFAULT_MODES,
+ RTEMS_DEFAULT_ATTRIBUTES,
+ &ctx->tid
+ );
+ rtems_test_assert( sc == RTEMS_SUCCESSFUL );
+ sc = rtems_task_start( ctx->tid, task_clock, (rtems_task_argument) ctx );
+ rtems_test_assert( sc == RTEMS_SUCCESSFUL );
+}
+
+static void test_settime_and_sleeping_step( int step )
+{
+ const rtems_interval ticks_per_sec = rtems_clock_get_ticks_per_second();
+ struct timespec tv;
+
+ clock_context ns_ctx;
+ clock_context cnr_ctx;
+ clock_context cnm_ctx;
+
+ printf( "\nClock settime while sleeping: step=%i\n", step );
+
+ clock_context_init(
+ &ns_ctx, "nanosleep", 0, 0, 500000000,
+ test_nanosleep );
+ clock_context_init(
+ &cnr_ctx, "clock_nanosleep(CLOCK_REALTIME)", 0, 0, 500000000,
+ test_clock_nanosleep_realtime );
+ clock_context_init(
+ &cnm_ctx, "clock_nanosleep(CLOCK_MONOTONIC)", 0, 0, 500000000,
+ test_clock_nanosleep_monotonic );
+
+ /* Sat, 01 Jan 2000 00:00:00 GMT */
+ tv.tv_sec = 946684800;
+ tv.tv_nsec = 0;
+ rtems_test_assert( clock_settime( CLOCK_REALTIME, &tv ) == 0 );
+
+ wait_ticks( 1 );
+
+ test_start_task( &ns_ctx );
+ test_start_task( &cnr_ctx );
+ test_start_task( &cnm_ctx );
+
+ wait_ticks( 2 );
+
+ /*
+ * Jump forwards 1 second
+ */
+ if ( step != 0 )
+ {
+ tv.tv_sec = 946684800 + step;
+ tv.tv_nsec = 0;
+ rtems_test_assert( clock_settime( CLOCK_REALTIME, &tv ) == 0 );
+ }
+
+ while (true)
+ {
+ int counts = 0;
+ wait_ticks( ticks_per_sec / 4 );
+ counts += ns_ctx.counter;
+ counts += cnr_ctx.counter;
+ counts += cnm_ctx.counter;
+ if (counts == 3)
+ {
+ break;
+ }
+ }
+
+ test_clock_check( &ns_ctx, ticks_per_sec );
+ test_clock_check( &cnr_ctx, ticks_per_sec );
+ test_clock_check( &cnm_ctx, ticks_per_sec );
+}
+
+static void test_settime_and_sleeping( void )
+{
+ test_settime_and_sleeping_step( 0 );
+ test_settime_and_sleeping_step( 1 );
+ test_settime_and_sleeping_step( -1 );
+}
+
typedef struct {
int counter;
struct timespec delta;
@@ -339,6 +526,8 @@ static rtems_task Init(
}
#endif
+ test_settime_and_sleeping( );
+
TEST_END();
rtems_test_exit(0);
}
@@ -351,7 +540,7 @@ static rtems_task Init(
#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
-#define CONFIGURE_MAXIMUM_TASKS 2
+#define CONFIGURE_MAXIMUM_TASKS 4
#define CONFIGURE_INIT
#include <rtems/confdefs.h>