source: rtems/testsuites/smptests/smpload01/init.c @ 4b04cb61

5
Last change on this file since 4b04cb61 was 4b04cb61, checked in by Sebastian Huber <sebastian.huber@…>, on 05/18/16 at 06:03:05

score: Rename _ISR_Disable_without_giant()

Rename _ISR_Disable_without_giant() into _ISR_Local_disable(). Rename
_ISR_Enable_without_giant() into _ISR_Local_enable().

This is a preparation to remove the Giant lock.

Update #2555.

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