source: rtems/testsuites/smptests/smpstrongapa01/init.c @ 4fe0e97f

5
Last change on this file since 4fe0e97f was 4fe0e97f, checked in by Sebastian Huber <sebastian.huber@…>, on 06/30/16 at 07:50:41

smptests/smpstrongapa01: Add test cases

  • Property mode set to 100644
File size: 7.7 KB
Line 
1/*
2 * Copyright (c) 2016 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 <rtems/score/threadimpl.h>
22
23const char rtems_test_name[] = "SMPSTRONGAPA 1";
24
25#define CPU_COUNT 4
26
27#define TASK_COUNT (3 * CPU_COUNT)
28
29#define P(i) (UINT32_C(2) + i)
30
31#define ALL ((UINT32_C(1) << CPU_COUNT) - 1)
32
33#define IDLE UINT8_C(255)
34
35#define NAME rtems_build_name('S', 'A', 'P', 'A')
36
37typedef struct {
38  enum {
39    KIND_RESET,
40    KIND_SET_PRIORITY,
41    KIND_SET_AFFINITY,
42    KIND_BLOCK,
43    KIND_UNBLOCK
44  } kind;
45
46  size_t index;
47
48  struct {
49    rtems_task_priority priority;
50    uint32_t cpu_set;
51  } data;
52
53  uint8_t expected_cpu_allocations[CPU_COUNT];
54} test_action;
55
56typedef struct {
57  rtems_id timer_id;
58  rtems_id master_id;
59  rtems_id task_ids[TASK_COUNT];
60  size_t action_index;
61} test_context;
62
63#define RESET \
64  { \
65    KIND_RESET, \
66    0, \
67    { 0 }, \
68    { IDLE, IDLE, IDLE, IDLE } \
69  }
70
71#define SET_PRIORITY(index, prio, cpu0, cpu1, cpu2, cpu3) \
72  { \
73    KIND_SET_PRIORITY, \
74    index, \
75    { .priority = prio }, \
76    { cpu0, cpu1, cpu2, cpu3 } \
77  }
78
79#define SET_AFFINITY(index, aff, cpu0, cpu1, cpu2, cpu3) \
80  { \
81    KIND_SET_AFFINITY, \
82    index, \
83    { .cpu_set = aff }, \
84    { cpu0, cpu1, cpu2, cpu3 } \
85  }
86
87#define BLOCK(index, cpu0, cpu1, cpu2, cpu3) \
88  { \
89    KIND_BLOCK, \
90    index, \
91    { 0 }, \
92    { cpu0, cpu1, cpu2, cpu3 } \
93  }
94
95#define UNBLOCK(index, cpu0, cpu1, cpu2, cpu3) \
96  { \
97    KIND_UNBLOCK, \
98    index, \
99    { 0 }, \
100    { cpu0, cpu1, cpu2, cpu3 } \
101  }
102
103static const test_action test_actions[] = {
104  RESET,
105  UNBLOCK(      0,           0, IDLE, IDLE, IDLE),
106  UNBLOCK(      1,           0,    1, IDLE, IDLE),
107  UNBLOCK(      2,           0,    1,    2, IDLE),
108  UNBLOCK(      3,           0,    1,    2,    3),
109  UNBLOCK(      5,           0,    1,    2,    3),
110  SET_PRIORITY( 3,  P(4),    0,    1,    2,    3),
111  SET_PRIORITY( 5,  P(3),    0,    1,    2,    5),
112  BLOCK(        5,           0,    1,    2,    3),
113  SET_AFFINITY( 5,   ALL,    0,    1,    2,    3),
114  RESET,
115  UNBLOCK(      0,           0, IDLE, IDLE, IDLE),
116  RESET
117};
118
119static test_context test_instance;
120
121static void set_priority(rtems_id id, rtems_task_priority prio)
122{
123  rtems_status_code sc;
124
125  sc = rtems_task_set_priority(id, prio, &prio);
126  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
127}
128
129static void set_affinity(rtems_id id, uint32_t cpu_set_32)
130{
131  rtems_status_code sc;
132  cpu_set_t cpu_set;
133  size_t i;
134
135  CPU_ZERO(&cpu_set);
136
137  for (i = 0; i < CPU_COUNT; ++i) {
138    uint32_t one;
139
140    one = 1;
141
142    if ((cpu_set_32 & (one << i)) != 0) {
143      CPU_SET(i, &cpu_set);
144    }
145  }
146
147  sc = rtems_task_set_affinity(id, sizeof(cpu_set), &cpu_set);
148  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
149}
150
151static void reset(test_context *ctx)
152{
153  rtems_status_code sc;
154  size_t i;
155
156  for (i = CPU_COUNT; i < TASK_COUNT; ++i) {
157    set_priority(ctx->task_ids[i], P(i));
158    set_affinity(ctx->task_ids[i], ALL);
159
160    sc = rtems_task_suspend(ctx->task_ids[i]);
161    rtems_test_assert(sc == RTEMS_SUCCESSFUL || sc == RTEMS_ALREADY_SUSPENDED);
162  }
163
164  for (i = 0; i < CPU_COUNT; ++i) {
165    set_priority(ctx->task_ids[i], P(i));
166
167    sc = rtems_task_resume(ctx->task_ids[i]);
168    rtems_test_assert(sc == RTEMS_SUCCESSFUL || sc == RTEMS_INCORRECT_STATE);
169  }
170
171  /* Order the idle threads explicitly */
172  for (i = 0; i < CPU_COUNT; ++i) {
173    const Per_CPU_Control *c;
174    const Thread_Control *h;
175
176    c = _Per_CPU_Get_by_index(CPU_COUNT - 1 - i);
177    h = c->heir;
178
179    sc = rtems_task_suspend(h->Object.id);
180    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
181  }
182}
183
184static void check_cpu_allocations(test_context *ctx, const test_action *action)
185{
186  size_t i;
187
188  for (i = 0; i < CPU_COUNT; ++i) {
189    size_t e;
190    const Per_CPU_Control *c;
191    const Thread_Control *h;
192
193    e = action->expected_cpu_allocations[i];
194    c = _Per_CPU_Get_by_index(i);
195    h = c->heir;
196
197    if (e != IDLE) {
198      rtems_test_assert(h->Object.id == ctx->task_ids[e]);
199    } else {
200      rtems_test_assert(h->Start.Entry.adaptor == _Thread_Entry_adaptor_idle);
201    }
202  }
203}
204
205/*
206 * Use a timer to execute the actions, since it runs with thread dispatching
207 * disabled.  This is necessary to check the expected processor allocations.
208 */
209static void timer(rtems_id id, void *arg)
210{
211  test_context *ctx;
212  rtems_status_code sc;
213  size_t i;
214
215  ctx = arg;
216  i = ctx->action_index;
217
218  if (i == 0) {
219    sc = rtems_task_suspend(ctx->master_id);
220    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
221  }
222
223  if (i < RTEMS_ARRAY_SIZE(test_actions)) {
224    const test_action *action = &test_actions[i];
225    rtems_id task;
226
227    ctx->action_index = i + 1;
228
229    task = ctx->task_ids[action->index];
230
231    switch (action->kind) {
232      case KIND_SET_PRIORITY:
233        set_priority(task, action->data.priority);
234        break;
235      case KIND_SET_AFFINITY:
236        set_affinity(task, action->data.cpu_set);
237        break;
238      case KIND_BLOCK:
239        sc = rtems_task_suspend(task);
240        rtems_test_assert(sc == RTEMS_SUCCESSFUL);
241        break;
242      case KIND_UNBLOCK:
243        sc = rtems_task_resume(task);
244        rtems_test_assert(sc == RTEMS_SUCCESSFUL);
245        break;
246      default:
247        rtems_test_assert(action->kind == KIND_RESET);
248        reset(ctx);
249        break;
250    }
251
252    check_cpu_allocations(ctx, action);
253
254    sc = rtems_timer_reset(id);
255    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
256  } else {
257    sc = rtems_task_resume(ctx->master_id);
258    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
259
260    sc = rtems_event_transient_send(ctx->master_id);
261    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
262  }
263}
264
265static void do_nothing_task(rtems_task_argument arg)
266{
267  (void) arg;
268
269  while (true) {
270    /* Do nothing */
271  }
272}
273
274static void test(void)
275{
276  test_context *ctx;
277  rtems_status_code sc;
278  size_t i;
279
280  ctx = &test_instance;
281
282  ctx->master_id = rtems_task_self();
283
284  for (i = 0; i < TASK_COUNT; ++i) {
285    sc = rtems_task_create(
286      NAME,
287      P(i),
288      RTEMS_MINIMUM_STACK_SIZE,
289      RTEMS_DEFAULT_MODES,
290      RTEMS_DEFAULT_ATTRIBUTES,
291      &ctx->task_ids[i]
292    );
293    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
294
295    sc = rtems_task_start(ctx->task_ids[i], do_nothing_task, 0);
296    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
297  }
298
299  sc = rtems_timer_create(NAME, &ctx->timer_id);
300  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
301
302  sc = rtems_timer_fire_after(ctx->timer_id, 1, timer, ctx);
303  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
304
305  sc = rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT);
306  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
307
308  for (i = 0; i < TASK_COUNT; ++i) {
309    sc = rtems_task_delete(ctx->task_ids[i]);
310    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
311  }
312
313  sc = rtems_timer_delete(ctx->timer_id);
314  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
315}
316
317static void Init(rtems_task_argument arg)
318{
319  TEST_BEGIN();
320
321  if (rtems_get_processor_count() == CPU_COUNT) {
322    test();
323  } else {
324    puts("warning: wrong processor count to run the test");
325  }
326
327  TEST_END();
328  rtems_test_exit(0);
329}
330
331#define CONFIGURE_MICROSECONDS_PER_TICK 1000
332
333#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
334#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
335
336#define CONFIGURE_MAXIMUM_TASKS (1 + TASK_COUNT)
337#define CONFIGURE_MAXIMUM_TIMERS 1
338
339#define CONFIGURE_SMP_APPLICATION
340
341#define CONFIGURE_SMP_MAXIMUM_PROCESSORS CPU_COUNT
342
343#define CONFIGURE_SCHEDULER_STRONG_APA
344
345#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
346
347#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
348
349#define CONFIGURE_INIT
350
351#include <rtems/confdefs.h>
Note: See TracBrowser for help on using the repository browser.