source: rtems/testsuites/smptests/smpload01/init.c @ b3613c3a

4.115
Last change on this file since b3613c3a was b3613c3a, checked in by Sebastian Huber <sebastian.huber@…>, on 04/16/14 at 10:34:07

smptests/smpload01: Reduce timeout value

Use events instead of suspend/resume.

  • Property mode set to 100644
File size: 9.8 KB
Line 
1/*
2 * Copyright (c) 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.org/license/LICENSE.
13 */
14
15#ifdef HAVE_CONFIG_H
16  #include "config.h"
17#endif
18
19#include "tmacros.h"
20
21#include <stdlib.h>
22#include <stdio.h>
23#include <inttypes.h>
24
25#include <rtems.h>
26#include <rtems/counter.h>
27#include <rtems/profiling.h>
28#include <rtems/score/smpbarrier.h>
29#include <rtems/score/smplock.h>
30
31const char rtems_test_name[] = "SMPLOAD 1";
32
33#define CPU_COUNT 32
34
35#define MAX_INHERIT_OBTAIN_COUNT CPU_COUNT
36
37#define SEM_WORKER_COUNT (3 * CPU_COUNT)
38
39#define INIT_PRIO 1
40
41#define INHERIT_RELEASE_PRIO_HIGH (INIT_PRIO + 1)
42
43#define INHERIT_OBTAIN_PRIO_BASE (INHERIT_RELEASE_PRIO_HIGH + 1)
44
45#define INHERIT_RELEASE_PRIO_LOW (INHERIT_OBTAIN_PRIO_BASE + MAX_INHERIT_OBTAIN_COUNT)
46
47#define LOAD_PRIO (INHERIT_RELEASE_PRIO_LOW + 1)
48
49#define SEM_WORKER_CEILING_PRIO (LOAD_PRIO + 1)
50
51#define SEM_WORKER_PRIO_BASE (SEM_WORKER_CEILING_PRIO + 1)
52
53typedef struct {
54  rtems_id main_task_id;
55  rtems_id inherit_release_task_id;
56  rtems_id inherit_main_obtain_task_id;
57  rtems_id sem_worker_sem_prio_inherit;
58  rtems_id sem_worker_sem_prio_ceiling;
59  rtems_id inherit_sem;
60  rtems_counter_ticks inherit_obtain_delay;
61  SMP_barrier_Control inherit_barrier;
62  uint64_t inherit_obtain_counter[MAX_INHERIT_OBTAIN_COUNT];
63  uint64_t inherit_release_counter;
64  uint64_t sem_worker_counter[SEM_WORKER_COUNT];
65} test_context;
66
67static test_context test_instance = {
68  .inherit_barrier = SMP_BARRIER_CONTROL_INITIALIZER
69};
70
71static uint32_t simple_random(uint32_t v)
72{
73  v *= 1664525;
74  v += 1013904223;
75
76  return v;
77}
78
79static void inherit_obtain_task(rtems_task_argument arg)
80{
81  test_context *ctx = &test_instance;
82  rtems_status_code sc;
83  SMP_barrier_State barrier_state = SMP_BARRIER_STATE_INITIALIZER;
84  uint32_t cpu_count = rtems_get_processor_count();
85  rtems_counter_ticks delay = (cpu_count - 1 - arg) * ctx->inherit_obtain_delay;
86
87  while (true) {
88    _SMP_barrier_Wait(&ctx->inherit_barrier, &barrier_state, cpu_count);
89
90    rtems_counter_delay_ticks(delay);
91
92    sc = rtems_semaphore_obtain(ctx->inherit_sem, RTEMS_WAIT, 1);
93    rtems_test_assert(sc == RTEMS_TIMEOUT);
94
95    _SMP_barrier_Wait(&ctx->inherit_barrier, &barrier_state, cpu_count);
96
97    ++ctx->inherit_obtain_counter[arg];
98
99    if (arg == 0) {
100      rtems_task_priority prio = INHERIT_RELEASE_PRIO_HIGH;
101
102      sc = rtems_task_set_priority(ctx->inherit_release_task_id, prio, &prio);
103      rtems_test_assert(sc == RTEMS_SUCCESSFUL);
104
105      sc = rtems_event_transient_send(ctx->inherit_release_task_id);
106      rtems_test_assert(sc == RTEMS_SUCCESSFUL);
107
108      sc = rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT);
109      rtems_test_assert(sc == RTEMS_SUCCESSFUL);
110    }
111  }
112}
113
114static void inherit_release_task(rtems_task_argument arg)
115{
116  test_context *ctx = &test_instance;
117  rtems_status_code sc;
118
119  sc = rtems_semaphore_obtain(
120    ctx->inherit_sem,
121    RTEMS_WAIT,
122    RTEMS_NO_TIMEOUT
123  );
124  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
125
126  sc = rtems_event_transient_send(ctx->main_task_id);
127  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
128
129  while (true) {
130    rtems_task_priority prio = INHERIT_RELEASE_PRIO_LOW;
131
132    sc = rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT);
133    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
134
135    sc = rtems_semaphore_release(ctx->inherit_sem);
136    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
137
138    ++ctx->inherit_release_counter;
139
140    sc = rtems_semaphore_obtain(
141      ctx->inherit_sem,
142      RTEMS_WAIT,
143      RTEMS_NO_TIMEOUT
144    );
145    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
146
147    sc = rtems_task_set_priority(RTEMS_SELF, prio, &prio);
148    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
149
150    sc = rtems_event_transient_send(ctx->inherit_main_obtain_task_id);
151    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
152  }
153}
154
155static void load_task(rtems_task_argument arg)
156{
157  size_t data_size;
158  volatile int *data;
159  volatile int dummy;
160  size_t n;
161
162  data_size = rtems_cache_get_data_cache_size(0);
163  if (data_size > 0) {
164    data = malloc(data_size);
165    rtems_test_assert(data != NULL);
166  } else {
167    data_size = sizeof(dummy);
168    data = &dummy;
169  }
170
171  n = data_size / sizeof(*data);
172  while (true) {
173    size_t i;
174
175    for (i = 0; i < n; ++i) {
176      data[i] = i;
177    }
178  }
179}
180
181static void sem_worker_task(rtems_task_argument arg)
182{
183  test_context *ctx = &test_instance;
184  uint32_t v = arg;
185
186  while (true) {
187    rtems_status_code sc;
188    rtems_id id;
189
190    v = simple_random(v);
191
192    if ((v & 0x80000000) != 0) {
193      id = ctx->sem_worker_sem_prio_inherit;
194    } else {
195      id = ctx->sem_worker_sem_prio_ceiling;
196    }
197
198    sc = rtems_semaphore_obtain(id, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
199    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
200
201    sc = rtems_task_wake_after(1);
202    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
203
204    sc = rtems_semaphore_release(id);
205    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
206
207    ++ctx->sem_worker_counter[arg];
208  }
209}
210
211static int cmp(const void *ap, const void *bp)
212{
213  const rtems_counter_ticks *a = ap;
214  const rtems_counter_ticks *b = bp;
215
216  return *a - *b;
217}
218
219static void get_obtain_delay_estimate(test_context *ctx)
220{
221  rtems_counter_ticks t[32];
222  SMP_lock_Control lock;
223  ISR_Level level;
224  size_t n = RTEMS_ARRAY_SIZE(t);
225  size_t i;
226
227  _SMP_lock_Initialize(&lock, "test");
228
229  _ISR_Disable_without_giant(level);
230
231  for (i = 0; i < n; ++i) {
232    SMP_lock_Context lock_context;
233    rtems_counter_ticks a;
234    rtems_counter_ticks b;
235
236    a = rtems_counter_read();
237    _SMP_lock_ISR_disable_and_acquire(&lock, &lock_context);
238    b = rtems_counter_read();
239    _SMP_lock_Release_and_ISR_enable(&lock, &lock_context);
240
241    t[i] = rtems_counter_difference(b, a);
242  }
243
244  _ISR_Enable_without_giant(level);
245
246  _SMP_lock_Destroy(&lock);
247
248  qsort(&t[0], n, sizeof(t[0]), cmp);
249
250  ctx->inherit_obtain_delay = t[n / 2];
251}
252
253static void test(void)
254{
255  test_context *ctx = &test_instance;
256  uint32_t i;
257  rtems_status_code sc;
258  rtems_id id;
259
260  ctx->main_task_id = rtems_task_self();
261
262  get_obtain_delay_estimate(ctx);
263
264  sc = rtems_semaphore_create(
265    rtems_build_name('S', 'E', 'M', 'I'),
266    1,
267    RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY,
268    0,
269    &ctx->sem_worker_sem_prio_inherit
270  );
271  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
272
273  sc = rtems_semaphore_create(
274    rtems_build_name('S', 'E', 'M', 'C'),
275    1,
276    RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_PRIORITY_CEILING,
277    SEM_WORKER_CEILING_PRIO,
278    &ctx->sem_worker_sem_prio_ceiling
279  );
280  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
281
282  sc = rtems_semaphore_create(
283    rtems_build_name('I', 'N', 'H', 'E'),
284    1,
285    RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY,
286    0,
287    &ctx->inherit_sem
288  );
289  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
290
291  for (i = 0; i < SEM_WORKER_COUNT; ++i) {
292    sc = rtems_task_create(
293      rtems_build_name('S', 'E', 'M', 'W'),
294      SEM_WORKER_PRIO_BASE + i,
295      RTEMS_MINIMUM_STACK_SIZE,
296      RTEMS_DEFAULT_MODES,
297      RTEMS_DEFAULT_ATTRIBUTES,
298      &id
299    );
300    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
301
302    sc = rtems_task_start(id, sem_worker_task, i);
303    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
304  }
305
306  sc = rtems_task_create(
307    rtems_build_name('L', 'O', 'A', 'D'),
308    LOAD_PRIO,
309    RTEMS_MINIMUM_STACK_SIZE,
310    RTEMS_DEFAULT_MODES,
311    RTEMS_DEFAULT_ATTRIBUTES,
312    &id
313  );
314  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
315
316  sc = rtems_task_start(id, load_task, 0);
317  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
318
319  sc = rtems_task_create(
320    rtems_build_name('I', 'N', 'H', 'R'),
321    INHERIT_RELEASE_PRIO_LOW,
322    RTEMS_MINIMUM_STACK_SIZE,
323    RTEMS_DEFAULT_MODES,
324    RTEMS_DEFAULT_ATTRIBUTES,
325    &id
326  );
327  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
328
329  ctx->inherit_release_task_id = id;
330
331  sc = rtems_task_start(id, inherit_release_task, 0);
332  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
333
334  sc = rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT);
335  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
336
337  for (i = 0; i < rtems_get_processor_count(); ++i) {
338    sc = rtems_task_create(
339      rtems_build_name('I', 'N', 'H', 'O'),
340      INHERIT_OBTAIN_PRIO_BASE + i,
341      RTEMS_MINIMUM_STACK_SIZE,
342      RTEMS_DEFAULT_MODES,
343      RTEMS_DEFAULT_ATTRIBUTES,
344      &id
345    );
346    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
347
348    if (i == 0) {
349      ctx->inherit_main_obtain_task_id = id;
350    }
351
352    sc = rtems_task_start(id, inherit_obtain_task, i);
353    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
354  }
355
356  sc = rtems_task_wake_after(30 * rtems_clock_get_ticks_per_second());
357  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
358
359  for (i = 0; i < SEM_WORKER_COUNT; ++i) {
360    printf(
361      "semaphore worker count %2" PRIu32 ": %" PRIu64 "\n",
362      i,
363      ctx->sem_worker_counter[i]
364    );
365  }
366
367  printf(
368    "priority inheritance release count: %" PRIu64 "\n",
369    ctx->inherit_release_counter
370  );
371
372  for (i = 0; i < rtems_get_processor_count(); ++i) {
373    printf(
374      "priority inheritance obtain count %2" PRIu32 ": %" PRIu64 "\n",
375      i,
376      ctx->inherit_obtain_counter[i]
377    );
378  }
379
380  rtems_profiling_report_xml("SMPLOAD 1", rtems_printf_plugin, NULL, 1, "  ");
381}
382
383static void Init(rtems_task_argument arg)
384{
385  TEST_BEGIN();
386
387  test();
388
389  TEST_END();
390  rtems_test_exit(0);
391}
392
393#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
394#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
395
396#define CONFIGURE_MICROSECONDS_PER_TICK 1000
397
398#define CONFIGURE_SMP_APPLICATION
399
400#define CONFIGURE_SMP_MAXIMUM_PROCESSORS CPU_COUNT
401
402#define CONFIGURE_MAXIMUM_TASKS \
403  (1 + MAX_INHERIT_OBTAIN_COUNT + 1 + 1 + SEM_WORKER_COUNT)
404
405#define CONFIGURE_MAXIMUM_SEMAPHORES 3
406
407#define CONFIGURE_INIT_TASK_PRIORITY INIT_PRIO
408
409#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
410
411#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
412
413#define CONFIGURE_INIT
414
415#include <rtems/confdefs.h>
Note: See TracBrowser for help on using the repository browser.