source: rtems/testsuites/smptests/smplock01/init.c @ 28779c7

4.11
Last change on this file since 28779c7 was 28779c7, checked in by Sebastian Huber <sebastian.huber@…>, on Mar 7, 2014 at 11:53:41 AM

score: Add function to destroy SMP locks

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