summaryrefslogtreecommitdiffstats
path: root/cpukit/include/rtems/test.h
diff options
context:
space:
mode:
authorChris Johns <chrisj@rtems.org>2017-12-23 18:18:56 +1100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2018-01-25 08:45:26 +0100
commit2afb22b7e1ebcbe40373ff7e0efae7d207c655a9 (patch)
tree44759efe9374f13200a97e96d91bd9a2b7e5ce2a /cpukit/include/rtems/test.h
parentMAINTAINERS: Add myself to Write After Approval. (diff)
downloadrtems-2afb22b7e1ebcbe40373ff7e0efae7d207c655a9.tar.bz2
Remove make preinstall
A speciality of the RTEMS build system was the make preinstall step. It copied header files from arbitrary locations into the build tree. The header files were included via the -Bsome/build/tree/path GCC command line option. This has at least seven problems: * The make preinstall step itself needs time and disk space. * Errors in header files show up in the build tree copy. This makes it hard for editors to open the right file to fix the error. * There is no clear relationship between source and build tree header files. This makes an audit of the build process difficult. * The visibility of all header files in the build tree makes it difficult to enforce API barriers. For example it is discouraged to use BSP-specifics in the cpukit. * An introduction of a new build system is difficult. * Include paths specified by the -B option are system headers. This may suppress warnings. * The parallel build had sporadic failures on some hosts. This patch removes the make preinstall step. All installed header files are moved to dedicated include directories in the source tree. Let @RTEMS_CPU@ be the target architecture, e.g. arm, powerpc, sparc, etc. Let @RTEMS_BSP_FAMILIY@ be a BSP family base directory, e.g. erc32, imx, qoriq, etc. The new cpukit include directories are: * cpukit/include * cpukit/score/cpu/@RTEMS_CPU@/include * cpukit/libnetworking The new BSP include directories are: * bsps/include * bsps/@RTEMS_CPU@/include * bsps/@RTEMS_CPU@/@RTEMS_BSP_FAMILIY@/include There are build tree include directories for generated files. The include directory order favours the most general header file, e.g. it is not possible to override general header files via the include path order. The "bootstrap -p" option was removed. The new "bootstrap -H" option should be used to regenerate the "headers.am" files. Update #3254.
Diffstat (limited to 'cpukit/include/rtems/test.h')
-rw-r--r--cpukit/include/rtems/test.h314
1 files changed, 314 insertions, 0 deletions
diff --git a/cpukit/include/rtems/test.h b/cpukit/include/rtems/test.h
new file mode 100644
index 0000000000..3dbdb9e32e
--- /dev/null
+++ b/cpukit/include/rtems/test.h
@@ -0,0 +1,314 @@
+/*
+ * Copyright (c) 2014, 2017 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Dornierstr. 4
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * 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 <rtems.h>
+#include <rtems/printer.h>
+#include <rtems/score/atomic.h>
+#include <rtems/score/smpbarrier.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup RTEMSTest Test Support
+ *
+ * @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 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 */