source: rtems/testsuites/smptests/smpatomic01/init.c @ 7f577d3

4.115
Last change on this file since 7f577d3 was 7f577d3, checked in by Alexander Krutwig <alexander.krutwig@…>, on Mar 5, 2015 at 8:06:44 AM

tests: Refactor parallel test execution

  • Property mode set to 100644
File size: 9.5 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 * Copyright (c) 2013 Deng Hengyi.
11 *
12 * The license and distribution terms for this file may be
13 * found in the file LICENSE in this distribution or at
14 * http://www.rtems.org/license/LICENSE.
15 */
16
17#ifdef HAVE_CONFIG_H
18  #include "config.h"
19#endif
20
21#include <rtems/score/atomic.h>
22#include <rtems.h>
23#include <rtems/test.h>
24#include <limits.h>
25#include <string.h>
26
27#include "tmacros.h"
28
29const char rtems_test_name[] = "SMPATOMIC 1";
30
31#define MASTER_PRIORITY 1
32
33#define WORKER_PRIORITY 2
34
35#define CPU_COUNT 32
36
37typedef struct {
38  rtems_test_parallel_context base;
39  Atomic_Uint atomic_int_value;
40  Atomic_Ulong atomic_value;
41  unsigned long per_worker_value[CPU_COUNT];
42  unsigned long normal_value;
43  char unused_space_for_cache_line_separation[128];
44  unsigned long second_value;
45  Atomic_Flag global_flag;
46} smpatomic01_context;
47
48static smpatomic01_context test_instance;
49
50static rtems_interval test_duration(void)
51{
52  return rtems_clock_get_ticks_per_second();
53}
54
55static void test_fini(
56  smpatomic01_context *ctx,
57  const char *test,
58  bool atomic
59)
60{
61  unsigned long expected_value = 0;
62  unsigned long actual_value;
63  size_t worker_index;
64
65  printf("=== atomic %s test case ===\n", test);
66
67  for (
68    worker_index = 0;
69    worker_index < ctx->base.worker_count;
70    ++worker_index
71  ) {
72    unsigned long worker_value = ctx->per_worker_value[worker_index];
73
74    expected_value += worker_value;
75
76    printf(
77      "worker %zu value: %lu\n",
78      worker_index,
79      worker_value
80    );
81  }
82
83  if (atomic) {
84    actual_value = _Atomic_Load_ulong(&ctx->atomic_value, ATOMIC_ORDER_RELAXED);
85  } else {
86    actual_value = ctx->normal_value;
87  }
88
89  printf(
90    "atomic value: expected = %lu, actual = %lu\n",
91    expected_value,
92    actual_value
93  );
94
95  rtems_test_assert(expected_value == actual_value);
96}
97
98
99static rtems_interval test_atomic_add_init(
100  rtems_test_parallel_context *base,
101  void *arg
102)
103{
104  smpatomic01_context *ctx = (smpatomic01_context *) base;
105
106  _Atomic_Init_ulong(&ctx->atomic_value, 0);
107
108  return test_duration();
109}
110
111static void test_atomic_add_body(
112  rtems_test_parallel_context *base,
113  void *arg,
114  size_t worker_index
115)
116{
117  smpatomic01_context *ctx = (smpatomic01_context *) base;
118  unsigned long counter = 0;
119
120  while (!rtems_test_parallel_stop_job(&ctx->base)) {
121    ++counter;
122    _Atomic_Fetch_add_ulong(&ctx->atomic_value, 1, ATOMIC_ORDER_RELAXED);
123  }
124
125  ctx->per_worker_value[worker_index] = counter;
126}
127
128static void test_atomic_add_fini(rtems_test_parallel_context *base, void *arg)
129{
130  smpatomic01_context *ctx = (smpatomic01_context *) base;
131
132  test_fini(ctx, "add", true);
133}
134
135static rtems_interval test_atomic_flag_init(
136  rtems_test_parallel_context *base,
137  void *arg
138)
139{
140  smpatomic01_context *ctx = (smpatomic01_context *) base;
141
142  _Atomic_Flag_clear(&ctx->global_flag, ATOMIC_ORDER_RELEASE);
143  ctx->normal_value = 0;
144
145  return test_duration();
146}
147
148static void test_atomic_flag_body(
149  rtems_test_parallel_context *base,
150  void *arg,
151  size_t worker_index
152)
153{
154  smpatomic01_context *ctx = (smpatomic01_context *) base;
155  unsigned long counter = 0;
156
157  while (!rtems_test_parallel_stop_job(&ctx->base)) {
158    while (_Atomic_Flag_test_and_set(&ctx->global_flag, ATOMIC_ORDER_ACQUIRE)) {
159      /* Wait */
160    }
161
162    ++counter;
163    ++ctx->normal_value;
164
165    _Atomic_Flag_clear(&ctx->global_flag, ATOMIC_ORDER_RELEASE);
166  }
167
168  ctx->per_worker_value[worker_index] = counter;
169}
170
171static void test_atomic_flag_fini(rtems_test_parallel_context *base, void *arg)
172{
173  smpatomic01_context *ctx = (smpatomic01_context *) base;
174
175  test_fini(ctx, "flag", false);
176}
177
178static rtems_interval test_atomic_sub_init(
179  rtems_test_parallel_context *base,
180  void *arg
181)
182{
183  smpatomic01_context *ctx = (smpatomic01_context *) base;
184
185  _Atomic_Init_ulong(&ctx->atomic_value, 0);
186
187  return test_duration();
188}
189
190static void test_atomic_sub_body(
191  rtems_test_parallel_context *base,
192  void *arg,
193  size_t worker_index
194)
195{
196  smpatomic01_context *ctx = (smpatomic01_context *) base;
197  unsigned long counter = 0;
198
199  while (!rtems_test_parallel_stop_job(&ctx->base)) {
200    --counter;
201    _Atomic_Fetch_sub_ulong(&ctx->atomic_value, 1, ATOMIC_ORDER_RELAXED);
202  }
203
204  ctx->per_worker_value[worker_index] = counter;
205}
206
207static void test_atomic_sub_fini(rtems_test_parallel_context *base, void *arg)
208{
209  smpatomic01_context *ctx = (smpatomic01_context *) base;
210
211  test_fini(ctx, "sub", true);
212}
213
214static rtems_interval test_atomic_compare_exchange_init(
215  rtems_test_parallel_context *base,
216  void *arg
217)
218{
219  smpatomic01_context *ctx = (smpatomic01_context *) base;
220
221  _Atomic_Init_ulong(&ctx->atomic_value, 0);
222  ctx->normal_value = 0;
223
224  return test_duration();
225}
226
227static void test_atomic_compare_exchange_body(
228  rtems_test_parallel_context *base,
229  void *arg,
230  size_t worker_index
231)
232{
233  smpatomic01_context *ctx = (smpatomic01_context *) base;
234  unsigned long counter = 0;
235
236  while (!rtems_test_parallel_stop_job(&ctx->base)) {
237    bool success;
238
239    do {
240      unsigned long zero = 0;
241
242      success = _Atomic_Compare_exchange_ulong(
243        &ctx->atomic_value,
244        &zero,
245        1,
246        ATOMIC_ORDER_ACQUIRE,
247        ATOMIC_ORDER_RELAXED
248      );
249    } while (!success);
250
251    ++counter;
252    ++ctx->normal_value;
253
254    _Atomic_Store_ulong(&ctx->atomic_value, 0, ATOMIC_ORDER_RELEASE);
255  }
256
257  ctx->per_worker_value[worker_index] = counter;
258}
259
260static void test_atomic_compare_exchange_fini(
261  rtems_test_parallel_context *base,
262  void *arg
263)
264{
265  smpatomic01_context *ctx = (smpatomic01_context *) base;
266
267  test_fini(ctx, "compare exchange", false);
268}
269
270static rtems_interval test_atomic_or_and_init(
271  rtems_test_parallel_context *base,
272  void *arg
273)
274{
275  smpatomic01_context *ctx = (smpatomic01_context *) base;
276
277  _Atomic_Init_ulong(&ctx->atomic_value, 0);
278
279  return test_duration();
280}
281
282static void test_atomic_or_and_body(
283  rtems_test_parallel_context *base,
284  void *arg,
285  size_t worker_index
286)
287{
288  smpatomic01_context *ctx = (smpatomic01_context *) base;
289  unsigned long the_bit = 1UL << worker_index;
290  unsigned long current_bit = 0;
291
292  while (!rtems_test_parallel_stop_job(&ctx->base)) {
293    unsigned long previous;
294
295    if (current_bit != 0) {
296      previous = _Atomic_Fetch_and_ulong(
297        &ctx->atomic_value,
298        ~the_bit,
299        ATOMIC_ORDER_RELAXED
300      );
301      current_bit = 0;
302    } else {
303      previous = _Atomic_Fetch_or_ulong(
304        &ctx->atomic_value,
305        the_bit,
306        ATOMIC_ORDER_RELAXED
307      );
308      current_bit = the_bit;
309    }
310
311    rtems_test_assert((previous & the_bit) != current_bit);
312  }
313
314  ctx->per_worker_value[worker_index] = current_bit;
315}
316
317static void test_atomic_or_and_fini(
318  rtems_test_parallel_context *base,
319  void *arg
320)
321{
322  smpatomic01_context *ctx = (smpatomic01_context *) base;
323
324  test_fini(ctx, "or/and", true);
325}
326
327static rtems_interval test_atomic_fence_init(
328  rtems_test_parallel_context *base,
329  void *arg
330)
331{
332  smpatomic01_context *ctx = (smpatomic01_context *) base;
333
334  ctx->normal_value = 0;
335  ctx->second_value = 0;
336  _Atomic_Fence(ATOMIC_ORDER_RELEASE);
337
338  return test_duration();
339}
340
341static void test_atomic_fence_body(
342  rtems_test_parallel_context *base,
343  void *arg,
344  size_t worker_index
345)
346{
347  smpatomic01_context *ctx = (smpatomic01_context *) base;
348
349  if (rtems_test_parallel_is_master_worker(worker_index)) {
350    unsigned long counter = 0;
351
352    while (!rtems_test_parallel_stop_job(&ctx->base)) {
353      ++counter;
354      ctx->normal_value = counter;
355      _Atomic_Fence(ATOMIC_ORDER_RELEASE);
356      ctx->second_value = counter;
357    }
358  } else {
359    while (!rtems_test_parallel_stop_job(&ctx->base)) {
360      unsigned long n;
361      unsigned long s;
362
363      s = ctx->second_value;
364      _Atomic_Fence(ATOMIC_ORDER_ACQUIRE);
365      n = ctx->normal_value;
366
367      rtems_test_assert(n - s < LONG_MAX);
368    }
369  }
370}
371
372static void test_atomic_fence_fini(rtems_test_parallel_context *base, void *arg)
373{
374  smpatomic01_context *ctx = (smpatomic01_context *) base;
375
376  printf(
377    "=== atomic fence test case ===\n"
378    "normal value = %lu, second value = %lu\n",
379    ctx->normal_value,
380    ctx->second_value
381  );
382}
383
384static const rtems_test_parallel_job test_jobs[] = {
385  {
386    test_atomic_add_init,
387    test_atomic_add_body,
388    test_atomic_add_fini
389  }, {
390    test_atomic_flag_init,
391    test_atomic_flag_body,
392    test_atomic_flag_fini
393  }, {
394    test_atomic_sub_init,
395    test_atomic_sub_body,
396    test_atomic_sub_fini
397  }, {
398    test_atomic_compare_exchange_init,
399    test_atomic_compare_exchange_body,
400    test_atomic_compare_exchange_fini
401  }, {
402    test_atomic_or_and_init,
403    test_atomic_or_and_body,
404    test_atomic_or_and_fini
405  }, {
406    test_atomic_fence_init,
407    test_atomic_fence_body,
408    test_atomic_fence_fini
409  },
410};
411
412static void Init(rtems_task_argument arg)
413{
414  smpatomic01_context *ctx = &test_instance;
415
416  TEST_BEGIN();
417
418  rtems_test_parallel(
419    &ctx->base,
420    WORKER_PRIORITY,
421    &test_jobs[0],
422    RTEMS_ARRAY_SIZE(test_jobs)
423  );
424
425  TEST_END();
426  rtems_test_exit(0);
427}
428
429#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
430#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
431
432#define CONFIGURE_SMP_APPLICATION
433
434#define CONFIGURE_SMP_MAXIMUM_PROCESSORS CPU_COUNT
435
436#define CONFIGURE_MAXIMUM_TASKS CPU_COUNT
437
438#define CONFIGURE_MAXIMUM_TIMERS 1
439
440#define CONFIGURE_INIT_TASK_PRIORITY MASTER_PRIORITY
441#define CONFIGURE_INIT_TASK_INITIAL_MODES RTEMS_DEFAULT_MODES
442#define CONFIGURE_INIT_TASK_ATTRIBUTES RTEMS_DEFAULT_ATTRIBUTES
443
444#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
445
446#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
447
448#define CONFIGURE_INIT
449
450#include <rtems/confdefs.h>
Note: See TracBrowser for help on using the repository browser.