source: rtems/testsuites/smptests/smpatomic01/init.c @ 33b72fd

4.115
Last change on this file since 33b72fd was 33b72fd, checked in by Alexander Krutwig <alexander.krutwig@…>, on 03/06/15 at 15:13:40

testsupport: Add cascade option to parallel test

  • Property mode set to 100644
File size: 10.1 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  size_t active_workers
103)
104{
105  smpatomic01_context *ctx = (smpatomic01_context *) base;
106
107  _Atomic_Init_ulong(&ctx->atomic_value, 0);
108
109  return test_duration();
110}
111
112static void test_atomic_add_body(
113  rtems_test_parallel_context *base,
114  void *arg,
115  size_t active_workers,
116  size_t worker_index
117)
118{
119  smpatomic01_context *ctx = (smpatomic01_context *) base;
120  unsigned long counter = 0;
121
122  while (!rtems_test_parallel_stop_job(&ctx->base)) {
123    ++counter;
124    _Atomic_Fetch_add_ulong(&ctx->atomic_value, 1, ATOMIC_ORDER_RELAXED);
125  }
126
127  ctx->per_worker_value[worker_index] = counter;
128}
129
130static void test_atomic_add_fini(
131  rtems_test_parallel_context *base,
132  void *arg,
133  size_t active_workers
134)
135{
136  smpatomic01_context *ctx = (smpatomic01_context *) base;
137
138  test_fini(ctx, "add", true);
139}
140
141static rtems_interval test_atomic_flag_init(
142  rtems_test_parallel_context *base,
143  void *arg,
144  size_t active_workers
145)
146{
147  smpatomic01_context *ctx = (smpatomic01_context *) base;
148
149  _Atomic_Flag_clear(&ctx->global_flag, ATOMIC_ORDER_RELEASE);
150  ctx->normal_value = 0;
151
152  return test_duration();
153}
154
155static void test_atomic_flag_body(
156  rtems_test_parallel_context *base,
157  void *arg,
158  size_t active_workers,
159  size_t worker_index
160)
161{
162  smpatomic01_context *ctx = (smpatomic01_context *) base;
163  unsigned long counter = 0;
164
165  while (!rtems_test_parallel_stop_job(&ctx->base)) {
166    while (_Atomic_Flag_test_and_set(&ctx->global_flag, ATOMIC_ORDER_ACQUIRE)) {
167      /* Wait */
168    }
169
170    ++counter;
171    ++ctx->normal_value;
172
173    _Atomic_Flag_clear(&ctx->global_flag, ATOMIC_ORDER_RELEASE);
174  }
175
176  ctx->per_worker_value[worker_index] = counter;
177}
178
179static void test_atomic_flag_fini(
180  rtems_test_parallel_context *base,
181  void *arg,
182  size_t active_workers
183  )
184{
185  smpatomic01_context *ctx = (smpatomic01_context *) base;
186
187  test_fini(ctx, "flag", false);
188}
189
190static rtems_interval test_atomic_sub_init(
191  rtems_test_parallel_context *base,
192  void *arg,
193  size_t active_workers
194)
195{
196  smpatomic01_context *ctx = (smpatomic01_context *) base;
197
198  _Atomic_Init_ulong(&ctx->atomic_value, 0);
199
200  return test_duration();
201}
202
203static void test_atomic_sub_body(
204  rtems_test_parallel_context *base,
205  void *arg,
206  size_t active_workers,
207  size_t worker_index
208)
209{
210  smpatomic01_context *ctx = (smpatomic01_context *) base;
211  unsigned long counter = 0;
212
213  while (!rtems_test_parallel_stop_job(&ctx->base)) {
214    --counter;
215    _Atomic_Fetch_sub_ulong(&ctx->atomic_value, 1, ATOMIC_ORDER_RELAXED);
216  }
217
218  ctx->per_worker_value[worker_index] = counter;
219}
220
221static void test_atomic_sub_fini(
222  rtems_test_parallel_context *base,
223  void *arg,
224  size_t active_workers
225)
226{
227  smpatomic01_context *ctx = (smpatomic01_context *) base;
228
229  test_fini(ctx, "sub", true);
230}
231
232static rtems_interval test_atomic_compare_exchange_init(
233  rtems_test_parallel_context *base,
234  void *arg,
235  size_t active_workers
236)
237{
238  smpatomic01_context *ctx = (smpatomic01_context *) base;
239
240  _Atomic_Init_ulong(&ctx->atomic_value, 0);
241  ctx->normal_value = 0;
242
243  return test_duration();
244}
245
246static void test_atomic_compare_exchange_body(
247  rtems_test_parallel_context *base,
248  void *arg,
249  size_t active_workers,
250  size_t worker_index
251)
252{
253  smpatomic01_context *ctx = (smpatomic01_context *) base;
254  unsigned long counter = 0;
255
256  while (!rtems_test_parallel_stop_job(&ctx->base)) {
257    bool success;
258
259    do {
260      unsigned long zero = 0;
261
262      success = _Atomic_Compare_exchange_ulong(
263        &ctx->atomic_value,
264        &zero,
265        1,
266        ATOMIC_ORDER_ACQUIRE,
267        ATOMIC_ORDER_RELAXED
268      );
269    } while (!success);
270
271    ++counter;
272    ++ctx->normal_value;
273
274    _Atomic_Store_ulong(&ctx->atomic_value, 0, ATOMIC_ORDER_RELEASE);
275  }
276
277  ctx->per_worker_value[worker_index] = counter;
278}
279
280static void test_atomic_compare_exchange_fini(
281  rtems_test_parallel_context *base,
282  void *arg,
283  size_t active_workers
284)
285{
286  smpatomic01_context *ctx = (smpatomic01_context *) base;
287
288  test_fini(ctx, "compare exchange", false);
289}
290
291static rtems_interval test_atomic_or_and_init(
292  rtems_test_parallel_context *base,
293  void *arg,
294  size_t active_workers
295)
296{
297  smpatomic01_context *ctx = (smpatomic01_context *) base;
298
299  _Atomic_Init_ulong(&ctx->atomic_value, 0);
300
301  return test_duration();
302}
303
304static void test_atomic_or_and_body(
305  rtems_test_parallel_context *base,
306  void *arg,
307  size_t active_workers,
308  size_t worker_index
309)
310{
311  smpatomic01_context *ctx = (smpatomic01_context *) base;
312  unsigned long the_bit = 1UL << worker_index;
313  unsigned long current_bit = 0;
314
315  while (!rtems_test_parallel_stop_job(&ctx->base)) {
316    unsigned long previous;
317
318    if (current_bit != 0) {
319      previous = _Atomic_Fetch_and_ulong(
320        &ctx->atomic_value,
321        ~the_bit,
322        ATOMIC_ORDER_RELAXED
323      );
324      current_bit = 0;
325    } else {
326      previous = _Atomic_Fetch_or_ulong(
327        &ctx->atomic_value,
328        the_bit,
329        ATOMIC_ORDER_RELAXED
330      );
331      current_bit = the_bit;
332    }
333
334    rtems_test_assert((previous & the_bit) != current_bit);
335  }
336
337  ctx->per_worker_value[worker_index] = current_bit;
338}
339
340static void test_atomic_or_and_fini(
341  rtems_test_parallel_context *base,
342  void *arg,
343  size_t active_workers
344)
345{
346  smpatomic01_context *ctx = (smpatomic01_context *) base;
347
348  test_fini(ctx, "or/and", true);
349}
350
351static rtems_interval test_atomic_fence_init(
352  rtems_test_parallel_context *base,
353  void *arg,
354  size_t active_workers
355)
356{
357  smpatomic01_context *ctx = (smpatomic01_context *) base;
358
359  ctx->normal_value = 0;
360  ctx->second_value = 0;
361  _Atomic_Fence(ATOMIC_ORDER_RELEASE);
362
363  return test_duration();
364}
365
366static void test_atomic_fence_body(
367  rtems_test_parallel_context *base,
368  void *arg,
369  size_t active_workers,
370  size_t worker_index
371)
372{
373  smpatomic01_context *ctx = (smpatomic01_context *) base;
374
375  if (rtems_test_parallel_is_master_worker(worker_index)) {
376    unsigned long counter = 0;
377
378    while (!rtems_test_parallel_stop_job(&ctx->base)) {
379      ++counter;
380      ctx->normal_value = counter;
381      _Atomic_Fence(ATOMIC_ORDER_RELEASE);
382      ctx->second_value = counter;
383    }
384  } else {
385    while (!rtems_test_parallel_stop_job(&ctx->base)) {
386      unsigned long n;
387      unsigned long s;
388
389      s = ctx->second_value;
390      _Atomic_Fence(ATOMIC_ORDER_ACQUIRE);
391      n = ctx->normal_value;
392
393      rtems_test_assert(n - s < LONG_MAX);
394    }
395  }
396}
397
398static void test_atomic_fence_fini(
399  rtems_test_parallel_context *base,
400  void *arg,
401  size_t active_workers
402)
403{
404  smpatomic01_context *ctx = (smpatomic01_context *) base;
405
406  printf(
407    "=== atomic fence test case ===\n"
408    "normal value = %lu, second value = %lu\n",
409    ctx->normal_value,
410    ctx->second_value
411  );
412}
413
414static const rtems_test_parallel_job test_jobs[] = {
415  {
416    .init = test_atomic_add_init,
417    .body = test_atomic_add_body,
418    .fini = test_atomic_add_fini
419  }, {
420    .init = test_atomic_flag_init,
421    .body =test_atomic_flag_body,
422    .fini =test_atomic_flag_fini
423  }, {
424    .init = test_atomic_sub_init,
425    .body =test_atomic_sub_body,
426    .fini =test_atomic_sub_fini
427  }, {
428    .init = test_atomic_compare_exchange_init,
429    .body =test_atomic_compare_exchange_body,
430    .fini =test_atomic_compare_exchange_fini
431  }, {
432    .init = test_atomic_or_and_init,
433    .body =test_atomic_or_and_body,
434    .fini =test_atomic_or_and_fini
435  }, {
436    .init = test_atomic_fence_init,
437    .body =test_atomic_fence_body,
438    .fini =test_atomic_fence_fini
439  },
440};
441
442static void Init(rtems_task_argument arg)
443{
444  smpatomic01_context *ctx = &test_instance;
445
446  TEST_BEGIN();
447
448  rtems_test_parallel(
449    &ctx->base,
450    WORKER_PRIORITY,
451    &test_jobs[0],
452    RTEMS_ARRAY_SIZE(test_jobs)
453  );
454
455  TEST_END();
456  rtems_test_exit(0);
457}
458
459#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
460#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
461
462#define CONFIGURE_SMP_APPLICATION
463
464#define CONFIGURE_SMP_MAXIMUM_PROCESSORS CPU_COUNT
465
466#define CONFIGURE_MAXIMUM_TASKS CPU_COUNT
467
468#define CONFIGURE_MAXIMUM_TIMERS 1
469
470#define CONFIGURE_INIT_TASK_PRIORITY MASTER_PRIORITY
471#define CONFIGURE_INIT_TASK_INITIAL_MODES RTEMS_DEFAULT_MODES
472#define CONFIGURE_INIT_TASK_ATTRIBUTES RTEMS_DEFAULT_ATTRIBUTES
473
474#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
475
476#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
477
478#define CONFIGURE_INIT
479
480#include <rtems/confdefs.h>
Note: See TracBrowser for help on using the repository browser.