source: rtems/testsuites/smptests/smplock01/init.c @ ad48ebb

4.115
Last change on this file since ad48ebb was ad48ebb, checked in by Sebastian Huber <sebastian.huber@…>, on 03/17/14 at 07:10:19

tests/smptests: Use <rtems/test.h>

  • Property mode set to 100644
File size: 7.9 KB
Line 
1/*
2 * Copyright (c) 2013-2014 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.com/license/LICENSE.
13 */
14
15#ifdef HAVE_CONFIG_H
16  #include "config.h"
17#endif
18
19#include <rtems/score/smplock.h>
20#include <rtems/score/smpbarrier.h>
21#include <rtems/score/atomic.h>
22#include <rtems.h>
23
24#include "tmacros.h"
25
26const char rtems_test_name[] = "SMPLOCK 1";
27
28#define TASK_PRIORITY 1
29
30#define CPU_COUNT 32
31
32#define TEST_COUNT 5
33
34typedef enum {
35  INITIAL,
36  START_TEST,
37  STOP_TEST
38} states;
39
40typedef struct {
41  Atomic_Uint state;
42  SMP_barrier_Control barrier;
43  rtems_id timer_id;
44  rtems_interval timeout;
45  unsigned long counter[TEST_COUNT];
46  unsigned long test_counter[TEST_COUNT][CPU_COUNT];
47  SMP_lock_Control lock;
48} global_context;
49
50static global_context context = {
51  .state = ATOMIC_INITIALIZER_UINT(INITIAL),
52  .barrier = SMP_BARRIER_CONTROL_INITIALIZER,
53  .lock = SMP_LOCK_INITIALIZER("global")
54};
55
56static const char *test_names[TEST_COUNT] = {
57  "aquire global lock with local counter",
58  "aquire global lock with global counter",
59  "aquire local lock with local counter",
60  "aquire local lock with global counter",
61  "aquire global lock with busy section"
62};
63
64static void stop_test_timer(rtems_id timer_id, void *arg)
65{
66  global_context *ctx = arg;
67
68  _Atomic_Store_uint(&ctx->state, STOP_TEST, ATOMIC_ORDER_RELEASE);
69}
70
71static void wait_for_state(global_context *ctx, int desired_state)
72{
73  while (
74    _Atomic_Load_uint(&ctx->state, ATOMIC_ORDER_ACQUIRE) != desired_state
75  ) {
76    /* Wait */
77  }
78}
79
80static bool assert_state(global_context *ctx, int desired_state)
81{
82  return _Atomic_Load_uint(&ctx->state, ATOMIC_ORDER_RELAXED) == desired_state;
83}
84
85typedef void (*test_body)(
86  int test,
87  global_context *ctx,
88  SMP_barrier_State *bs,
89  unsigned int cpu_count,
90  unsigned int cpu_self
91);
92
93static void test_0_body(
94  int test,
95  global_context *ctx,
96  SMP_barrier_State *bs,
97  unsigned int cpu_count,
98  unsigned int cpu_self
99)
100{
101  unsigned long counter = 0;
102  SMP_lock_Context lock_context;
103
104  while (assert_state(ctx, START_TEST)) {
105    _SMP_lock_Acquire(&ctx->lock, &lock_context);
106    _SMP_lock_Release(&ctx->lock, &lock_context);
107    ++counter;
108  }
109
110  ctx->test_counter[test][cpu_self] = counter;
111}
112
113static void test_1_body(
114  int test,
115  global_context *ctx,
116  SMP_barrier_State *bs,
117  unsigned int cpu_count,
118  unsigned int cpu_self
119)
120{
121  unsigned long counter = 0;
122  SMP_lock_Context lock_context;
123
124  while (assert_state(ctx, START_TEST)) {
125    _SMP_lock_Acquire(&ctx->lock, &lock_context);
126    ++ctx->counter[test];
127    _SMP_lock_Release(&ctx->lock, &lock_context);
128    ++counter;
129  }
130
131  ctx->test_counter[test][cpu_self] = counter;
132}
133
134static void test_2_body(
135  int test,
136  global_context *ctx,
137  SMP_barrier_State *bs,
138  unsigned int cpu_count,
139  unsigned int cpu_self
140)
141{
142  unsigned long counter = 0;
143  SMP_lock_Control lock;
144  SMP_lock_Context lock_context;
145
146  _SMP_lock_Initialize(&lock, "local");
147
148  while (assert_state(ctx, START_TEST)) {
149    _SMP_lock_Acquire(&lock, &lock_context);
150    _SMP_lock_Release(&lock, &lock_context);
151    ++counter;
152  }
153
154  _SMP_lock_Destroy(&lock);
155
156  ctx->test_counter[test][cpu_self] = counter;
157}
158
159static void test_3_body(
160  int test,
161  global_context *ctx,
162  SMP_barrier_State *bs,
163  unsigned int cpu_count,
164  unsigned int cpu_self
165)
166{
167  unsigned long counter = 0;
168  SMP_lock_Control lock;
169  SMP_lock_Context lock_context;
170
171  _SMP_lock_Initialize(&lock, "local");
172
173  while (assert_state(ctx, START_TEST)) {
174    _SMP_lock_Acquire(&lock, &lock_context);
175
176    /* The counter value is not interesting, only the access to it */
177    ++ctx->counter[test];
178
179    _SMP_lock_Release(&lock, &lock_context);
180    ++counter;
181  }
182
183  _SMP_lock_Destroy(&lock);
184
185  ctx->test_counter[test][cpu_self] = counter;
186}
187
188static void busy_section(void)
189{
190  int i;
191
192  for (i = 0; i < 101; ++i) {
193    RTEMS_COMPILER_MEMORY_BARRIER();
194  }
195}
196
197static void test_4_body(
198  int test,
199  global_context *ctx,
200  SMP_barrier_State *bs,
201  unsigned int cpu_count,
202  unsigned int cpu_self
203)
204{
205  unsigned long counter = 0;
206  SMP_lock_Context lock_context;
207
208  while (assert_state(ctx, START_TEST)) {
209    _SMP_lock_Acquire(&ctx->lock, &lock_context);
210    busy_section();
211    _SMP_lock_Release(&ctx->lock, &lock_context);
212    ++counter;
213  }
214
215  ctx->test_counter[test][cpu_self] = counter;
216}
217
218static const test_body test_bodies[TEST_COUNT] = {
219  test_0_body,
220  test_1_body,
221  test_2_body,
222  test_3_body,
223  test_4_body
224};
225
226static void run_tests(
227  global_context *ctx,
228  SMP_barrier_State *bs,
229  unsigned int cpu_count,
230  unsigned int cpu_self,
231  bool master
232)
233{
234  int test;
235
236  for (test = 0; test < TEST_COUNT; ++test) {
237    _SMP_barrier_Wait(&ctx->barrier, bs, cpu_count);
238
239    if (master) {
240      rtems_status_code sc = rtems_timer_fire_after(
241        ctx->timer_id,
242        ctx->timeout,
243        stop_test_timer,
244        ctx
245      );
246      rtems_test_assert(sc == RTEMS_SUCCESSFUL);
247
248      _Atomic_Store_uint(&ctx->state, START_TEST, ATOMIC_ORDER_RELEASE);
249    }
250
251    wait_for_state(ctx, START_TEST);
252
253    (*test_bodies[test])(test, ctx, bs, cpu_count, cpu_self);
254  }
255
256  _SMP_barrier_Wait(&ctx->barrier, bs, cpu_count);
257}
258
259static void task(rtems_task_argument arg)
260{
261  global_context *ctx = (global_context *) arg;
262  uint32_t cpu_count = rtems_smp_get_processor_count();
263  uint32_t cpu_self = rtems_smp_get_current_processor();
264  rtems_status_code sc;
265  SMP_barrier_State bs = SMP_BARRIER_STATE_INITIALIZER;
266
267  run_tests(ctx, &bs, cpu_count, cpu_self, false);
268
269  sc = rtems_task_suspend(RTEMS_SELF);
270  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
271}
272
273static void test(void)
274{
275  global_context *ctx = &context;
276  uint32_t cpu_count = rtems_smp_get_processor_count();
277  uint32_t cpu_self = rtems_smp_get_current_processor();
278  uint32_t cpu;
279  int test;
280  rtems_status_code sc;
281  SMP_barrier_State bs = SMP_BARRIER_STATE_INITIALIZER;
282
283  for (cpu = 0; cpu < cpu_count; ++cpu) {
284    if (cpu != cpu_self) {
285      rtems_id task_id;
286
287      sc = rtems_task_create(
288        rtems_build_name('T', 'A', 'S', 'K'),
289        TASK_PRIORITY,
290        RTEMS_MINIMUM_STACK_SIZE,
291        RTEMS_DEFAULT_MODES,
292        RTEMS_DEFAULT_ATTRIBUTES,
293        &task_id
294      );
295      rtems_test_assert(sc == RTEMS_SUCCESSFUL);
296
297      sc = rtems_task_start(task_id, task, (rtems_task_argument) ctx);
298      rtems_test_assert(sc == RTEMS_SUCCESSFUL);
299    }
300  }
301
302  ctx->timeout = 10 * rtems_clock_get_ticks_per_second();
303
304  sc = rtems_timer_create(rtems_build_name('T', 'I', 'M', 'R'), &ctx->timer_id);
305  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
306
307  run_tests(ctx, &bs, cpu_count, cpu_self, true);
308
309  for (test = 0; test < TEST_COUNT; ++test) {
310    unsigned long sum = 0;
311
312    printf("%s\n", test_names[test]);
313
314    for (cpu = 0; cpu < cpu_count; ++cpu) {
315      unsigned long local_counter = ctx->test_counter[test][cpu];
316
317      sum += local_counter;
318
319      printf(
320        "\tprocessor %" PRIu32 ", local counter %lu\n",
321        cpu,
322        local_counter
323      );
324    }
325
326    printf(
327      "\tglobal counter %lu, sum of local counter %lu\n",
328      ctx->counter[test],
329      sum
330    );
331  }
332}
333
334static void Init(rtems_task_argument arg)
335{
336  TEST_BEGIN();
337
338  test();
339
340  TEST_END();
341  rtems_test_exit(0);
342}
343
344#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
345#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
346
347#define CONFIGURE_SMP_APPLICATION
348
349#define CONFIGURE_SMP_MAXIMUM_PROCESSORS CPU_COUNT
350
351#define CONFIGURE_MAXIMUM_TASKS CPU_COUNT
352
353#define CONFIGURE_MAXIMUM_SEMAPHORES 1
354
355#define CONFIGURE_MAXIMUM_TIMERS 1
356
357#define CONFIGURE_INIT_TASK_PRIORITY TASK_PRIORITY
358#define CONFIGURE_INIT_TASK_INITIAL_MODES RTEMS_DEFAULT_MODES
359#define CONFIGURE_INIT_TASK_ATTRIBUTES RTEMS_DEFAULT_ATTRIBUTES
360
361#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
362
363#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
364
365#define CONFIGURE_INIT
366
367#include <rtems/confdefs.h>
Note: See TracBrowser for help on using the repository browser.