source: rtems/testsuites/smptests/smpmigration02/init.c @ c0bd006

5
Last change on this file since c0bd006 was c0bd006, checked in by Sebastian Huber <sebastian.huber@…>, on 06/30/16 at 12:08:18

rtems: Fix rtems_task_set_scheduler() API

Task priorities are only valid within a scheduler instance. The
rtems_task_set_scheduler() directive moves a task from one scheduler
instance to another using the current priority of the thread. However,
the current task priority of the source scheduler instance is undefined
in the target scheduler instance. Add a third parameter to specify the
priority.

Close #2749.

  • Property mode set to 100644
File size: 12.4 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 <rtems.h>
20#include <rtems/libcsupport.h>
21#include <rtems/score/objectimpl.h>
22#include <rtems/score/threadimpl.h>
23
24#include "tmacros.h"
25
26const char rtems_test_name[] = "SMPMIGRATION 2";
27
28#define CPU_COUNT 32
29
30#define TASK_COUNT (CPU_COUNT + 1)
31
32#define PRIO_LOW 3
33
34#define PRIO_HIGH 2
35
36typedef struct {
37  uint32_t value;
38  uint32_t cache_line_separation[31];
39} test_counter;
40
41typedef struct {
42  test_counter counters[TASK_COUNT];
43  rtems_id scheduler_ids[CPU_COUNT];
44  rtems_id task_ids[TASK_COUNT];
45} test_context;
46
47static test_context test_instance;
48
49static rtems_task_priority migration_task_prio(uint32_t task_index)
50{
51  return task_index > 0 ? PRIO_LOW : PRIO_HIGH;
52}
53
54static void migration_task(rtems_task_argument arg)
55{
56  test_context *ctx = &test_instance;
57  uint32_t task_index = arg;
58  rtems_task_priority prio = migration_task_prio(task_index);
59  uint32_t cpu_count = rtems_get_processor_count();
60  uint32_t cpu_index = rtems_get_current_processor();
61
62  while (true) {
63    rtems_status_code sc;
64
65    cpu_index = (cpu_index + 1) % cpu_count;
66
67    sc = rtems_task_set_scheduler(
68      RTEMS_SELF,
69      ctx->scheduler_ids[cpu_index],
70      prio
71    );
72    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
73
74    ++ctx->counters[task_index].value;
75
76    rtems_test_assert(cpu_index == rtems_get_current_processor());
77  }
78}
79
80static void test_migrations(test_context *ctx)
81{
82  rtems_status_code sc;
83  uint32_t cpu_count = rtems_get_processor_count();
84  uint32_t task_count = cpu_count + 1;
85  uint32_t task_index;
86
87  for (task_index = 0; task_index < task_count; ++task_index) {
88    rtems_id task_id;
89
90    sc = rtems_task_create(
91      rtems_build_name('T', 'A', 'S', 'K'),
92      255,
93      RTEMS_MINIMUM_STACK_SIZE,
94      RTEMS_DEFAULT_MODES,
95      RTEMS_DEFAULT_ATTRIBUTES,
96      &task_id
97    );
98    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
99
100    sc = rtems_task_set_scheduler(
101      task_id,
102      ctx->scheduler_ids[task_index % cpu_count],
103      migration_task_prio(task_index)
104    );
105    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
106
107    sc = rtems_task_start(task_id, migration_task, task_index);
108    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
109
110    ctx->task_ids[task_index] = task_id;
111  }
112
113  sc = rtems_task_wake_after(30 * rtems_clock_get_ticks_per_second());
114  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
115
116  for (task_index = 0; task_index < task_count; ++task_index) {
117    printf(
118      "task %" PRIu32 " counter: %" PRIu32 "\n",
119      task_index,
120      ctx->counters[task_index].value
121    );
122
123    sc = rtems_task_delete(ctx->task_ids[task_index]);
124    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
125  }
126}
127
128static void busy_loop_task(rtems_task_argument arg)
129{
130  while (true) {
131    /* Do nothing */
132  }
133}
134
135static Thread_Control *get_thread_by_id(rtems_id task_id)
136{
137  ISR_lock_Context lock_context;
138  Thread_Control *thread;
139
140  thread = _Thread_Get(task_id, &lock_context);
141  rtems_test_assert(thread != NULL);
142  _ISR_lock_ISR_enable(&lock_context);
143
144  return thread;
145}
146
147static void test_double_migration(test_context *ctx)
148{
149  uint32_t cpu_count = rtems_get_processor_count();
150
151  if (cpu_count >= 2) {
152    rtems_status_code sc;
153    rtems_id task_id;
154    rtems_id scheduler_id;
155    uint32_t cpu_self_index = 0;
156    uint32_t cpu_other_index = 1;
157    Per_CPU_Control *cpu_self = _Per_CPU_Get_by_index(cpu_self_index);
158    Per_CPU_Control *cpu_other = _Per_CPU_Get_by_index(cpu_other_index);
159    Per_CPU_Control *cpu_self_dispatch_disabled;
160    Thread_Control *self;
161    Thread_Control *other;
162
163    sc = rtems_task_get_scheduler(RTEMS_SELF, &scheduler_id);
164    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
165
166    rtems_test_assert(scheduler_id == ctx->scheduler_ids[cpu_self_index]);
167
168    sc = rtems_task_create(
169      rtems_build_name('T', 'A', 'S', 'K'),
170      2,
171      RTEMS_MINIMUM_STACK_SIZE,
172      RTEMS_DEFAULT_MODES,
173      RTEMS_DEFAULT_ATTRIBUTES,
174      &task_id
175    );
176    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
177
178    other = get_thread_by_id(task_id);
179
180    sc = rtems_task_set_scheduler(
181      task_id,
182      ctx->scheduler_ids[cpu_other_index],
183      2
184    );
185    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
186
187    sc = rtems_task_start(task_id, busy_loop_task, 0);
188    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
189
190    while (!_Thread_Is_executing_on_a_processor(other)) {
191      /* Wait */
192    }
193
194    cpu_self_dispatch_disabled = _Thread_Dispatch_disable();
195    rtems_test_assert(cpu_self == cpu_self_dispatch_disabled);
196
197    self = _Thread_Executing;
198
199    rtems_test_assert(cpu_self->executing == self);
200    rtems_test_assert(cpu_self->heir == self);
201    rtems_test_assert(!cpu_self->dispatch_necessary);
202
203    rtems_test_assert(cpu_other->executing == other);
204    rtems_test_assert(cpu_other->heir == other);
205    rtems_test_assert(!cpu_other->dispatch_necessary);
206
207    sc = rtems_task_set_scheduler(
208      RTEMS_SELF,
209      ctx->scheduler_ids[cpu_other_index],
210      1
211    );
212    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
213
214    rtems_test_assert(cpu_self->executing == self);
215    rtems_test_assert(cpu_self->heir != self);
216    rtems_test_assert(cpu_self->dispatch_necessary);
217
218    while (_Thread_Is_executing_on_a_processor(other)) {
219      /* Wait */
220    }
221
222    rtems_test_assert(cpu_other->executing == self);
223    rtems_test_assert(cpu_other->heir == self);
224    rtems_test_assert(!cpu_other->dispatch_necessary);
225
226    sc = rtems_task_set_scheduler(
227      RTEMS_SELF,
228      ctx->scheduler_ids[cpu_self_index],
229      1
230    );
231    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
232
233    rtems_test_assert(cpu_self->executing == self);
234    rtems_test_assert(cpu_self->heir == self);
235    rtems_test_assert(cpu_self->dispatch_necessary);
236
237    rtems_test_assert(cpu_other->heir == other);
238
239    _Thread_Dispatch_enable(cpu_self_dispatch_disabled);
240
241    while (!_Thread_Is_executing_on_a_processor(other)) {
242      /* Wait */
243    }
244
245    sc = rtems_task_delete(task_id);
246    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
247  }
248}
249
250static void init_scheduler_ids(test_context *ctx)
251{
252  rtems_status_code sc;
253  uint32_t cpu_count = rtems_get_processor_count();
254  uint32_t cpu_index;
255
256  for (cpu_index = 0; cpu_index < cpu_count; ++cpu_index) {
257    sc = rtems_scheduler_ident(cpu_index, &ctx->scheduler_ids[cpu_index]);
258    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
259  }
260}
261
262static void Init(rtems_task_argument arg)
263{
264  test_context *ctx = &test_instance;
265  rtems_resource_snapshot snapshot;
266
267  TEST_BEGIN();
268
269  rtems_resource_snapshot_take(&snapshot);
270
271  init_scheduler_ids(ctx);
272  test_double_migration(ctx);
273  test_migrations(ctx);
274
275  rtems_test_assert(rtems_resource_snapshot_check(&snapshot));
276
277  TEST_END();
278  rtems_test_exit(0);
279}
280
281#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
282#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
283
284#define CONFIGURE_SMP_APPLICATION
285
286#define CONFIGURE_SMP_MAXIMUM_PROCESSORS CPU_COUNT
287
288#define CONFIGURE_SCHEDULER_SIMPLE_SMP
289
290#include <rtems/scheduler.h>
291
292RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(0);
293RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(1);
294RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(2);
295RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(3);
296RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(4);
297RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(5);
298RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(6);
299RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(7);
300RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(8);
301RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(9);
302RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(10);
303RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(11);
304RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(12);
305RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(13);
306RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(14);
307RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(15);
308RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(16);
309RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(17);
310RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(18);
311RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(19);
312RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(20);
313RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(21);
314RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(22);
315RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(23);
316RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(24);
317RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(25);
318RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(26);
319RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(27);
320RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(28);
321RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(29);
322RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(30);
323RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(31);
324
325#define CONFIGURE_SCHEDULER_CONTROLS \
326  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(0, 0), \
327  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(1, 1), \
328  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(2, 2), \
329  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(3, 3), \
330  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(4, 4), \
331  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(5, 5), \
332  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(6, 6), \
333  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(7, 7), \
334  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(8, 8), \
335  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(9, 9), \
336  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(10, 10), \
337  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(11, 11), \
338  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(12, 12), \
339  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(13, 13), \
340  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(14, 14), \
341  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(15, 15), \
342  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(16, 16), \
343  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(17, 17), \
344  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(18, 18), \
345  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(19, 19), \
346  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(20, 20), \
347  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(21, 21), \
348  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(22, 22), \
349  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(23, 23), \
350  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(24, 24), \
351  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(25, 25), \
352  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(26, 26), \
353  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(27, 27), \
354  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(28, 28), \
355  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(29, 29), \
356  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(30, 30), \
357  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(31, 31)
358
359#define CONFIGURE_SMP_SCHEDULER_ASSIGNMENTS \
360  RTEMS_SCHEDULER_ASSIGN(0, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
361  RTEMS_SCHEDULER_ASSIGN(1, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
362  RTEMS_SCHEDULER_ASSIGN(2, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
363  RTEMS_SCHEDULER_ASSIGN(3, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
364  RTEMS_SCHEDULER_ASSIGN(4, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
365  RTEMS_SCHEDULER_ASSIGN(5, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
366  RTEMS_SCHEDULER_ASSIGN(6, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
367  RTEMS_SCHEDULER_ASSIGN(7, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
368  RTEMS_SCHEDULER_ASSIGN(8, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
369  RTEMS_SCHEDULER_ASSIGN(9, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
370  RTEMS_SCHEDULER_ASSIGN(10, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
371  RTEMS_SCHEDULER_ASSIGN(11, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
372  RTEMS_SCHEDULER_ASSIGN(12, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
373  RTEMS_SCHEDULER_ASSIGN(13, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
374  RTEMS_SCHEDULER_ASSIGN(14, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
375  RTEMS_SCHEDULER_ASSIGN(15, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
376  RTEMS_SCHEDULER_ASSIGN(16, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
377  RTEMS_SCHEDULER_ASSIGN(17, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
378  RTEMS_SCHEDULER_ASSIGN(18, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
379  RTEMS_SCHEDULER_ASSIGN(19, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
380  RTEMS_SCHEDULER_ASSIGN(20, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
381  RTEMS_SCHEDULER_ASSIGN(21, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
382  RTEMS_SCHEDULER_ASSIGN(22, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
383  RTEMS_SCHEDULER_ASSIGN(23, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
384  RTEMS_SCHEDULER_ASSIGN(24, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
385  RTEMS_SCHEDULER_ASSIGN(25, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
386  RTEMS_SCHEDULER_ASSIGN(26, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
387  RTEMS_SCHEDULER_ASSIGN(27, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
388  RTEMS_SCHEDULER_ASSIGN(28, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
389  RTEMS_SCHEDULER_ASSIGN(29, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
390  RTEMS_SCHEDULER_ASSIGN(30, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
391  RTEMS_SCHEDULER_ASSIGN(31, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL)
392
393#define CONFIGURE_MAXIMUM_TASKS (1 + TASK_COUNT)
394
395#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
396
397#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
398
399#define CONFIGURE_INIT
400
401#include <rtems/confdefs.h>
Note: See TracBrowser for help on using the repository browser.