source: rtems/testsuites/smptests/smpmutex01/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: 8.7 KB
Line 
1/*
2 * Copyright (c) 2015 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
21const char rtems_test_name[] = "SMPMUTEX 1";
22
23#define SCHED_A rtems_build_name(' ', ' ', ' ', 'A')
24
25#define SCHED_B rtems_build_name(' ', ' ', ' ', 'B')
26
27#define PART_COUNT 2
28
29#define TASK_COUNT 9
30
31typedef enum {
32  REQ_WAKE_UP_MASTER = RTEMS_EVENT_0,
33  REQ_WAKE_UP_HELPER = RTEMS_EVENT_1,
34  REQ_MTX_OBTAIN = RTEMS_EVENT_2,
35  REQ_MTX_RELEASE = RTEMS_EVENT_3
36} request_id;
37
38typedef enum {
39  A_1,
40  A_2_0,
41  A_2_1,
42  M,
43  B_4,
44  B_5_0,
45  B_5_1,
46  H_A,
47  H_B,
48  NONE
49} task_id;
50
51typedef struct {
52  rtems_id mtx;
53  rtems_id tasks[TASK_COUNT];
54  int generation[TASK_COUNT];
55  int expected_generation[TASK_COUNT];
56} test_context;
57
58static test_context test_instance;
59
60static void start_task(
61  test_context *ctx,
62  task_id id,
63  rtems_task_entry entry,
64  rtems_task_priority prio,
65  rtems_name scheduler
66)
67{
68  rtems_status_code sc;
69  rtems_id scheduler_id;
70
71  sc = rtems_task_create(
72    rtems_build_name('T', 'A', 'S', 'K'),
73    prio,
74    RTEMS_MINIMUM_STACK_SIZE,
75    RTEMS_DEFAULT_MODES,
76    RTEMS_DEFAULT_ATTRIBUTES,
77    &ctx->tasks[id]
78  );
79  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
80
81  sc = rtems_scheduler_ident(scheduler, &scheduler_id);
82  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
83
84  sc = rtems_task_set_scheduler(ctx->tasks[id], scheduler_id, prio);
85  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
86
87  sc = rtems_task_start(ctx->tasks[id], entry, id);
88  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
89}
90
91static void send_event(test_context *ctx, task_id id, rtems_event_set events)
92{
93  rtems_status_code sc;
94
95  sc = rtems_event_send(ctx->tasks[id], events);
96  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
97}
98
99static rtems_event_set wait_for_events(void)
100{
101  rtems_event_set events;
102  rtems_status_code sc;
103
104  sc = rtems_event_receive(
105    RTEMS_ALL_EVENTS,
106    RTEMS_EVENT_ANY | RTEMS_WAIT,
107    RTEMS_NO_TIMEOUT,
108    &events
109  );
110  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
111
112  return events;
113}
114
115static void sync_with_helper_by_id(test_context *ctx, task_id id)
116{
117  rtems_event_set events;
118
119  send_event(ctx, id, REQ_WAKE_UP_HELPER);
120  events = wait_for_events();
121  rtems_test_assert(events == REQ_WAKE_UP_MASTER);
122}
123
124static void sync_with_helper(test_context *ctx)
125{
126  sync_with_helper_by_id(ctx, H_A);
127  sync_with_helper_by_id(ctx, H_B);
128}
129
130static void request(test_context *ctx, task_id id, request_id req)
131{
132  send_event(ctx, id, req);
133  sync_with_helper(ctx);
134}
135
136static void obtain(test_context *ctx)
137{
138  rtems_status_code sc;
139
140  sc = rtems_semaphore_obtain(ctx->mtx, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
141  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
142}
143
144static void release(test_context *ctx)
145{
146  rtems_status_code sc;
147
148  sc = rtems_semaphore_release(ctx->mtx);
149  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
150}
151
152static void check_generations(test_context *ctx, task_id a, task_id b)
153{
154  size_t i;
155
156  if (a != NONE) {
157    ++ctx->expected_generation[a];
158  }
159
160  if (b != NONE) {
161    ++ctx->expected_generation[b];
162  }
163
164  for (i = 0; i < TASK_COUNT; ++i) {
165    rtems_test_assert(ctx->generation[i] == ctx->expected_generation[i]);
166  }
167}
168
169static void assert_prio(
170  test_context *ctx,
171  task_id id,
172  rtems_task_priority expected
173)
174{
175  rtems_task_priority actual;
176  rtems_status_code sc;
177
178  sc = rtems_task_set_priority(
179    ctx->tasks[id],
180    RTEMS_CURRENT_PRIORITY,
181    &actual
182  );
183  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
184  rtems_test_assert(expected == actual);
185}
186
187static void helper(rtems_task_argument arg)
188{
189  test_context *ctx = &test_instance;
190
191  while (true) {
192    rtems_event_set events = wait_for_events();
193    rtems_test_assert(events == REQ_WAKE_UP_HELPER);
194    send_event(ctx, M, REQ_WAKE_UP_MASTER);
195  }
196}
197
198static void worker(rtems_task_argument arg)
199{
200  test_context *ctx = &test_instance;
201  task_id id = arg;
202
203  while (true) {
204    rtems_event_set events = wait_for_events();
205
206    if ((events & REQ_MTX_OBTAIN) != 0) {
207      obtain(ctx);
208      ++ctx->generation[id];
209    }
210
211    if ((events & REQ_MTX_RELEASE) != 0) {
212      release(ctx);
213      ++ctx->generation[id];
214    }
215  }
216}
217
218static void test(void)
219{
220  test_context *ctx = &test_instance;
221  rtems_status_code sc;
222
223  ctx->tasks[M] = rtems_task_self();
224  start_task(ctx, A_1, worker, 1, SCHED_A);
225  start_task(ctx, A_2_0, worker, 2, SCHED_A);
226  start_task(ctx, A_2_1, worker, 2, SCHED_A);
227  start_task(ctx, B_4, worker, 4, SCHED_B);
228  start_task(ctx, B_5_0, worker, 5, SCHED_B);
229  start_task(ctx, B_5_1, worker, 5, SCHED_B);
230  start_task(ctx, H_A, helper, 3, SCHED_A);
231  start_task(ctx, H_B, helper, 6, SCHED_B);
232
233  sc = rtems_semaphore_create(
234    rtems_build_name(' ', 'M', 'T', 'X'),
235    1,
236    RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY,
237    0,
238    &ctx->mtx
239  );
240  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
241
242  obtain(ctx);
243  request(ctx, A_1, REQ_MTX_OBTAIN);
244  check_generations(ctx, NONE, NONE);
245  assert_prio(ctx, M, 1);
246  release(ctx);
247  check_generations(ctx, A_1, NONE);
248  assert_prio(ctx, M, 3);
249  request(ctx, A_1, REQ_MTX_RELEASE);
250  check_generations(ctx, A_1, NONE);
251
252  obtain(ctx);
253  request(ctx, A_2_0, REQ_MTX_OBTAIN);
254  request(ctx, A_1, REQ_MTX_OBTAIN);
255  request(ctx, A_2_1, REQ_MTX_OBTAIN);
256  check_generations(ctx, NONE, NONE);
257  assert_prio(ctx, M, 1);
258  release(ctx);
259  check_generations(ctx, A_1, NONE);
260  assert_prio(ctx, M, 3);
261  assert_prio(ctx, A_1, 1);
262  request(ctx, A_1, REQ_MTX_RELEASE);
263  check_generations(ctx, A_1, A_2_0);
264  request(ctx, A_2_0, REQ_MTX_RELEASE);
265  check_generations(ctx, A_2_0, A_2_1);
266  request(ctx, A_2_1, REQ_MTX_RELEASE);
267  check_generations(ctx, A_2_1, NONE);
268
269  obtain(ctx);
270  request(ctx, B_5_0, REQ_MTX_OBTAIN);
271  request(ctx, B_4, REQ_MTX_OBTAIN);
272  request(ctx, B_5_1, REQ_MTX_OBTAIN);
273  check_generations(ctx, NONE, NONE);
274  assert_prio(ctx, M, 0);
275  release(ctx);
276  sync_with_helper(ctx);
277  assert_prio(ctx, M, 3);
278  check_generations(ctx, B_4, NONE);
279  request(ctx, B_4, REQ_MTX_RELEASE);
280  check_generations(ctx, B_4, B_5_0);
281  request(ctx, B_5_0, REQ_MTX_RELEASE);
282  check_generations(ctx, B_5_0, B_5_1);
283  request(ctx, B_5_1, REQ_MTX_RELEASE);
284  check_generations(ctx, B_5_1, NONE);
285
286  obtain(ctx);
287  request(ctx, A_2_0, REQ_MTX_OBTAIN);
288  check_generations(ctx, NONE, NONE);
289  assert_prio(ctx, M, 2);
290  request(ctx, B_5_0, REQ_MTX_OBTAIN);
291  check_generations(ctx, NONE, NONE);
292  assert_prio(ctx, M, 0);
293  request(ctx, B_5_1, REQ_MTX_OBTAIN);
294  request(ctx, B_4, REQ_MTX_OBTAIN);
295  request(ctx, A_2_1, REQ_MTX_OBTAIN);
296  request(ctx, A_1, REQ_MTX_OBTAIN);
297  check_generations(ctx, NONE, NONE);
298  release(ctx);
299  sync_with_helper(ctx);
300  check_generations(ctx, A_1, NONE);
301  assert_prio(ctx, M, 3);
302  assert_prio(ctx, A_1, 0);
303  request(ctx, A_1, REQ_MTX_RELEASE);
304  check_generations(ctx, A_1, B_4);
305  assert_prio(ctx, A_1, 1);
306  assert_prio(ctx, B_4, 0);
307  request(ctx, B_4, REQ_MTX_RELEASE);
308  check_generations(ctx, B_4, A_2_0);
309  assert_prio(ctx, B_4, 4);
310  assert_prio(ctx, A_2_0, 0);
311  request(ctx, A_2_0, REQ_MTX_RELEASE);
312  check_generations(ctx, A_2_0, B_5_0);
313  assert_prio(ctx, A_2_0, 2);
314  assert_prio(ctx, B_5_0, 0);
315  request(ctx, B_5_0, REQ_MTX_RELEASE);
316  check_generations(ctx, B_5_0, A_2_1);
317  assert_prio(ctx, B_5_0, 5);
318  assert_prio(ctx, A_2_1, 0);
319  request(ctx, A_2_1, REQ_MTX_RELEASE);
320  check_generations(ctx, A_2_1, B_5_1);
321  assert_prio(ctx, A_2_1, 2);
322  assert_prio(ctx, B_5_1, 5);
323  request(ctx, B_5_1, REQ_MTX_RELEASE);
324  check_generations(ctx, B_5_1, NONE);
325  assert_prio(ctx, B_5_1, 5);
326}
327
328static void Init(rtems_task_argument arg)
329{
330  TEST_BEGIN();
331
332  if (rtems_get_processor_count() >= PART_COUNT) {
333    test();
334  }
335
336  TEST_END();
337  rtems_test_exit(0);
338}
339
340#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
341#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
342
343#define CONFIGURE_SMP_APPLICATION
344
345#define CONFIGURE_SMP_MAXIMUM_PROCESSORS PART_COUNT
346
347#define CONFIGURE_SCHEDULER_SIMPLE_SMP
348
349#include <rtems/scheduler.h>
350
351RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(a);
352
353RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(b);
354
355#define CONFIGURE_SCHEDULER_CONTROLS \
356  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(a, SCHED_A), \
357  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(b, SCHED_B)
358
359#define CONFIGURE_SMP_SCHEDULER_ASSIGNMENTS \
360  RTEMS_SCHEDULER_ASSIGN(0, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_MANDATORY), \
361  RTEMS_SCHEDULER_ASSIGN(1, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL)
362
363#define CONFIGURE_MAXIMUM_TASKS TASK_COUNT
364
365#define CONFIGURE_MAXIMUM_SEMAPHORES 1
366
367#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
368
369#define CONFIGURE_INIT_TASK_PRIORITY 3
370
371#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
372
373#define CONFIGURE_INIT
374
375#include <rtems/confdefs.h>
Note: See TracBrowser for help on using the repository browser.