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

4.115
Last change on this file since edde99b was edde99b, checked in by Sebastian Huber <sebastian.huber@…>, on 06/14/13 at 12:26:34

score: Rename rtems_smp_get_number_of_processors()

Rename in rtems_smp_get_processor_count(). Always provide
<rtems/score/smp.h> and <rtems/rtems/smp.h>. Add
_SMP_Get_processor_count(). This function will be a compile time
constant defined to be one on uni-processor configurations. This allows
iterations over all processors without overhead on uni-processor
configurations.

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