source: rtems/testsuites/smptests/smpmutex01/init.c @ 2ef85b1

5
Last change on this file since 2ef85b1 was ec771f2, checked in by Sebastian Huber <sebastian.huber@…>, on 11/16/17 at 14:04:21

score: Fix priority ceiling updates

We must not clear the priority updates in _Thread_queue_Extract_locked()
since this function is used by the priority ceiling surrender operations
after the ceiling priority handover from the previous owner to the new
owner. This is especially important in SMP configurations.

Move the _Thread_queue_Context_clear_priority_updates() invocation to
the callers.

Close #3237.

  • Property mode set to 100644
File size: 27.1 KB
Line 
1/*
2 * Copyright (c) 2015, 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
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
31#define PRIO_NONE 0
32
33/* Value choosen for Qemu, 2 would be sufficient for real targets */
34#define TIMEOUT_IN_TICKS 10
35
36typedef enum {
37  REQ_WAKE_UP_MASTER = RTEMS_EVENT_0,
38  REQ_WAKE_UP_HELPER = RTEMS_EVENT_1,
39  REQ_MTX_OBTAIN = RTEMS_EVENT_2,
40  REQ_MTX_OBTAIN_TIMEOUT = RTEMS_EVENT_3,
41  REQ_MTX_OBTAIN_UNSATISFIED = RTEMS_EVENT_4,
42  REQ_MTX_RELEASE = RTEMS_EVENT_5,
43  REQ_MTX_2_OBTAIN = RTEMS_EVENT_6,
44  REQ_MTX_2_RELEASE = RTEMS_EVENT_7,
45  REQ_SEM_OBTAIN_RELEASE = RTEMS_EVENT_8,
46  REQ_SEM_RELEASE = RTEMS_EVENT_9,
47  REQ_SET_DONE = RTEMS_EVENT_10,
48  REQ_WAIT_FOR_DONE = RTEMS_EVENT_11,
49  REQ_SEND_EVENT_2 = RTEMS_EVENT_12,
50  REQ_SEND_EVENT_3 = RTEMS_EVENT_13,
51  REQ_CEIL_OBTAIN = RTEMS_EVENT_14,
52  REQ_CEIL_RELEASE = RTEMS_EVENT_15
53} request_id;
54
55typedef enum {
56  A_1,
57  A_2_0,
58  A_2_1,
59  M,
60  B_4,
61  B_5_0,
62  B_5_1,
63  H_A,
64  H_B,
65  NONE
66} task_id;
67
68typedef struct {
69  rtems_id mtx;
70  rtems_id mtx_2;
71  rtems_id sem;
72  rtems_id ceil;
73  rtems_id tasks[TASK_COUNT];
74  Atomic_Uint done;
75  task_id id_2;
76  rtems_event_set events_2;
77  task_id id_3;
78  rtems_event_set events_3;
79  int generation[TASK_COUNT];
80  int expected_generation[TASK_COUNT];
81} test_context;
82
83static test_context test_instance;
84
85static void assert_cpu(uint32_t expected_cpu)
86{
87  rtems_test_assert(rtems_get_current_processor() == expected_cpu);
88}
89
90static void test_task_get_priority_not_defined(test_context *ctx)
91{
92  rtems_status_code sc;
93  rtems_id scheduler_id;
94  rtems_task_priority priority;
95
96  sc = rtems_scheduler_ident(SCHED_B, &scheduler_id);
97  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
98
99  priority = 0;
100  sc = rtems_task_get_priority(RTEMS_SELF, scheduler_id, &priority);
101  rtems_test_assert(sc == RTEMS_NOT_DEFINED);
102  rtems_test_assert(priority == 0);
103}
104
105static void start_task(
106  test_context *ctx,
107  task_id id,
108  rtems_task_entry entry,
109  rtems_task_priority prio,
110  rtems_name scheduler
111)
112{
113  rtems_status_code sc;
114  rtems_id scheduler_id;
115
116  sc = rtems_task_create(
117    rtems_build_name('T', 'A', 'S', 'K'),
118    prio,
119    RTEMS_MINIMUM_STACK_SIZE,
120    RTEMS_DEFAULT_MODES,
121    RTEMS_DEFAULT_ATTRIBUTES,
122    &ctx->tasks[id]
123  );
124  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
125
126  sc = rtems_scheduler_ident(scheduler, &scheduler_id);
127  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
128
129  sc = rtems_task_set_scheduler(ctx->tasks[id], scheduler_id, prio);
130  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
131
132  sc = rtems_task_start(ctx->tasks[id], entry, id);
133  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
134}
135
136static void send_event(test_context *ctx, task_id id, rtems_event_set events)
137{
138  rtems_status_code sc;
139
140  sc = rtems_event_send(ctx->tasks[id], events);
141  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
142}
143
144static void set_event_2(
145  test_context *ctx,
146  task_id id_2,
147  rtems_event_set events_2
148)
149{
150  ctx->id_2 = id_2;
151  ctx->events_2 = events_2;
152}
153
154static void set_event_3(
155  test_context *ctx,
156  task_id id_3,
157  rtems_event_set events_3
158)
159{
160  ctx->id_3 = id_3;
161  ctx->events_3 = events_3;
162}
163
164static void clear_done(test_context *ctx)
165{
166  _Atomic_Store_uint(&ctx->done, 0, ATOMIC_ORDER_RELAXED);
167}
168
169static void set_done(test_context *ctx)
170{
171  _Atomic_Store_uint(&ctx->done, 1, ATOMIC_ORDER_RELEASE);
172}
173
174static bool is_done(test_context *ctx)
175{
176  return _Atomic_Load_uint(&ctx->done, ATOMIC_ORDER_ACQUIRE) != 0;
177}
178
179static void wait_for_done(test_context *ctx)
180{
181  while (!is_done(ctx)) {
182    /* Wait */
183  }
184}
185
186static void request_pre_emption(test_context *ctx, task_id id)
187{
188  clear_done(ctx);
189  send_event(ctx, id, REQ_SET_DONE);
190  wait_for_done(ctx);
191}
192
193static rtems_event_set wait_for_events(void)
194{
195  rtems_event_set events;
196  rtems_status_code sc;
197
198  sc = rtems_event_receive(
199    RTEMS_ALL_EVENTS,
200    RTEMS_EVENT_ANY | RTEMS_WAIT,
201    RTEMS_NO_TIMEOUT,
202    &events
203  );
204  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
205
206  return events;
207}
208
209static void sync_with_helper_by_id(test_context *ctx, task_id id)
210{
211  rtems_event_set events;
212
213  send_event(ctx, id, REQ_WAKE_UP_HELPER);
214  events = wait_for_events();
215  rtems_test_assert(events == REQ_WAKE_UP_MASTER);
216}
217
218static void sync_with_helper(test_context *ctx)
219{
220  sync_with_helper_by_id(ctx, H_A);
221  sync_with_helper_by_id(ctx, H_B);
222}
223
224static void request(test_context *ctx, task_id id, request_id req)
225{
226  send_event(ctx, id, req);
227  clear_done(ctx);
228
229  if (rtems_get_current_processor() == 0) {
230    id = H_B;
231  } else {
232    id = H_A;
233  }
234
235  send_event(ctx, id, REQ_SET_DONE);
236  wait_for_done(ctx);
237}
238
239static void obtain(test_context *ctx)
240{
241  rtems_status_code sc;
242
243  sc = rtems_semaphore_obtain(ctx->mtx, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
244  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
245}
246
247static void obtain_timeout(test_context *ctx)
248{
249  rtems_status_code sc;
250
251  sc = rtems_semaphore_obtain(ctx->mtx, RTEMS_WAIT, TIMEOUT_IN_TICKS);
252  rtems_test_assert(sc == RTEMS_TIMEOUT);
253}
254
255static void obtain_unsatisfied(test_context *ctx)
256{
257  rtems_status_code sc;
258
259  sc = rtems_semaphore_obtain(ctx->mtx, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
260  rtems_test_assert(sc == RTEMS_UNSATISFIED);
261}
262
263static void release(test_context *ctx)
264{
265  rtems_status_code sc;
266
267  sc = rtems_semaphore_release(ctx->mtx);
268  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
269}
270
271static void flush(test_context *ctx)
272{
273  rtems_status_code sc;
274
275  sc = rtems_semaphore_flush(ctx->mtx);
276  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
277}
278
279static void obtain_2(test_context *ctx)
280{
281  rtems_status_code sc;
282
283  sc = rtems_semaphore_obtain(ctx->mtx_2, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
284  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
285}
286
287static void release_2(test_context *ctx)
288{
289  rtems_status_code sc;
290
291  sc = rtems_semaphore_release(ctx->mtx_2);
292  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
293}
294
295static void sem_obtain(test_context *ctx)
296{
297  rtems_status_code sc;
298
299  sc = rtems_semaphore_obtain(ctx->sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
300  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
301}
302
303static void sem_release(test_context *ctx)
304{
305  rtems_status_code sc;
306
307  sc = rtems_semaphore_release(ctx->sem);
308  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
309}
310
311static void ceil_obtain(test_context *ctx)
312{
313  rtems_status_code sc;
314
315  sc = rtems_semaphore_obtain(ctx->ceil, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
316  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
317}
318
319static void ceil_release(test_context *ctx)
320{
321  rtems_status_code sc;
322
323  sc = rtems_semaphore_release(ctx->ceil);
324  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
325}
326
327static void wait(void)
328{
329  rtems_status_code sc;
330
331  sc = rtems_task_wake_after(TIMEOUT_IN_TICKS + 1);
332  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
333}
334
335static void check_generations(test_context *ctx, task_id a, task_id b)
336{
337  size_t i;
338
339  if (a != NONE) {
340    ++ctx->expected_generation[a];
341  }
342
343  if (b != NONE) {
344    ++ctx->expected_generation[b];
345  }
346
347  for (i = 0; i < TASK_COUNT; ++i) {
348    rtems_test_assert(ctx->generation[i] == ctx->expected_generation[i]);
349  }
350}
351
352static void yield(void)
353{
354  rtems_status_code sc;
355
356  sc = rtems_task_wake_after(RTEMS_YIELD_PROCESSOR);
357  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
358}
359
360static void set_prio(test_context *ctx, task_id id, rtems_task_priority prio)
361{
362  rtems_status_code sc;
363
364  sc = rtems_task_set_priority(ctx->tasks[id], prio, &prio);
365  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
366}
367
368static void assert_prio(
369  test_context *ctx,
370  task_id id,
371  rtems_task_priority expected
372)
373{
374  rtems_task_priority actual;
375  rtems_status_code sc;
376
377  sc = rtems_task_set_priority(
378    ctx->tasks[id],
379    RTEMS_CURRENT_PRIORITY,
380    &actual
381  );
382  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
383  rtems_test_assert(expected == actual);
384}
385
386static void assert_prio_by_scheduler(
387  test_context *ctx,
388  task_id id,
389  rtems_name scheduler,
390  rtems_task_priority expected
391)
392{
393  rtems_task_priority actual;
394  rtems_status_code sc;
395  rtems_id scheduler_id;
396
397  sc = rtems_scheduler_ident(scheduler, &scheduler_id);
398  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
399
400  actual = PRIO_NONE;
401  sc = rtems_task_get_priority(
402    ctx->tasks[id],
403    scheduler_id,
404    &actual
405  );
406
407  if (expected == PRIO_NONE) {
408    rtems_test_assert(sc == RTEMS_NOT_DEFINED);
409  } else {
410    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
411  }
412
413  rtems_test_assert(actual == expected);
414}
415
416static void helper(rtems_task_argument arg)
417{
418  test_context *ctx = &test_instance;
419
420  while (true) {
421    rtems_event_set events = wait_for_events();
422
423    if ((events & REQ_WAKE_UP_HELPER) != 0) {
424      send_event(ctx, M, REQ_WAKE_UP_MASTER);
425    }
426
427    if ((events & REQ_SEM_RELEASE) != 0) {
428      sem_release(ctx);
429    }
430
431    if ((events & REQ_SET_DONE) != 0) {
432      set_done(ctx);
433    }
434  }
435}
436
437static void worker(rtems_task_argument arg)
438{
439  test_context *ctx = &test_instance;
440  task_id id = arg;
441
442  while (true) {
443    rtems_event_set events = wait_for_events();
444
445    if ((events & REQ_MTX_OBTAIN) != 0) {
446      obtain(ctx);
447      ++ctx->generation[id];
448    }
449
450    if ((events & REQ_MTX_OBTAIN_TIMEOUT) != 0) {
451      obtain_timeout(ctx);
452      ++ctx->generation[id];
453    }
454
455    if ((events & REQ_MTX_OBTAIN_UNSATISFIED) != 0) {
456      obtain_unsatisfied(ctx);
457      ++ctx->generation[id];
458    }
459
460    if ((events & REQ_MTX_RELEASE) != 0) {
461      release(ctx);
462      ++ctx->generation[id];
463    }
464
465    if ((events & REQ_MTX_2_OBTAIN) != 0) {
466      obtain_2(ctx);
467      ++ctx->generation[id];
468    }
469
470    if ((events & REQ_MTX_2_RELEASE) != 0) {
471      release_2(ctx);
472      ++ctx->generation[id];
473    }
474
475    if ((events & REQ_SEM_OBTAIN_RELEASE) != 0) {
476      sem_obtain(ctx);
477      ++ctx->generation[id];
478      sem_release(ctx);
479    }
480
481    if ((events & REQ_SEND_EVENT_2) != 0) {
482      send_event(ctx, ctx->id_2, ctx->events_2);
483    }
484
485    if ((events & REQ_SEND_EVENT_3) != 0) {
486      send_event(ctx, ctx->id_3, ctx->events_3);
487    }
488
489    if ((events & REQ_CEIL_OBTAIN) != 0) {
490      ceil_obtain(ctx);
491      ++ctx->generation[id];
492    }
493
494    if ((events & REQ_CEIL_RELEASE) != 0) {
495      ceil_release(ctx);
496      ++ctx->generation[id];
497    }
498
499    if ((events & REQ_SET_DONE) != 0) {
500      set_done(ctx);
501    }
502
503    if ((events & REQ_WAIT_FOR_DONE) != 0) {
504      wait_for_done(ctx);
505    }
506  }
507}
508
509static void test_init(test_context *ctx)
510{
511  rtems_status_code sc;
512
513  ctx->tasks[M] = rtems_task_self();
514  start_task(ctx, A_1, worker, 1, SCHED_A);
515  start_task(ctx, A_2_0, worker, 2, SCHED_A);
516  start_task(ctx, A_2_1, worker, 2, SCHED_A);
517  start_task(ctx, H_A, helper, 3, SCHED_A);
518
519  if (rtems_get_processor_count() >= PART_COUNT) {
520    start_task(ctx, B_4, worker, 4, SCHED_B);
521    start_task(ctx, B_5_0, worker, 5, SCHED_B);
522    start_task(ctx, B_5_1, worker, 5, SCHED_B);
523    start_task(ctx, H_B, helper, 6, SCHED_B);
524  }
525
526  sc = rtems_semaphore_create(
527    rtems_build_name('M', 'T', 'X', '1'),
528    1,
529    RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY,
530    0,
531    &ctx->mtx
532  );
533  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
534
535  sc = rtems_semaphore_create(
536    rtems_build_name('M', 'T', 'X', '2'),
537    1,
538    RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY,
539    0,
540    &ctx->mtx_2
541  );
542  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
543
544  sc = rtems_semaphore_create(
545    rtems_build_name(' ', 'S', 'E', 'M'),
546    0,
547    RTEMS_COUNTING_SEMAPHORE | RTEMS_PRIORITY,
548    0,
549    &ctx->sem
550  );
551  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
552
553  sc = rtems_semaphore_create(
554    rtems_build_name('C', 'E', 'I', 'L'),
555    1,
556    RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_PRIORITY_CEILING,
557    1,
558    &ctx->ceil
559  );
560  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
561}
562
563static void test_simple_inheritance(test_context *ctx)
564{
565  obtain(ctx);
566  request(ctx, A_1, REQ_MTX_OBTAIN);
567  check_generations(ctx, NONE, NONE);
568  assert_prio(ctx, M, 1);
569  release(ctx);
570  check_generations(ctx, A_1, NONE);
571  assert_prio(ctx, M, 3);
572  request(ctx, A_1, REQ_MTX_RELEASE);
573  check_generations(ctx, A_1, NONE);
574}
575
576static void test_flush_inheritance(test_context *ctx)
577{
578  assert_prio(ctx, M, 3);
579  obtain(ctx);
580  send_event(ctx, A_1, REQ_MTX_OBTAIN_UNSATISFIED);
581  check_generations(ctx, NONE, NONE);
582  assert_prio(ctx, M, 1);
583  flush(ctx);
584  check_generations(ctx, A_1, NONE);
585  assert_prio(ctx, M, 3);
586  release(ctx);
587}
588
589static void test_ceiling_mutex(test_context *ctx)
590{
591  assert_prio(ctx, M, 3);
592  ceil_obtain(ctx);
593  assert_prio(ctx, M, 1);
594  send_event(ctx, A_1, REQ_CEIL_OBTAIN);
595  yield();
596  check_generations(ctx, NONE, NONE);
597  ceil_release(ctx);
598  check_generations(ctx, A_1, NONE);
599  assert_prio(ctx, M, 3);
600  send_event(ctx, A_1, REQ_CEIL_RELEASE);
601  check_generations(ctx, A_1, NONE);
602}
603
604static void test_dequeue_order_one_scheduler_instance(test_context *ctx)
605{
606  obtain(ctx);
607  request(ctx, A_2_0, REQ_MTX_OBTAIN);
608  request(ctx, A_1, REQ_MTX_OBTAIN);
609  request(ctx, A_2_1, REQ_MTX_OBTAIN);
610  check_generations(ctx, NONE, NONE);
611  assert_prio(ctx, M, 1);
612  release(ctx);
613  check_generations(ctx, A_1, NONE);
614  assert_prio(ctx, M, 3);
615  assert_prio(ctx, A_1, 1);
616  request(ctx, A_1, REQ_MTX_RELEASE);
617  check_generations(ctx, A_1, A_2_0);
618  request(ctx, A_2_0, REQ_MTX_RELEASE);
619  check_generations(ctx, A_2_0, A_2_1);
620  request(ctx, A_2_1, REQ_MTX_RELEASE);
621  check_generations(ctx, A_2_1, NONE);
622}
623
624static void test_mixed_queue_two_scheduler_instances(test_context *ctx)
625{
626  obtain(ctx);
627  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
628  assert_prio_by_scheduler(ctx, M, SCHED_B, PRIO_NONE);
629
630  request(ctx, B_4, REQ_MTX_OBTAIN_TIMEOUT);
631  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
632  assert_prio_by_scheduler(ctx, M, SCHED_B, 4);
633  check_generations(ctx, NONE, NONE);
634  wait();
635  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
636  assert_prio_by_scheduler(ctx, M, SCHED_B, PRIO_NONE);
637  check_generations(ctx, B_4, NONE);
638
639  request(ctx, B_4, REQ_MTX_OBTAIN);
640  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
641  assert_prio_by_scheduler(ctx, M, SCHED_B, 4);
642  check_generations(ctx, NONE, NONE);
643
644  request(ctx, B_5_0, REQ_SEM_OBTAIN_RELEASE);
645  send_event(ctx, H_A, REQ_SEM_RELEASE);
646  check_generations(ctx, NONE, NONE);
647
648  /*
649   * We are in scheduler instance A.  Task B_5_0 of scheduler instance B issued
650   * the counting semaphore obtain before us.  However, we inherited the
651   * priority of B_4, so we get the semaphore before B_5_0 (priority order
652   * within scheduler instance B).
653   */
654  sem_obtain(ctx);
655  check_generations(ctx, NONE, NONE);
656
657  release(ctx);
658  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
659  assert_prio_by_scheduler(ctx, M, SCHED_B, PRIO_NONE);
660  sync_with_helper(ctx);
661  check_generations(ctx, B_4, NONE);
662
663  request(ctx, B_4, REQ_MTX_RELEASE);
664  check_generations(ctx, B_4, NONE);
665
666  sem_release(ctx);
667  sync_with_helper(ctx);
668  check_generations(ctx, B_5_0, NONE);
669
670  sem_obtain(ctx);
671}
672
673static void test_mixed_queue_two_scheduler_instances_sem_only(test_context *ctx)
674{
675  request(ctx, B_5_0, REQ_SEM_OBTAIN_RELEASE);
676  send_event(ctx, H_A, REQ_SEM_RELEASE);
677  check_generations(ctx, NONE, NONE);
678
679  /*
680   * We are in scheduler instance A.  Task B_5_0 of scheduler instance B issued
681   * the counting semaphore obtain before us.  No priority inheritance is
682   * involved, so task B_5_0 gets the counting semaphore first.
683   */
684  sem_obtain(ctx);
685  check_generations(ctx, B_5_0, NONE);
686
687  sem_release(ctx);
688}
689
690static void test_simple_inheritance_two_scheduler_instances(test_context *ctx)
691{
692  obtain(ctx);
693  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
694  assert_prio_by_scheduler(ctx, M, SCHED_B, PRIO_NONE);
695
696  request(ctx, B_5_0, REQ_MTX_OBTAIN);
697  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
698  assert_prio_by_scheduler(ctx, M, SCHED_B, 5);
699
700  request(ctx, B_4, REQ_MTX_OBTAIN);
701  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
702  assert_prio_by_scheduler(ctx, M, SCHED_B, 4);
703
704  request(ctx, B_5_1, REQ_MTX_OBTAIN);
705  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
706  assert_prio_by_scheduler(ctx, M, SCHED_B, 4);
707  check_generations(ctx, NONE, NONE);
708
709  release(ctx);
710  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
711  assert_prio_by_scheduler(ctx, M, SCHED_B, PRIO_NONE);
712  sync_with_helper(ctx);
713  check_generations(ctx, B_4, NONE);
714
715  request(ctx, B_4, REQ_MTX_RELEASE);
716  check_generations(ctx, B_4, B_5_0);
717
718  request(ctx, B_5_0, REQ_MTX_RELEASE);
719  check_generations(ctx, B_5_0, B_5_1);
720
721  request(ctx, B_5_1, REQ_MTX_RELEASE);
722  check_generations(ctx, B_5_1, NONE);
723}
724
725static void test_nested_inheritance_two_scheduler_instances(test_context *ctx)
726{
727  obtain_2(ctx);
728  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
729  assert_prio_by_scheduler(ctx, M, SCHED_B, PRIO_NONE);
730
731  request(ctx, B_5_0, REQ_MTX_OBTAIN);
732  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
733  assert_prio_by_scheduler(ctx, M, SCHED_B, PRIO_NONE);
734  assert_prio_by_scheduler(ctx, B_5_0, SCHED_A, PRIO_NONE);
735  assert_prio_by_scheduler(ctx, B_5_0, SCHED_B, 5);
736  check_generations(ctx, B_5_0, NONE);
737
738  request(ctx, B_5_0, REQ_MTX_2_OBTAIN);
739  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
740  assert_prio_by_scheduler(ctx, M, SCHED_B, 5);
741  assert_prio_by_scheduler(ctx, B_5_0, SCHED_A, PRIO_NONE);
742  assert_prio_by_scheduler(ctx, B_5_0, SCHED_B, 5);
743
744  request(ctx, B_4, REQ_MTX_OBTAIN_TIMEOUT);
745  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
746  assert_prio_by_scheduler(ctx, M, SCHED_B, 4);
747  assert_prio_by_scheduler(ctx, B_5_0, SCHED_A, PRIO_NONE);
748  assert_prio_by_scheduler(ctx, B_5_0, SCHED_B, 4);
749  wait();
750  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
751  assert_prio_by_scheduler(ctx, M, SCHED_B, 5);
752  assert_prio_by_scheduler(ctx, B_5_0, SCHED_A, PRIO_NONE);
753  assert_prio_by_scheduler(ctx, B_5_0, SCHED_B, 5);
754  check_generations(ctx, B_4, NONE);
755
756  request(ctx, B_4, REQ_MTX_OBTAIN);
757  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
758  assert_prio_by_scheduler(ctx, M, SCHED_B, 4);
759  assert_prio_by_scheduler(ctx, B_5_0, SCHED_A, PRIO_NONE);
760  assert_prio_by_scheduler(ctx, B_5_0, SCHED_B, 4);
761
762  request(ctx, B_5_1, REQ_MTX_2_OBTAIN);
763  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
764  assert_prio_by_scheduler(ctx, M, SCHED_B, 4);
765  assert_prio_by_scheduler(ctx, B_5_0, SCHED_A, PRIO_NONE);
766  assert_prio_by_scheduler(ctx, B_5_0, SCHED_B, 4);
767  check_generations(ctx, NONE, NONE);
768
769  release_2(ctx);
770  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
771  assert_prio_by_scheduler(ctx, M, SCHED_B, PRIO_NONE);
772  assert_prio_by_scheduler(ctx, B_5_0, SCHED_A, PRIO_NONE);
773  assert_prio_by_scheduler(ctx, B_5_0, SCHED_B, 4);
774  sync_with_helper(ctx);
775  check_generations(ctx, B_5_0, NONE);
776
777  request(ctx, B_5_0, REQ_MTX_RELEASE);
778  assert_prio_by_scheduler(ctx, B_5_0, SCHED_A, PRIO_NONE);
779  assert_prio_by_scheduler(ctx, B_5_0, SCHED_B, 5);
780  check_generations(ctx, B_4, B_5_0);
781
782  request(ctx, B_4, REQ_MTX_RELEASE);
783  check_generations(ctx, B_4, NONE);
784
785  request(ctx, B_5_0, REQ_MTX_2_RELEASE);
786  check_generations(ctx, B_5_0, B_5_1);
787
788  request(ctx, B_5_1, REQ_MTX_2_RELEASE);
789  check_generations(ctx, B_5_1, NONE);
790}
791
792static void test_dequeue_order_two_scheduler_instances(test_context *ctx)
793{
794  obtain(ctx);
795  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
796  assert_prio_by_scheduler(ctx, M, SCHED_B, PRIO_NONE);
797
798  request(ctx, A_2_0, REQ_MTX_OBTAIN);
799  assert_prio_by_scheduler(ctx, M, SCHED_A, 2);
800  assert_prio_by_scheduler(ctx, M, SCHED_B, PRIO_NONE);
801  check_generations(ctx, NONE, NONE);
802
803  request(ctx, B_5_0, REQ_MTX_OBTAIN);
804  assert_prio_by_scheduler(ctx, M, SCHED_A, 2);
805  assert_prio_by_scheduler(ctx, M, SCHED_B, 5);
806  check_generations(ctx, NONE, NONE);
807
808  request(ctx, B_5_1, REQ_MTX_OBTAIN);
809  assert_prio_by_scheduler(ctx, M, SCHED_A, 2);
810  assert_prio_by_scheduler(ctx, M, SCHED_B, 5);
811
812  request(ctx, B_4, REQ_MTX_OBTAIN);
813  assert_prio_by_scheduler(ctx, M, SCHED_A, 2);
814  assert_prio_by_scheduler(ctx, M, SCHED_B, 4);
815
816  request(ctx, A_2_1, REQ_MTX_OBTAIN);
817  assert_prio_by_scheduler(ctx, M, SCHED_A, 2);
818  assert_prio_by_scheduler(ctx, M, SCHED_B, 4);
819
820  request(ctx, A_1, REQ_MTX_OBTAIN);
821  assert_prio_by_scheduler(ctx, M, SCHED_A, 1);
822  assert_prio_by_scheduler(ctx, M, SCHED_B, 4);
823  check_generations(ctx, NONE, NONE);
824
825  release(ctx);
826  sync_with_helper(ctx);
827  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
828  assert_prio_by_scheduler(ctx, M, SCHED_B, PRIO_NONE);
829  assert_prio_by_scheduler(ctx, A_1, SCHED_A, 1);
830  assert_prio_by_scheduler(ctx, A_1, SCHED_B, 4);
831  check_generations(ctx, A_1, NONE);
832
833  request(ctx, A_1, REQ_MTX_RELEASE);
834  assert_prio_by_scheduler(ctx, A_1, SCHED_A, 1);
835  assert_prio_by_scheduler(ctx, A_1, SCHED_B, PRIO_NONE);
836  assert_prio_by_scheduler(ctx, B_4, SCHED_A, 2);
837  assert_prio_by_scheduler(ctx, B_4, SCHED_B, 4);
838  check_generations(ctx, A_1, B_4);
839
840  request(ctx, B_4, REQ_MTX_RELEASE);
841  assert_prio_by_scheduler(ctx, B_4, SCHED_A, PRIO_NONE);
842  assert_prio_by_scheduler(ctx, B_4, SCHED_B, 4);
843  assert_prio_by_scheduler(ctx, A_2_0, SCHED_A, 2);
844  assert_prio_by_scheduler(ctx, A_2_0, SCHED_B, 5);
845  check_generations(ctx, B_4, A_2_0);
846
847  request(ctx, A_2_0, REQ_MTX_RELEASE);
848  assert_prio_by_scheduler(ctx, A_2_0, SCHED_A, 2);
849  assert_prio_by_scheduler(ctx, A_2_0, SCHED_B, PRIO_NONE);
850  assert_prio_by_scheduler(ctx, B_5_0, SCHED_A, 2);
851  assert_prio_by_scheduler(ctx, B_5_0, SCHED_B, 5);
852  check_generations(ctx, A_2_0, B_5_0);
853
854  request(ctx, B_5_0, REQ_MTX_RELEASE);
855  assert_prio_by_scheduler(ctx, B_5_0, SCHED_A, PRIO_NONE);
856  assert_prio_by_scheduler(ctx, B_5_0, SCHED_B, 5);
857  assert_prio_by_scheduler(ctx, A_2_1, SCHED_A, 2);
858  assert_prio_by_scheduler(ctx, A_2_1, SCHED_B, 5);
859  check_generations(ctx, B_5_0, A_2_1);
860
861  request(ctx, A_2_1, REQ_MTX_RELEASE);
862  assert_prio_by_scheduler(ctx, A_2_1, SCHED_A, 2);
863  assert_prio_by_scheduler(ctx, A_2_1, SCHED_B, PRIO_NONE);
864  assert_prio_by_scheduler(ctx, B_5_1, SCHED_A, PRIO_NONE);
865  assert_prio_by_scheduler(ctx, B_5_1, SCHED_B, 5);
866  check_generations(ctx, A_2_1, B_5_1);
867
868  request(ctx, B_5_1, REQ_MTX_RELEASE);
869  assert_prio_by_scheduler(ctx, B_5_1, SCHED_A, PRIO_NONE);
870  assert_prio_by_scheduler(ctx, B_5_1, SCHED_B, 5);
871  check_generations(ctx, B_5_1, NONE);
872}
873
874static void test_omip_pre_emption(test_context *ctx)
875{
876  assert_cpu(0);
877  obtain(ctx);
878  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
879  assert_prio_by_scheduler(ctx, M, SCHED_B, PRIO_NONE);
880
881  request(ctx, B_5_0, REQ_MTX_OBTAIN);
882  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
883  assert_prio_by_scheduler(ctx, M, SCHED_B, 5);
884  check_generations(ctx, NONE, NONE);
885
886  request_pre_emption(ctx, A_1);
887  assert_cpu(1);
888
889  request_pre_emption(ctx, B_4);
890  assert_cpu(0);
891
892  request_pre_emption(ctx, A_1);
893  assert_cpu(1);
894
895  release(ctx);
896  assert_cpu(0);
897  sync_with_helper(ctx);
898  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
899  assert_prio_by_scheduler(ctx, M, SCHED_B, PRIO_NONE);
900  check_generations(ctx, B_5_0, NONE);
901
902  request(ctx, B_5_0, REQ_MTX_RELEASE);
903  assert_prio_by_scheduler(ctx, B_5_0, SCHED_A, PRIO_NONE);
904  assert_prio_by_scheduler(ctx, B_5_0, SCHED_B, 5);
905  check_generations(ctx, B_5_0, NONE);
906}
907
908static void test_omip_rescue(test_context *ctx)
909{
910  assert_cpu(0);
911  obtain(ctx);
912  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
913  assert_prio_by_scheduler(ctx, M, SCHED_B, PRIO_NONE);
914
915  clear_done(ctx);
916  set_event_3(ctx, H_B, REQ_SET_DONE);
917  set_event_2(ctx, B_5_0, REQ_SEND_EVENT_3 | REQ_MTX_OBTAIN);
918  send_event(ctx, A_1, REQ_SEND_EVENT_2 | REQ_WAIT_FOR_DONE);
919  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
920  assert_prio_by_scheduler(ctx, M, SCHED_B, 5);
921  assert_cpu(1);
922
923  release(ctx);
924  assert_cpu(0);
925  sync_with_helper(ctx);
926  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
927  assert_prio_by_scheduler(ctx, M, SCHED_B, PRIO_NONE);
928  check_generations(ctx, B_5_0, NONE);
929
930  request(ctx, B_5_0, REQ_MTX_RELEASE);
931  assert_prio_by_scheduler(ctx, B_5_0, SCHED_A, PRIO_NONE);
932  assert_prio_by_scheduler(ctx, B_5_0, SCHED_B, 5);
933  check_generations(ctx, B_5_0, NONE);
934}
935
936static void test_omip_timeout(test_context *ctx)
937{
938  assert_cpu(0);
939  obtain(ctx);
940  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
941  assert_prio_by_scheduler(ctx, M, SCHED_B, PRIO_NONE);
942
943  clear_done(ctx);
944  set_event_3(ctx, H_B, REQ_SET_DONE);
945  set_event_2(ctx, B_5_0, REQ_SEND_EVENT_3 | REQ_MTX_OBTAIN_TIMEOUT);
946  send_event(ctx, A_1, REQ_SEND_EVENT_2 | REQ_WAIT_FOR_DONE);
947  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
948  assert_prio_by_scheduler(ctx, M, SCHED_B, 5);
949  assert_cpu(1);
950
951  wait();
952  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
953  assert_prio_by_scheduler(ctx, M, SCHED_B, PRIO_NONE);
954  check_generations(ctx, B_5_0, NONE);
955  assert_cpu(0);
956
957  release(ctx);
958}
959
960static void test_omip_yield(test_context *ctx)
961{
962  assert_cpu(0);
963  obtain(ctx);
964  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
965  assert_prio_by_scheduler(ctx, M, SCHED_B, PRIO_NONE);
966
967  request(ctx, B_5_0, REQ_MTX_OBTAIN);
968  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
969  assert_prio_by_scheduler(ctx, M, SCHED_B, 5);
970  check_generations(ctx, NONE, NONE);
971
972  clear_done(ctx);
973  send_event(ctx, H_A, REQ_SET_DONE);
974  yield();
975  assert_cpu(1);
976  wait_for_done(ctx);
977
978  clear_done(ctx);
979  send_event(ctx, H_B, REQ_SET_DONE);
980  set_prio(ctx, H_B, 5);
981  yield();
982  assert_cpu(1);
983  rtems_test_assert(!is_done(ctx));
984
985  set_prio(ctx, H_B, 4);
986  assert_cpu(0);
987
988  wait_for_done(ctx);
989  set_prio(ctx, H_B, 6);
990
991  release(ctx);
992  sync_with_helper(ctx);
993  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
994  assert_prio_by_scheduler(ctx, M, SCHED_B, PRIO_NONE);
995  check_generations(ctx, B_5_0, NONE);
996
997  request(ctx, B_5_0, REQ_MTX_RELEASE);
998  assert_prio_by_scheduler(ctx, B_5_0, SCHED_A, PRIO_NONE);
999  assert_prio_by_scheduler(ctx, B_5_0, SCHED_B, 5);
1000  check_generations(ctx, B_5_0, NONE);
1001}
1002
1003static void test(test_context *ctx)
1004{
1005  test_init(ctx);
1006
1007  if (rtems_get_processor_count() >= PART_COUNT) {
1008    test_task_get_priority_not_defined(ctx);
1009    test_simple_inheritance(ctx);
1010    test_dequeue_order_one_scheduler_instance(ctx);
1011    test_mixed_queue_two_scheduler_instances(ctx);
1012    test_mixed_queue_two_scheduler_instances_sem_only(ctx);
1013    test_simple_inheritance_two_scheduler_instances(ctx);
1014    test_nested_inheritance_two_scheduler_instances(ctx);
1015    test_dequeue_order_two_scheduler_instances(ctx);
1016    test_omip_pre_emption(ctx);
1017    test_omip_rescue(ctx);
1018    test_omip_timeout(ctx);
1019    test_omip_yield(ctx);
1020  }
1021
1022  test_flush_inheritance(ctx);
1023  test_ceiling_mutex(ctx);
1024}
1025
1026static void Init(rtems_task_argument arg)
1027{
1028  TEST_BEGIN();
1029  test(&test_instance);
1030  TEST_END();
1031  rtems_test_exit(0);
1032}
1033
1034#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
1035#define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
1036
1037#define CONFIGURE_MAXIMUM_PROCESSORS PART_COUNT
1038
1039#define CONFIGURE_SCHEDULER_SIMPLE_SMP
1040
1041#include <rtems/scheduler.h>
1042
1043RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(a);
1044
1045RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(b);
1046
1047#define CONFIGURE_SCHEDULER_CONTROLS \
1048  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(a, SCHED_A), \
1049  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(b, SCHED_B)
1050
1051#define CONFIGURE_SMP_SCHEDULER_ASSIGNMENTS \
1052  RTEMS_SCHEDULER_ASSIGN(0, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_MANDATORY), \
1053  RTEMS_SCHEDULER_ASSIGN(1, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL)
1054
1055#define CONFIGURE_MAXIMUM_TASKS TASK_COUNT
1056
1057#define CONFIGURE_MAXIMUM_SEMAPHORES 4
1058
1059#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
1060
1061#define CONFIGURE_INIT_TASK_PRIORITY 3
1062
1063#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
1064
1065#define CONFIGURE_INIT
1066
1067#include <rtems/confdefs.h>
Note: See TracBrowser for help on using the repository browser.