source: rtems/cpukit/libmisc/testsupport/testparallel.c @ 7f577d3

4.115
Last change on this file since 7f577d3 was 7f577d3, checked in by Alexander Krutwig <alexander.krutwig@…>, on 03/05/15 at 08:06:44

tests: Refactor parallel test execution

  • Property mode set to 100644
File size: 3.6 KB
Line 
1/*
2 * Copyright (c) 2013-2015 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
16#ifdef HAVE_CONFIG_H
17  #include "config.h"
18#endif
19
20#include <rtems/test.h>
21#include <rtems/score/assert.h>
22#include <rtems.h>
23
24static void stop_worker_timer(rtems_id timer_id, void *arg)
25{
26  rtems_test_parallel_context *ctx = arg;
27
28  _Atomic_Store_ulong(&ctx->stop, 1, ATOMIC_ORDER_RELAXED);
29}
30
31static void start_worker_stop_timer(
32  rtems_test_parallel_context *ctx,
33  rtems_interval duration
34)
35{
36  rtems_status_code sc;
37
38  _Atomic_Store_ulong(&ctx->stop, 0, ATOMIC_ORDER_RELEASE);
39
40  sc = rtems_timer_fire_after(
41    ctx->stop_worker_timer_id,
42    duration,
43    stop_worker_timer,
44    ctx
45  );
46  _Assert(sc == RTEMS_SUCCESSFUL);
47}
48
49static void run_tests(
50  rtems_test_parallel_context *ctx,
51  const rtems_test_parallel_job *jobs,
52  size_t job_count,
53  size_t worker_index
54)
55{
56  SMP_barrier_State bs = SMP_BARRIER_STATE_INITIALIZER;
57  size_t i;
58
59  for (i = 0; i < job_count; ++i) {
60    const rtems_test_parallel_job *job = &jobs[i];
61
62    if (rtems_test_parallel_is_master_worker(worker_index)) {
63      rtems_interval duration = (*job->init)(ctx, job->arg);
64
65      start_worker_stop_timer(ctx, duration);
66    }
67
68    _SMP_barrier_Wait(&ctx->barrier, &bs, ctx->worker_count);
69
70    (*job->body)(ctx, job->arg, worker_index);
71
72    _SMP_barrier_Wait(&ctx->barrier, &bs, ctx->worker_count);
73
74    if (rtems_test_parallel_is_master_worker(worker_index)) {
75      (*job->fini)(ctx, job->arg);
76    }
77  }
78}
79
80typedef struct {
81  rtems_test_parallel_context *ctx;
82  const rtems_test_parallel_job *jobs;
83  size_t job_count;
84  size_t worker_index;
85} worker_arg;
86
87static void worker_task(rtems_task_argument arg)
88{
89  worker_arg warg = *(worker_arg *) arg;
90  rtems_status_code sc;
91
92  sc = rtems_event_transient_send(warg.ctx->master_id);
93  _Assert(sc == RTEMS_SUCCESSFUL);
94
95  run_tests(warg.ctx, warg.jobs, warg.job_count, warg.worker_index);
96
97  rtems_task_delete(RTEMS_SELF);
98}
99
100void rtems_test_parallel(
101  rtems_test_parallel_context *ctx,
102  rtems_task_priority non_master_worker_priority,
103  const rtems_test_parallel_job *jobs,
104  size_t job_count
105)
106{
107  rtems_status_code sc;
108  size_t worker_index;
109
110  _Atomic_Init_ulong(&ctx->stop, 0);
111  _SMP_barrier_Control_initialize(&ctx->barrier);
112  ctx->worker_count = rtems_get_processor_count();
113  ctx->master_id = rtems_task_self();
114
115  sc = rtems_timer_create(
116    rtems_build_name('S', 'T', 'O', 'P'),
117    &ctx->stop_worker_timer_id
118  );
119  if (sc != RTEMS_SUCCESSFUL) {
120    rtems_fatal_error_occurred(sc);
121  }
122
123  for (worker_index = 1; worker_index < ctx->worker_count; ++worker_index) {
124    worker_arg warg = {
125      .ctx = ctx,
126      .jobs = jobs,
127      .job_count = job_count,
128      .worker_index = worker_index
129    };
130    rtems_id worker_id;
131
132    sc = rtems_task_create(
133      rtems_build_name('W', 'O', 'R', 'K'),
134      non_master_worker_priority,
135      RTEMS_MINIMUM_STACK_SIZE,
136      RTEMS_DEFAULT_MODES,
137      RTEMS_DEFAULT_ATTRIBUTES,
138      &worker_id
139    );
140    if (sc != RTEMS_SUCCESSFUL) {
141      rtems_fatal_error_occurred(sc);
142    }
143
144    sc = rtems_task_start(worker_id, worker_task, (rtems_task_argument) &warg);
145    _Assert(sc == RTEMS_SUCCESSFUL);
146
147    sc = rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT);
148    _Assert(sc == RTEMS_SUCCESSFUL);
149  }
150
151  run_tests(ctx, jobs, job_count, 0);
152
153  sc = rtems_timer_delete(ctx->stop_worker_timer_id);
154  _Assert(sc == RTEMS_SUCCESSFUL);
155}
Note: See TracBrowser for help on using the repository browser.