From 9de8d61a9a4a7eda2bef620c8dde1b659850dce9 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Fri, 17 Jul 2020 13:36:49 +0200 Subject: libtest: to Rename this header file to later move to . The main feature provided by is the output of standard test information which is consumed by the RTEMS Tester. Update #3199. --- cpukit/include/rtems/test-info.h | 329 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 329 insertions(+) create mode 100644 cpukit/include/rtems/test-info.h (limited to 'cpukit/include/rtems/test-info.h') diff --git a/cpukit/include/rtems/test-info.h b/cpukit/include/rtems/test-info.h new file mode 100644 index 0000000000..873b8482af --- /dev/null +++ b/cpukit/include/rtems/test-info.h @@ -0,0 +1,329 @@ +/* + * Copyright (c) 2014, 2018 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * + * + * 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. + */ + +#ifndef _RTEMS_TEST_H +#define _RTEMS_TEST_H + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup RTEMSTest Test Support + * + * @ingroup RTEMSAPI + * + * @brief Test support functions. + * + * @{ + */ + +/** + * @brief Each test must define a test name string. + */ +extern const char rtems_test_name[]; + +/** + * @brief Each test must define a printer. + */ +extern rtems_printer rtems_test_printer; + +/** + * @brief Fatal extension for tests. + */ +void rtems_test_fatal_extension( + rtems_fatal_source source, + bool always_set_to_false, + rtems_fatal_code code +); + +/** + * @brief Initial extension for tests. + */ +#define RTEMS_TEST_INITIAL_EXTENSION \ + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, rtems_test_fatal_extension } + +/** + * @brief Test states. + */ +typedef enum +{ + RTEMS_TEST_STATE_PASS, + RTEMS_TEST_STATE_FAIL, + RTEMS_TEST_STATE_USER_INPUT, + RTEMS_TEST_STATE_INDETERMINATE, + RTEMS_TEST_STATE_BENCHMARK +} RTEMS_TEST_STATE; + +#if (TEST_STATE_EXPECTED_FAIL && TEST_STATE_USER_INPUT) || \ + (TEST_STATE_EXPECTED_FAIL && TEST_STATE_INDETERMINATE) || \ + (TEST_STATE_EXPECTED_FAIL && TEST_STATE_BENCHMARK) || \ + (TEST_STATE_USER_INPUT && TEST_STATE_INDETERMINATE) || \ + (TEST_STATE_USER_INPUT && TEST_STATE_BENCHMARK) || \ + (TEST_STATE_INDETERMINATE && TEST_STATE_BENCHMARK) + #error Test states must be unique +#endif + +#if TEST_STATE_EXPECTED_FAIL + #define TEST_STATE RTEMS_TEST_STATE_FAIL +#elif TEST_STATE_USER_INPUT + #define TEST_STATE RTEMS_TEST_STATE_USER_INPUT +#elif TEST_STATE_INDETERMINATE + #define TEST_STATE RTEMS_TEST_STATE_INDETERMINATE +#elif TEST_STATE_BENCHMARK + #define TEST_STATE RTEMS_TEST_STATE_BENCHMARK +#else + #define TEST_STATE RTEMS_TEST_STATE_PASS +#endif + +/** + * @brief Prints a begin of test message using printf(). + * + * @returns As specified by printf(). + */ +int rtems_test_begin(const char* name, const RTEMS_TEST_STATE state); + +/** + * @brief Prints an end of test message using printf(). + * + * @returns As specified by printf(). + */ +int rtems_test_end(const char* name); + +/** + * @brief Exit the test without calling exit() since it closes stdin, etc and + * pulls in stdio code + */ +void rtems_test_exit(int status) RTEMS_NO_RETURN; + +/** + * @brief Prints via the RTEMS printer. + * + * @returns As specified by printf(). + */ +int rtems_test_printf(const char* format, ...) RTEMS_PRINTFLIKE(1, 2); + +#define RTEMS_TEST_PARALLEL_PROCESSOR_MAX 32 + +typedef struct rtems_test_parallel_job rtems_test_parallel_job; + +/** + * @brief Internal context for parallel job execution. + */ +typedef struct { + Atomic_Ulong stop; + SMP_barrier_Control barrier; + size_t worker_count; + rtems_id worker_ids[RTEMS_TEST_PARALLEL_PROCESSOR_MAX]; + rtems_id stop_worker_timer_id; + const struct rtems_test_parallel_job *jobs; + size_t job_count; +} rtems_test_parallel_context; + +/** + * @brief Worker task setup handler. + * + * Called during rtems_test_parallel() to optionally setup a worker task before + * it is started. + * + * @param[in] ctx The parallel context. + * @param[in] worker_index The worker index. + * @param[in] worker_id The worker task identifier. + */ +typedef void (*rtems_test_parallel_worker_setup)( + rtems_test_parallel_context *ctx, + size_t worker_index, + rtems_id worker_id +); + +/** + * @brief Basic parallel job description. + */ +struct rtems_test_parallel_job { + /** + * @brief Job initialization handler. + * + * This handler executes only in the context of the master worker before the + * job body handler. + * + * @param[in] ctx The parallel context. + * @param[in] arg The user specified argument. + * @param[in] active_workers Count of active workers. Depends on the cascade + * option. + * + * @return The desired job body execution time in clock ticks. See + * rtems_test_parallel_stop_job(). + */ + rtems_interval (*init)( + rtems_test_parallel_context *ctx, + void *arg, + size_t active_workers + ); + + /** + * @brief Job body handler. + * + * @param[in] ctx The parallel context. + * @param[in] arg The user specified argument. + * @param[in] active_workers Count of active workers. Depends on the cascade + * option. + * @param[in] worker_index The worker index. It ranges from 0 to the + * processor count minus one. + */ + void (*body)( + rtems_test_parallel_context *ctx, + void *arg, + size_t active_workers, + size_t worker_index + ); + + /** + * @brief Job finalization handler. + * + * This handler executes only in the context of the master worker after the + * job body handler. + * + * @param[in] ctx The parallel context. + * @param[in] arg The user specified argument. + * @param[in] active_workers Count of active workers. Depends on the cascade + * option. + */ + void (*fini)( + rtems_test_parallel_context *ctx, + void *arg, + size_t active_workers + ); + + /** + * @brief Job specific argument. + */ + void *arg; + + /** + * @brief Job cascading flag. + * + * This flag indicates whether the job should be executed in a cascaded + * manner (the job is executed on one processor first, two processors + * afterwards and incremented step by step until all processors are used). + */ + bool cascade; +}; + +/** + * @brief Indicates if a job body should stop its work loop. + * + * @param[in] ctx The parallel context. + * + * @retval true The job body should stop its work loop and return to the caller. + * @retval false Otherwise. + */ +static inline bool rtems_test_parallel_stop_job( + const rtems_test_parallel_context *ctx +) +{ + return _Atomic_Load_ulong(&ctx->stop, ATOMIC_ORDER_RELAXED) != 0; +} + +/** + * @brief Indicates if a worker is the master worker. + * + * The master worker is the thread that called rtems_test_parallel(). + * + * @param[in] worker_index The worker index. + * + * @retval true This is the master worker. + * @retval false Otherwise. + */ +static inline bool rtems_test_parallel_is_master_worker(size_t worker_index) +{ + return worker_index == 0; +} + +/** + * @brief Returns the task identifier for a worker. + * + * @param[in] ctx The parallel context. + * @param[in] worker_index The worker index. + * + * @return The task identifier of the worker. + */ +static inline rtems_id rtems_test_parallel_get_task_id( + const rtems_test_parallel_context *ctx, + size_t worker_index +) +{ + return ctx->worker_ids[worker_index]; +} + +/** + * @brief Runs a bunch of jobs in parallel on all processors of the system. + * + * The worker tasks inherit the priority of the executing task. + * + * There are SMP barriers before and after the job body. + * + * @param[in] ctx The parallel context. + * @param[in] worker_setup Optional handler to setup a worker task before it is + * started. + * @param[in] jobs The table of jobs. + * @param[in] job_count The count of jobs in the job table. + */ +void rtems_test_parallel( + rtems_test_parallel_context *ctx, + rtems_test_parallel_worker_setup worker_setup, + const rtems_test_parallel_job *jobs, + size_t job_count +); + +/** + * @brief Performs a busy loop for the specified seconds and nanoseconds based + * on the CPU usage of the executing thread. + * + * This function continuously reads the CPU usage of the executing thread. + * This operation may lead to a scheduler instance lock contention in SMP + * configurations. + * + * @param[in] seconds The busy seconds. + * @param[in] nanoseconds The busy nanoseconds. + */ +void rtems_test_busy_cpu_usage(time_t seconds, long nanoseconds); + +/** + * @brief Performs a busy loop with the specified iteration count. + * + * This function is optimized to not perform memory accesses and should have a + * small jitter. + * + * @param[in] count The iteration count. + */ +void rtems_test_busy(uint_fast32_t count); + +/** + * @brief Returns a count value for rtems_test_busy() which yields roughly a + * duration of one clock tick. + */ +uint_fast32_t rtems_test_get_one_tick_busy_count(void); + +/** @} */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _RTEMS_TEST_H */ -- cgit v1.2.3