source: rtems/testsuites/smptests/smpscheduler02/init.c @ 38b59a6

4.115
Last change on this file since 38b59a6 was 38b59a6, checked in by Sebastian Huber <sebastian.huber@…>, on 05/02/14 at 08:31:09

score: Implement forced thread migration

The current implementation of task migration in RTEMS has some
implications with respect to the interrupt latency. It is crucial to
preserve the system invariant that a task can execute on at most one
processor in the system at a time. This is accomplished with a boolean
indicator in the task context. The processor architecture specific
low-level task context switch code will mark that a task context is no
longer executing and waits that the heir context stopped execution
before it restores the heir context and resumes execution of the heir
task. So there is one point in time in which a processor is without a
task. This is essential to avoid cyclic dependencies in case multiple
tasks migrate at once. Otherwise some supervising entity is necessary to
prevent life-locks. Such a global supervisor would lead to scalability
problems so this approach is not used. Currently the thread dispatch is
performed with interrupts disabled. So in case the heir task is
currently executing on another processor then this prolongs the time of
disabled interrupts since one processor has to wait for another
processor to make progress.

It is difficult to avoid this issue with the interrupt latency since
interrupts normally store the context of the interrupted task on its
stack. In case a task is marked as not executing we must not use its
task stack to store such an interrupt context. We cannot use the heir
stack before it stopped execution on another processor. So if we enable
interrupts during this transition we have to provide an alternative task
independent stack for this time frame. This issue needs further
investigation.

  • Property mode set to 100644
File size: 8.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
22#include "tmacros.h"
23
24const char rtems_test_name[] = "SMPSCHEDULER 2";
25
26#if defined(__RTEMS_HAVE_SYS_CPUSET_H__)
27
28#define SCHED_A rtems_build_name(' ', ' ', ' ', 'A')
29
30#define SCHED_B rtems_build_name(' ', ' ', ' ', 'B')
31
32#define SCHED_C rtems_build_name(' ', ' ', ' ', 'C')
33
34static rtems_id main_task_id;
35
36static void task(rtems_task_argument arg)
37{
38  rtems_status_code sc;
39
40  (void) arg;
41
42  rtems_test_assert(rtems_get_current_processor() == 1);
43
44  sc = rtems_event_transient_send(main_task_id);
45  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
46
47  while (1) {
48    /* Do nothing */
49  }
50}
51
52static void test(void)
53{
54  rtems_status_code sc;
55  rtems_id task_id;
56  rtems_id scheduler_id;
57  rtems_id scheduler_a_id;
58  rtems_id scheduler_b_id;
59  rtems_id scheduler_c_id;
60  cpu_set_t cpuset;
61  cpu_set_t first_cpu;
62  cpu_set_t second_cpu;
63  cpu_set_t all_cpus;
64
65  main_task_id = rtems_task_self();
66
67  CPU_ZERO(&first_cpu);
68  CPU_SET(0, &first_cpu);
69
70  CPU_ZERO(&second_cpu);
71  CPU_SET(1, &second_cpu);
72
73  CPU_ZERO(&all_cpus);
74  CPU_SET(0, &all_cpus);
75  CPU_SET(1, &all_cpus);
76
77  rtems_test_assert(rtems_get_current_processor() == 0);
78
79  sc = rtems_scheduler_ident(SCHED_A, &scheduler_a_id);
80  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
81
82  sc = rtems_scheduler_ident(SCHED_B, &scheduler_b_id);
83  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
84  rtems_test_assert(scheduler_a_id != scheduler_b_id);
85
86  sc = rtems_scheduler_ident(SCHED_C, &scheduler_c_id);
87  rtems_test_assert(sc == RTEMS_UNSATISFIED);
88
89  CPU_ZERO(&cpuset);
90  sc = rtems_scheduler_get_processor_set(
91    scheduler_a_id,
92    sizeof(cpuset),
93    &cpuset
94  );
95  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
96  rtems_test_assert(CPU_EQUAL(&cpuset, &first_cpu));
97
98  CPU_ZERO(&cpuset);
99  sc = rtems_scheduler_get_processor_set(
100    scheduler_b_id,
101    sizeof(cpuset),
102    &cpuset
103  );
104  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
105  rtems_test_assert(CPU_EQUAL(&cpuset, &second_cpu));
106
107  sc = rtems_task_create(
108    rtems_build_name('T', 'A', 'S', 'K'),
109    1,
110    RTEMS_MINIMUM_STACK_SIZE,
111    RTEMS_DEFAULT_MODES,
112    RTEMS_DEFAULT_ATTRIBUTES,
113    &task_id
114  );
115  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
116
117  sc = rtems_task_get_scheduler(task_id, &scheduler_id);
118  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
119  rtems_test_assert(scheduler_id == scheduler_a_id);
120
121  CPU_ZERO(&cpuset);
122  sc = rtems_task_get_affinity(task_id, sizeof(cpuset), &cpuset);
123  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
124  rtems_test_assert(CPU_EQUAL(&cpuset, &first_cpu));
125
126  sc = rtems_task_set_scheduler(task_id, scheduler_b_id);
127  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
128
129  sc = rtems_task_set_scheduler(task_id, scheduler_b_id + 1);
130  rtems_test_assert(sc == RTEMS_INVALID_ID);
131
132  sc = rtems_task_get_scheduler(task_id, &scheduler_id);
133  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
134  rtems_test_assert(scheduler_id == scheduler_b_id);
135
136  CPU_ZERO(&cpuset);
137  sc = rtems_task_get_affinity(task_id, sizeof(cpuset), &cpuset);
138  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
139  rtems_test_assert(CPU_EQUAL(&cpuset, &second_cpu));
140
141  sc = rtems_task_set_affinity(task_id, sizeof(all_cpus), &all_cpus);
142  rtems_test_assert(sc == RTEMS_INVALID_NUMBER);
143
144  sc = rtems_task_set_affinity(task_id, sizeof(first_cpu), &first_cpu);
145  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
146
147  sc = rtems_task_get_scheduler(task_id, &scheduler_id);
148  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
149  rtems_test_assert(scheduler_id == scheduler_a_id);
150
151  sc = rtems_task_set_affinity(task_id, sizeof(second_cpu), &second_cpu);
152  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
153
154  sc = rtems_task_get_scheduler(task_id, &scheduler_id);
155  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
156  rtems_test_assert(scheduler_id == scheduler_b_id);
157
158  sc = rtems_task_start(task_id, task, 0);
159  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
160
161  sc = rtems_task_set_scheduler(task_id, scheduler_b_id);
162  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
163
164  sc = rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT);
165  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
166
167  sc = rtems_task_delete(task_id);
168  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
169}
170
171#else /* defined(__RTEMS_HAVE_SYS_CPUSET_H__) */
172
173static void test(void)
174{
175  /* Nothing to do */
176}
177
178#endif /* defined(__RTEMS_HAVE_SYS_CPUSET_H__) */
179
180static void Init(rtems_task_argument arg)
181{
182  rtems_resource_snapshot snapshot;
183
184  TEST_BEGIN();
185
186  rtems_resource_snapshot_take(&snapshot);
187
188  test();
189
190  rtems_test_assert(rtems_resource_snapshot_check(&snapshot));
191
192  TEST_END();
193  rtems_test_exit(0);
194}
195
196#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
197#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
198
199#define CONFIGURE_SMP_APPLICATION
200
201/* Lets see when the first RTEMS system hits this limit */
202#define CONFIGURE_SMP_MAXIMUM_PROCESSORS 64
203
204#define CONFIGURE_MAXIMUM_PRIORITY 255
205
206#define CONFIGURE_SCHEDULER_PRIORITY_SMP
207#define CONFIGURE_SCHEDULER_SIMPLE_SMP
208
209#include <rtems/scheduler.h>
210
211RTEMS_SCHEDULER_CONTEXT_PRIORITY_SMP(a, CONFIGURE_MAXIMUM_PRIORITY + 1);
212
213RTEMS_SCHEDULER_CONTEXT_PRIORITY_SMP(b, CONFIGURE_MAXIMUM_PRIORITY + 1);
214
215RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(c);
216
217#define CONFIGURE_SCHEDULER_CONTROLS \
218  RTEMS_SCHEDULER_CONTROL_PRIORITY_SMP(a, SCHED_A), \
219  RTEMS_SCHEDULER_CONTROL_PRIORITY_SMP(b, SCHED_B), \
220  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(c, SCHED_C)
221
222#define CONFIGURE_SMP_SCHEDULER_ASSIGNMENTS \
223  RTEMS_SCHEDULER_ASSIGN(0, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_MANDATORY), \
224  RTEMS_SCHEDULER_ASSIGN(1, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_MANDATORY), \
225  RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \
226  RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \
227  RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \
228  RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \
229  RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \
230  RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \
231  RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \
232  RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \
233  RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \
234  RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \
235  RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \
236  RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \
237  RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \
238  RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \
239  RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \
240  RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \
241  RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \
242  RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \
243  RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \
244  RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \
245  RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \
246  RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \
247  RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \
248  RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \
249  RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \
250  RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \
251  RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \
252  RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \
253  RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \
254  RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \
255  RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \
256  RTEMS_SCHEDULER_ASSIGN(2, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL)
257
258#define CONFIGURE_MAXIMUM_TASKS 2
259
260#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
261
262#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
263
264#define CONFIGURE_INIT
265
266#include <rtems/confdefs.h>
Note: See TracBrowser for help on using the repository browser.