Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:49

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*
0004  * Copyright (C) 2015, 2024 embedded brains GmbH & Co. KG
0005  *
0006  * Redistribution and use in source and binary forms, with or without
0007  * modification, are permitted provided that the following conditions
0008  * are met:
0009  * 1. Redistributions of source code must retain the above copyright
0010  *    notice, this list of conditions and the following disclaimer.
0011  * 2. Redistributions in binary form must reproduce the above copyright
0012  *    notice, this list of conditions and the following disclaimer in the
0013  *    documentation and/or other materials provided with the distribution.
0014  *
0015  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0016  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0017  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0018  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0019  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0020  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0021  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0022  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0023  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0024  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0025  * POSSIBILITY OF SUCH DAMAGE.
0026  */
0027 
0028 #ifdef HAVE_CONFIG_H
0029 #include "config.h"
0030 #endif
0031 
0032 #include <sys/lock.h>
0033 
0034 #define _KERNEL
0035 
0036 #include <sys/time.h>
0037 #include <sys/timetc.h>
0038 
0039 #include <stdlib.h>
0040 #include <stdio.h>
0041 #include <inttypes.h>
0042 #include <unistd.h>
0043 
0044 #include <rtems.h>
0045 #include <rtems/counter.h>
0046 #include <rtems/test-info.h>
0047 
0048 #include <rtems/score/timecounterimpl.h>
0049 #include <rtems/timecounter.h>
0050 #include <rtems/bsd.h>
0051 
0052 #include <test_support.h>
0053 
0054 #include "tmacros.h"
0055 
0056 const char rtems_test_name[] = "SPTIMECOUNTER 2";
0057 
0058 #define CPU_COUNT 32
0059 
0060 #define DURATION_IN_SECONDS 1
0061 
0062 typedef struct {
0063   rtems_test_parallel_context base;
0064   const char *test_sep;
0065   const char *counter_sep;
0066   struct timecounter tc_null;
0067   uint32_t binuptime_per_job[CPU_COUNT];
0068   sbintime_t duration_per_job[CPU_COUNT];
0069   uint32_t rtemsuptime_per_job[CPU_COUNT];
0070 } timecounter_context;
0071 
0072 static timecounter_context test_instance;
0073 
0074 static rtems_interval test_duration(void)
0075 {
0076   return DURATION_IN_SECONDS * rtems_clock_get_ticks_per_second();
0077 }
0078 
0079 static uint32_t test_get_timecount_null(struct timecounter *tc)
0080 {
0081   return 0;
0082 }
0083 
0084 static void install_tc_null(timecounter_context *ctx)
0085 {
0086   struct timecounter *tc_cpu = &ctx->tc_null;
0087 
0088   tc_cpu->tc_get_timecount = test_get_timecount_null;
0089   tc_cpu->tc_counter_mask = 0xffffffff;
0090   tc_cpu->tc_frequency = rtems_counter_nanoseconds_to_ticks(1000000000);
0091   tc_cpu->tc_quality = 2000;
0092   rtems_timecounter_install(tc_cpu);
0093 }
0094 
0095 static void test_print_results(
0096   const char *driver,
0097   timecounter_context *ctx,
0098   size_t active_workers
0099 )
0100 {
0101   const char *value_sep;
0102   size_t i;
0103 
0104   if (active_workers == 1) {
0105     printf(
0106       "%s{\n"
0107       "    \"timecounter\": \"%s\",\n"
0108       "    \"counter\": [",
0109       ctx->test_sep,
0110       driver
0111     );
0112     ctx->test_sep = ", ";
0113     ctx->counter_sep = "\n      ";
0114   }
0115 
0116   printf("%s[", ctx->counter_sep);
0117   ctx->counter_sep = "],\n      ";
0118   value_sep = "";
0119 
0120   for (i = 0; i < active_workers; ++i) {
0121     printf(
0122       "%s%" PRIu32,
0123       value_sep,
0124       ctx->binuptime_per_job[i]
0125     );
0126     value_sep = ", ";
0127   }
0128 
0129   if (active_workers == rtems_scheduler_get_processor_maximum()) {
0130     printf("]\n    ]\n  }");
0131   }
0132 }
0133 
0134 static rtems_interval test_bintime_init(
0135   rtems_test_parallel_context *base,
0136   void *arg,
0137   size_t active_workers
0138 )
0139 {
0140   rtems_test_spin_until_next_tick();
0141 
0142   return test_duration();
0143 }
0144 
0145 static void test_bintime_body(
0146   rtems_test_parallel_context *base,
0147   void *arg,
0148   size_t active_workers,
0149   size_t worker_index
0150 )
0151 {
0152   timecounter_context *ctx = (timecounter_context *) base;
0153   uint32_t counter = 1;
0154   struct bintime start;
0155   struct bintime end;
0156 
0157   rtems_bsd_binuptime(&start);
0158 
0159   do {
0160     ++counter;
0161     rtems_bsd_binuptime(&end);
0162   } while (!rtems_test_parallel_stop_job(&ctx->base));
0163 
0164   ctx->binuptime_per_job[worker_index] = counter;
0165   ctx->duration_per_job[worker_index] = bttosbt(end) - bttosbt(start);
0166 }
0167 
0168 static void test_bintime_fini(
0169   rtems_test_parallel_context *base,
0170   void *arg,
0171   size_t active_workers
0172 )
0173 {
0174   timecounter_context *ctx = (timecounter_context *) base;
0175   size_t i;
0176 
0177   for (i = 0; i < active_workers; ++i) {
0178     sbintime_t error;
0179 
0180     error = DURATION_IN_SECONDS * SBT_1S - ctx->duration_per_job[i];
0181     rtems_test_assert(error * error < SBT_1MS * SBT_1MS);
0182   }
0183 
0184   test_print_results("Clock Driver", ctx, active_workers);
0185 }
0186 
0187 static rtems_interval test_bintime_null_init(
0188   rtems_test_parallel_context *base,
0189   void *arg,
0190   size_t active_workers
0191 )
0192 {
0193   timecounter_context *ctx = &test_instance;
0194 
0195   install_tc_null(ctx);
0196 
0197   return test_duration();
0198 }
0199 
0200 static void test_bintime_null_body(
0201   rtems_test_parallel_context *base,
0202   void *arg,
0203   size_t active_workers,
0204   size_t worker_index
0205 )
0206 {
0207   timecounter_context *ctx = (timecounter_context *) base;
0208   struct bintime bt;
0209   uint32_t counter = 0;
0210 
0211   while (!rtems_test_parallel_stop_job(&ctx->base)) {
0212     ++counter;
0213     rtems_bsd_binuptime(&bt);
0214   }
0215 
0216   ctx->binuptime_per_job[worker_index] = counter;
0217 }
0218 
0219 static void test_bintime_null_fini(
0220   rtems_test_parallel_context *base,
0221   void *arg,
0222   size_t active_workers
0223 )
0224 {
0225   test_print_results("Null", (timecounter_context *) base, active_workers);
0226 }
0227 
0228 static const rtems_test_parallel_job timecounter_jobs[] = {
0229   {
0230     .init = test_bintime_init,
0231     .body = test_bintime_body,
0232     .fini = test_bintime_fini,
0233     .cascade = true
0234   },{
0235     .init = test_bintime_null_init,
0236     .body = test_bintime_null_body,
0237     .fini = test_bintime_null_fini,
0238     .cascade = true
0239   }
0240 };
0241 
0242 static void Init(rtems_task_argument arg)
0243 {
0244   timecounter_context *ctx = &test_instance;
0245   struct bintime bt;
0246   struct timespec ts;
0247   struct timeval tv;
0248 
0249   TEST_BEGIN();
0250 
0251   printf("*** BEGIN OF JSON DATA ***\n[\n  ");
0252 
0253   ctx->test_sep = "";
0254   rtems_test_parallel(
0255     &ctx->base,
0256     NULL,
0257     &timecounter_jobs[0],
0258     RTEMS_ARRAY_SIZE(timecounter_jobs)
0259   );
0260 
0261   printf("\n]\n*** END OF JSON DATA ***\n");
0262 
0263   /* Check for all functions available in the bsd.h user space */
0264 
0265   rtems_bsd_bintime(&bt);
0266   rtems_bsd_microtime(&tv);
0267   rtems_bsd_nanotime(&ts);
0268   rtems_bsd_binuptime(&bt);
0269   rtems_bsd_microuptime(&tv);
0270   rtems_bsd_nanouptime(&ts);
0271   rtems_bsd_getbintime(&bt);
0272   rtems_bsd_getmicrotime(&tv);
0273   rtems_bsd_getnanotime(&ts);
0274   rtems_bsd_getbinuptime(&bt);
0275   rtems_bsd_getmicrouptime(&tv);
0276   rtems_bsd_getnanouptime(&ts);
0277 
0278   TEST_END();
0279   rtems_test_exit(0);
0280 }
0281 
0282 #define CONFIGURE_MICROSECONDS_PER_TICK 1000
0283 
0284 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
0285 #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
0286 
0287 #define CONFIGURE_MAXIMUM_TASKS (2 + CPU_COUNT - 1)
0288 #define CONFIGURE_MAXIMUM_TIMERS 2
0289 #define CONFIGURE_MAXIMUM_PERIODS 1
0290 
0291 #define CONFIGURE_MAXIMUM_PROCESSORS CPU_COUNT
0292 
0293 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
0294 
0295 #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
0296 
0297 #define CONFIGURE_INIT
0298 
0299 #include <rtems/confdefs.h>