source: rtems/testsuites/smptests/smpstrongapa01/init.c @ c4b8b147

5
Last change on this file since c4b8b147 was c4b8b147, checked in by Sebastian Huber <sebastian.huber@…>, on 11/03/17 at 07:35:38

tests: Use simple console driver

Update #3170.
Update #3199.

  • Property mode set to 100644
File size: 7.6 KB
Line 
1/*
2 * Copyright (c) 2016, 2017 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.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    if ((cpu_set_32 & (UINT32_C(1) << i)) != 0) {
139      CPU_SET(i, &cpu_set);
140    }
141  }
142
143  sc = rtems_task_set_affinity(id, sizeof(cpu_set), &cpu_set);
144  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
145}
146
147static void reset(test_context *ctx)
148{
149  rtems_status_code sc;
150  size_t i;
151
152  for (i = CPU_COUNT; i < TASK_COUNT; ++i) {
153    set_priority(ctx->task_ids[i], P(i));
154    set_affinity(ctx->task_ids[i], ALL);
155
156    sc = rtems_task_suspend(ctx->task_ids[i]);
157    rtems_test_assert(sc == RTEMS_SUCCESSFUL || sc == RTEMS_ALREADY_SUSPENDED);
158  }
159
160  for (i = 0; i < CPU_COUNT; ++i) {
161    set_priority(ctx->task_ids[i], P(i));
162
163    sc = rtems_task_resume(ctx->task_ids[i]);
164    rtems_test_assert(sc == RTEMS_SUCCESSFUL || sc == RTEMS_INCORRECT_STATE);
165  }
166
167  /* Order the idle threads explicitly */
168  for (i = 0; i < CPU_COUNT; ++i) {
169    const Per_CPU_Control *c;
170    const Thread_Control *h;
171
172    c = _Per_CPU_Get_by_index(CPU_COUNT - 1 - i);
173    h = c->heir;
174
175    sc = rtems_task_suspend(h->Object.id);
176    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
177  }
178}
179
180static void check_cpu_allocations(test_context *ctx, const test_action *action)
181{
182  size_t i;
183
184  for (i = 0; i < CPU_COUNT; ++i) {
185    size_t e;
186    const Per_CPU_Control *c;
187    const Thread_Control *h;
188
189    e = action->expected_cpu_allocations[i];
190    c = _Per_CPU_Get_by_index(i);
191    h = c->heir;
192
193    if (e != IDLE) {
194      rtems_test_assert(h->Object.id == ctx->task_ids[e]);
195    } else {
196      rtems_test_assert(h->is_idle);
197    }
198  }
199}
200
201/*
202 * Use a timer to execute the actions, since it runs with thread dispatching
203 * disabled.  This is necessary to check the expected processor allocations.
204 */
205static void timer(rtems_id id, void *arg)
206{
207  test_context *ctx;
208  rtems_status_code sc;
209  size_t i;
210
211  ctx = arg;
212  i = ctx->action_index;
213
214  if (i == 0) {
215    sc = rtems_task_suspend(ctx->master_id);
216    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
217  }
218
219  if (i < RTEMS_ARRAY_SIZE(test_actions)) {
220    const test_action *action = &test_actions[i];
221    rtems_id task;
222
223    ctx->action_index = i + 1;
224
225    task = ctx->task_ids[action->index];
226
227    switch (action->kind) {
228      case KIND_SET_PRIORITY:
229        set_priority(task, action->data.priority);
230        break;
231      case KIND_SET_AFFINITY:
232        set_affinity(task, action->data.cpu_set);
233        break;
234      case KIND_BLOCK:
235        sc = rtems_task_suspend(task);
236        rtems_test_assert(sc == RTEMS_SUCCESSFUL);
237        break;
238      case KIND_UNBLOCK:
239        sc = rtems_task_resume(task);
240        rtems_test_assert(sc == RTEMS_SUCCESSFUL);
241        break;
242      default:
243        rtems_test_assert(action->kind == KIND_RESET);
244        reset(ctx);
245        break;
246    }
247
248    check_cpu_allocations(ctx, action);
249
250    sc = rtems_timer_reset(id);
251    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
252  } else {
253    sc = rtems_task_resume(ctx->master_id);
254    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
255
256    sc = rtems_event_transient_send(ctx->master_id);
257    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
258  }
259}
260
261static void do_nothing_task(rtems_task_argument arg)
262{
263  (void) arg;
264
265  while (true) {
266    /* Do nothing */
267  }
268}
269
270static void test(void)
271{
272  test_context *ctx;
273  rtems_status_code sc;
274  size_t i;
275
276  ctx = &test_instance;
277
278  ctx->master_id = rtems_task_self();
279
280  for (i = 0; i < TASK_COUNT; ++i) {
281    sc = rtems_task_create(
282      NAME,
283      P(i),
284      RTEMS_MINIMUM_STACK_SIZE,
285      RTEMS_DEFAULT_MODES,
286      RTEMS_DEFAULT_ATTRIBUTES,
287      &ctx->task_ids[i]
288    );
289    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
290
291    sc = rtems_task_start(ctx->task_ids[i], do_nothing_task, 0);
292    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
293  }
294
295  sc = rtems_timer_create(NAME, &ctx->timer_id);
296  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
297
298  sc = rtems_timer_fire_after(ctx->timer_id, 1, timer, ctx);
299  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
300
301  sc = rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT);
302  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
303
304  for (i = 0; i < TASK_COUNT; ++i) {
305    sc = rtems_task_delete(ctx->task_ids[i]);
306    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
307  }
308
309  sc = rtems_timer_delete(ctx->timer_id);
310  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
311}
312
313static void Init(rtems_task_argument arg)
314{
315  TEST_BEGIN();
316
317  if (rtems_get_processor_count() == CPU_COUNT) {
318    test();
319  } else {
320    puts("warning: wrong processor count to run the test");
321  }
322
323  TEST_END();
324  rtems_test_exit(0);
325}
326
327#define CONFIGURE_MICROSECONDS_PER_TICK 1000
328
329#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
330#define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
331
332#define CONFIGURE_MAXIMUM_TASKS (1 + TASK_COUNT)
333#define CONFIGURE_MAXIMUM_TIMERS 1
334
335#define CONFIGURE_MAXIMUM_PROCESSORS CPU_COUNT
336
337#define CONFIGURE_SCHEDULER_STRONG_APA
338
339#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
340
341#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
342
343#define CONFIGURE_INIT
344
345#include <rtems/confdefs.h>
Note: See TracBrowser for help on using the repository browser.