source: rtems/cpukit/libmisc/testsupport/test.h @ 7f7a3e8f

5
Last change on this file since 7f7a3e8f was 7f7a3e8f, checked in by Sebastian Huber <sebastian.huber@…>, on 06/29/17 at 12:36:26

tests: Move busy loop to test support

Update #3056.

  • Property mode set to 100644
File size: 6.8 KB
Line 
1/*
2 * Copyright (c) 2014, 2017 embedded brains GmbH.  All rights reserved.
3 *
4 *  embedded brains GmbH
5 *  Dornierstr. 4
6 *  82178 Puchheim
7 *  Germany
8 *  <rtems@embedded-brains.de>
9 *
10 * The license and distribution terms for this file may be
11 * found in the file LICENSE in this distribution or at
12 * http://www.rtems.org/license/LICENSE.
13 */
14
15#ifndef _RTEMS_TEST_H
16#define _RTEMS_TEST_H
17
18#include <rtems.h>
19#include <rtems/printer.h>
20#include <rtems/score/atomic.h>
21#include <rtems/score/smpbarrier.h>
22
23#ifdef __cplusplus
24extern "C" {
25#endif /* __cplusplus */
26
27/**
28 * @defgroup RTEMSTest Test Support
29 *
30 * @brief Test support functions.
31 *
32 * @{
33 */
34
35/**
36 * @brief Each test must define a test name string.
37 */
38extern const char rtems_test_name[];
39
40/**
41 * @brief Each test must define a printer.
42 */
43extern rtems_printer rtems_test_printer;
44
45/**
46 * @brief Fatal extension for tests.
47 */
48void rtems_test_fatal_extension(
49  rtems_fatal_source source,
50  bool always_set_to_false,
51  rtems_fatal_code code
52);
53
54/**
55 * @brief Initial extension for tests.
56 */
57#define RTEMS_TEST_INITIAL_EXTENSION \
58  { NULL, NULL, NULL, NULL, NULL, NULL, NULL, rtems_test_fatal_extension }
59
60/**
61 * @brief Begin of test message format string.
62 */
63#define TEST_BEGIN_STRING "\n\n*** BEGIN OF TEST %s ***\n", rtems_test_name
64
65/**
66 * @brief End of test message format string.
67 */
68#define TEST_END_STRING "*** END OF TEST %s ***\n", rtems_test_name
69
70/**
71 * @brief Prints a begin of test message using printf().
72 *
73 * @returns As specified by printf().
74 */
75int rtems_test_begin(void);
76
77/**
78 * @brief Prints an end of test message using printf().
79 *
80 * @returns As specified by printf().
81 */
82int rtems_test_end(void);
83
84/**
85 * @brief Prints via the RTEMS printer.
86 *
87 * @returns As specified by printf().
88 */
89int rtems_test_printf(const char* format, ...) RTEMS_PRINTFLIKE(1, 2);
90
91#define RTEMS_TEST_PARALLEL_PROCESSOR_MAX 32
92
93typedef struct rtems_test_parallel_job rtems_test_parallel_job;
94
95/**
96 * @brief Internal context for parallel job execution.
97 */
98typedef struct {
99  Atomic_Ulong stop;
100  SMP_barrier_Control barrier;
101  size_t worker_count;
102  rtems_id worker_ids[RTEMS_TEST_PARALLEL_PROCESSOR_MAX];
103  rtems_id stop_worker_timer_id;
104  const struct rtems_test_parallel_job *jobs;
105  size_t job_count;
106} rtems_test_parallel_context;
107
108/**
109 * @brief Worker task setup handler.
110 *
111 * Called during rtems_test_parallel() to optionally setup a worker task before
112 * it is started.
113 *
114 * @param[in] ctx The parallel context.
115 * @param[in] worker_index The worker index.
116 * @param[in] worker_id The worker task identifier.
117 */
118typedef void (*rtems_test_parallel_worker_setup)(
119  rtems_test_parallel_context *ctx,
120  size_t worker_index,
121  rtems_id worker_id
122);
123
124/**
125 * @brief Basic parallel job description.
126 */
127struct rtems_test_parallel_job {
128  /**
129   * @brief Job initialization handler.
130   *
131   * This handler executes only in the context of the master worker before the
132   * job body handler.
133   *
134   * @param[in] ctx The parallel context.
135   * @param[in] arg The user specified argument.
136   * @param[in] active_workers Count of active workers.  Depends on the cascade
137   *   option.
138   *
139   * @return The desired job body execution time in clock ticks.  See
140   *   rtems_test_parallel_stop_job().
141   */
142  rtems_interval (*init)(
143    rtems_test_parallel_context *ctx,
144    void *arg,
145    size_t active_workers
146  );
147
148  /**
149   * @brief Job body handler.
150   *
151   * @param[in] ctx The parallel context.
152   * @param[in] arg The user specified argument.
153   * @param[in] active_workers Count of active workers.  Depends on the cascade
154   *   option.
155   * @param[in] worker_index The worker index.  It ranges from 0 to the
156   *   processor count minus one.
157   */
158  void (*body)(
159    rtems_test_parallel_context *ctx,
160    void *arg,
161    size_t active_workers,
162    size_t worker_index
163  );
164
165  /**
166   * @brief Job finalization handler.
167   *
168   * This handler executes only in the context of the master worker after the
169   * job body handler.
170   *
171   * @param[in] ctx The parallel context.
172   * @param[in] arg The user specified argument.
173   * @param[in] active_workers Count of active workers.  Depends on the cascade
174   *   option.
175   */
176  void (*fini)(
177    rtems_test_parallel_context *ctx,
178    void *arg,
179    size_t active_workers
180  );
181
182  /**
183   * @brief Job specific argument.
184   */
185  void *arg;
186
187  /**
188   * @brief Job cascading flag.
189   *
190   * This flag indicates whether the job should be executed in a cascaded
191   * manner (the job is executed on one processor first, two processors
192   * afterwards and incremented step by step until all processors are used).
193   */
194  bool cascade;
195};
196
197/**
198 * @brief Indicates if a job body should stop its work loop.
199 *
200 * @param[in] ctx The parallel context.
201 *
202 * @retval true The job body should stop its work loop and return to the caller.
203 * @retval false Otherwise.
204 */
205static inline bool rtems_test_parallel_stop_job(
206  const rtems_test_parallel_context *ctx
207)
208{
209  return _Atomic_Load_ulong(&ctx->stop, ATOMIC_ORDER_RELAXED) != 0;
210}
211
212/**
213 * @brief Indicates if a worker is the master worker.
214 *
215 * The master worker is the thread that called rtems_test_parallel().
216 *
217 * @param[in] worker_index The worker index.
218 *
219 * @retval true This is the master worker.
220 * @retval false Otherwise.
221 */
222static inline bool rtems_test_parallel_is_master_worker(size_t worker_index)
223{
224  return worker_index == 0;
225}
226
227/**
228 * @brief Returns the task identifier for a worker.
229 *
230 * @param[in] ctx The parallel context.
231 * @param[in] worker_index The worker index.
232 *
233 * @return The task identifier of the worker.
234 */
235static inline rtems_id rtems_test_parallel_get_task_id(
236  const rtems_test_parallel_context *ctx,
237  size_t worker_index
238)
239{
240  return ctx->worker_ids[worker_index];
241}
242
243/**
244 * @brief Runs a bunch of jobs in parallel on all processors of the system.
245 *
246 * The worker tasks inherit the priority of the executing task.
247 *
248 * There are SMP barriers before and after the job body.
249 *
250 * @param[in] ctx The parallel context.
251 * @param[in] worker_setup Optional handler to setup a worker task before it is
252 *   started.
253 * @param[in] jobs The table of jobs.
254 * @param[in] job_count The count of jobs in the job table.
255 */
256void rtems_test_parallel(
257  rtems_test_parallel_context *ctx,
258  rtems_test_parallel_worker_setup worker_setup,
259  const rtems_test_parallel_job *jobs,
260  size_t job_count
261);
262
263/**
264 * @brief Performs a busy loop with the specified iteration count.
265 *
266 * This function is optimized to not perform memory accesses and should have a
267 * small jitter.
268 *
269 * @param[in] count The iteration count.
270 */
271void rtems_test_busy(uint_fast32_t count);
272
273/**
274 * @brief Returns a count value for rtems_test_busy() which yields roughly a
275 * duration of one clock tick.
276 */
277uint_fast32_t rtems_test_get_one_tick_busy_count(void);
278
279/** @} */
280
281#ifdef __cplusplus
282}
283#endif /* __cplusplus */
284
285#endif /* _RTEMS_TEST_H */
Note: See TracBrowser for help on using the repository browser.