Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSTest
0007  *
0008  * @brief This header file provides interfaces of the RTEMS Test Support.
0009  */
0010 
0011 /*
0012  * Copyright (C) 2014, 2018 embedded brains GmbH & Co. KG
0013  *
0014  * Redistribution and use in source and binary forms, with or without
0015  * modification, are permitted provided that the following conditions
0016  * are met:
0017  * 1. Redistributions of source code must retain the above copyright
0018  *    notice, this list of conditions and the following disclaimer.
0019  * 2. Redistributions in binary form must reproduce the above copyright
0020  *    notice, this list of conditions and the following disclaimer in the
0021  *    documentation and/or other materials provided with the distribution.
0022  *
0023  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0024  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0025  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0026  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0027  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0028  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0029  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0030  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0031  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0032  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0033  * POSSIBILITY OF SUCH DAMAGE.
0034  */
0035 
0036 #ifndef _RTEMS_TEST_H
0037 #define _RTEMS_TEST_H
0038 
0039 #include <rtems.h>
0040 #include <rtems/score/atomic.h>
0041 #include <rtems/score/smpbarrier.h>
0042 
0043 #ifdef __cplusplus
0044 extern "C" {
0045 #endif /* __cplusplus */
0046 
0047 /**
0048  * @defgroup RTEMSTest Test Support
0049  *
0050  * @ingroup RTEMSAPI
0051  *
0052  * @brief Test support functions.
0053  *
0054  * @{
0055  */
0056 
0057 /**
0058  * @brief Each test must define a test name string.
0059  */
0060 extern const char rtems_test_name[];
0061 
0062 /**
0063  * @brief Fatal extension for tests.
0064  */
0065 void rtems_test_fatal_extension(
0066   rtems_fatal_source source,
0067   bool always_set_to_false,
0068   rtems_fatal_code code
0069 );
0070 
0071 /**
0072  * @brief Initial extension for tests.
0073  */
0074 #define RTEMS_TEST_INITIAL_EXTENSION \
0075   { NULL, NULL, NULL, NULL, NULL, NULL, NULL, rtems_test_fatal_extension, NULL }
0076 
0077 /**
0078  * @brief Test states.
0079  */
0080 typedef enum
0081 {
0082   RTEMS_TEST_STATE_PASS,
0083   RTEMS_TEST_STATE_FAIL,
0084   RTEMS_TEST_STATE_USER_INPUT,
0085   RTEMS_TEST_STATE_INDETERMINATE,
0086   RTEMS_TEST_STATE_BENCHMARK
0087 } RTEMS_TEST_STATE;
0088 
0089 #if (TEST_STATE_EXPECTED_FAIL && TEST_STATE_USER_INPUT) || \
0090     (TEST_STATE_EXPECTED_FAIL && TEST_STATE_INDETERMINATE) || \
0091     (TEST_STATE_EXPECTED_FAIL && TEST_STATE_BENCHMARK) || \
0092     (TEST_STATE_USER_INPUT    && TEST_STATE_INDETERMINATE) || \
0093     (TEST_STATE_USER_INPUT    && TEST_STATE_BENCHMARK) || \
0094     (TEST_STATE_INDETERMINATE && TEST_STATE_BENCHMARK)
0095   #error Test states must be unique
0096 #endif
0097 
0098 #if TEST_STATE_EXPECTED_FAIL
0099   #define TEST_STATE RTEMS_TEST_STATE_FAIL
0100 #elif TEST_STATE_USER_INPUT
0101   #define TEST_STATE RTEMS_TEST_STATE_USER_INPUT
0102 #elif TEST_STATE_INDETERMINATE
0103   #define TEST_STATE RTEMS_TEST_STATE_INDETERMINATE
0104 #elif TEST_STATE_BENCHMARK
0105   #define TEST_STATE RTEMS_TEST_STATE_BENCHMARK
0106 #else
0107   #define TEST_STATE RTEMS_TEST_STATE_PASS
0108 #endif
0109 
0110 /**
0111  * @brief Prints a begin of test message using printf().
0112  *
0113  * @return As specified by printf().
0114  */
0115 int rtems_test_begin(const char* name, const RTEMS_TEST_STATE state);
0116 
0117 /**
0118  * @brief Prints an end of test message using printf().
0119  *
0120  * @return As specified by printf().
0121  */
0122 int rtems_test_end(const char* name);
0123 
0124 /**
0125  * @brief Exit the test without calling exit() since it closes stdin, etc and
0126  * pulls in stdio code
0127  */
0128 RTEMS_NO_RETURN void rtems_test_exit(int status);
0129 
0130 #define RTEMS_TEST_PARALLEL_PROCESSOR_MAX 32
0131 
0132 typedef struct rtems_test_parallel_job rtems_test_parallel_job;
0133 
0134 /**
0135  * @brief Internal context for parallel job execution.
0136  */
0137 typedef struct {
0138   Atomic_Ulong stop;
0139   SMP_barrier_Control barrier;
0140   size_t worker_count;
0141   rtems_id worker_ids[RTEMS_TEST_PARALLEL_PROCESSOR_MAX];
0142   rtems_id stop_worker_timer_id;
0143   const struct rtems_test_parallel_job *jobs;
0144   size_t job_count;
0145 } rtems_test_parallel_context;
0146 
0147 /**
0148  * @brief Worker task setup handler.
0149  *
0150  * Called during rtems_test_parallel() to optionally setup a worker task before
0151  * it is started.
0152  *
0153  * @param[in] ctx The parallel context.
0154  * @param[in] worker_index The worker index.
0155  * @param[in] worker_id The worker task identifier.
0156  */
0157 typedef void (*rtems_test_parallel_worker_setup)(
0158   rtems_test_parallel_context *ctx,
0159   size_t worker_index,
0160   rtems_id worker_id
0161 );
0162 
0163 /**
0164  * @brief Basic parallel job description.
0165  */
0166 struct rtems_test_parallel_job {
0167   /**
0168    * @brief Job initialization handler.
0169    *
0170    * This handler executes only in the context of the master worker before the
0171    * job body handler.
0172    *
0173    * @param[in] ctx The parallel context.
0174    * @param[in] arg The user specified argument.
0175    * @param[in] active_workers Count of active workers.  Depends on the cascade
0176    *   option.
0177    *
0178    * @return The desired job body execution time in clock ticks.  See
0179    *   rtems_test_parallel_stop_job().
0180    */
0181   rtems_interval (*init)(
0182     rtems_test_parallel_context *ctx,
0183     void *arg,
0184     size_t active_workers
0185   );
0186 
0187   /**
0188    * @brief Job body handler.
0189    *
0190    * @param[in] ctx The parallel context.
0191    * @param[in] arg The user specified argument.
0192    * @param[in] active_workers Count of active workers.  Depends on the cascade
0193    *   option.
0194    * @param[in] worker_index The worker index.  It ranges from 0 to the
0195    *   processor count minus one.
0196    */
0197   void (*body)(
0198     rtems_test_parallel_context *ctx,
0199     void *arg,
0200     size_t active_workers,
0201     size_t worker_index
0202   );
0203 
0204   /**
0205    * @brief Job finalization handler.
0206    *
0207    * This handler executes only in the context of the master worker after the
0208    * job body handler.
0209    *
0210    * @param[in] ctx The parallel context.
0211    * @param[in] arg The user specified argument.
0212    * @param[in] active_workers Count of active workers.  Depends on the cascade
0213    *   option.
0214    */
0215   void (*fini)(
0216     rtems_test_parallel_context *ctx,
0217     void *arg,
0218     size_t active_workers
0219   );
0220 
0221   /**
0222    * @brief Job specific argument.
0223    */
0224   void *arg;
0225 
0226   /**
0227    * @brief Job cascading flag.
0228    *
0229    * This flag indicates whether the job should be executed in a cascaded
0230    * manner (the job is executed on one processor first, two processors
0231    * afterwards and incremented step by step until all processors are used).
0232    */
0233   bool cascade;
0234 };
0235 
0236 /**
0237  * @brief Indicates if a job body should stop its work loop.
0238  *
0239  * @param[in] ctx The parallel context.
0240  *
0241  * @retval true The job body should stop its work loop and return to the caller.
0242  * @retval false Otherwise.
0243  */
0244 static inline bool rtems_test_parallel_stop_job(
0245   const rtems_test_parallel_context *ctx
0246 )
0247 {
0248   return _Atomic_Load_ulong(&ctx->stop, ATOMIC_ORDER_RELAXED) != 0;
0249 }
0250 
0251 /**
0252  * @brief Indicates if a worker is the master worker.
0253  *
0254  * The master worker is the thread that called rtems_test_parallel().
0255  *
0256  * @param[in] worker_index The worker index.
0257  *
0258  * @retval true This is the master worker.
0259  * @retval false Otherwise.
0260  */
0261 static inline bool rtems_test_parallel_is_master_worker(size_t worker_index)
0262 {
0263   return worker_index == 0;
0264 }
0265 
0266 /**
0267  * @brief Returns the task identifier for a worker.
0268  *
0269  * @param[in] ctx The parallel context.
0270  * @param[in] worker_index The worker index.
0271  *
0272  * @return The task identifier of the worker.
0273  */
0274 static inline rtems_id rtems_test_parallel_get_task_id(
0275   const rtems_test_parallel_context *ctx,
0276   size_t worker_index
0277 )
0278 {
0279   return ctx->worker_ids[worker_index];
0280 }
0281 
0282 /**
0283  * @brief Runs a bunch of jobs in parallel on all processors of the system.
0284  *
0285  * The worker tasks inherit the priority of the executing task.
0286  *
0287  * There are SMP barriers before and after the job body.
0288  *
0289  * @param[in] ctx The parallel context.
0290  * @param[in] worker_setup Optional handler to setup a worker task before it is
0291  *   started.
0292  * @param[in] jobs The table of jobs.
0293  * @param[in] job_count The count of jobs in the job table.
0294  */
0295 void rtems_test_parallel(
0296   rtems_test_parallel_context *ctx,
0297   rtems_test_parallel_worker_setup worker_setup,
0298   const rtems_test_parallel_job *jobs,
0299   size_t job_count
0300 );
0301 
0302 /**
0303  * @brief Performs a busy loop for the specified seconds and nanoseconds based
0304  * on the CPU usage of the executing thread.
0305  *
0306  * This function continuously reads the CPU usage of the executing thread.
0307  * This operation may lead to a scheduler instance lock contention in SMP
0308  * configurations.
0309  *
0310  * @param[in] seconds The busy seconds.
0311  * @param[in] nanoseconds The busy nanoseconds.
0312  */
0313 void rtems_test_busy_cpu_usage(time_t seconds, long nanoseconds);
0314 
0315 /**
0316  * @brief Runs the test cases of the RTEMS Test Framework using a default
0317  *   configuration in the context of a task.
0318  *
0319  * The application must provide rtems_test_name.
0320  *
0321  * @param arg is the task argument.
0322  * @param state is the test state.
0323  */
0324 RTEMS_NO_RETURN void rtems_test_run(
0325   rtems_task_argument    arg,
0326   const RTEMS_TEST_STATE state
0327 );
0328 
0329 /**
0330  * @brief Dumps the gcov information as a base64 encoded gcfn and gcda data
0331  *   stream using rtems_put_char().
0332  */
0333 void rtems_test_gcov_dump_info( void );
0334 
0335 /** @} */
0336 
0337 #ifdef __cplusplus
0338 }
0339 #endif /* __cplusplus */
0340 
0341 #endif /* _RTEMS_TEST_H */