source: rtems/testsuites/smptests/smpmutex01/init.c @ fbd08066

5
Last change on this file since fbd08066 was fbd08066, checked in by Sebastian Huber <sebastian.huber@…>, on 02/07/19 at 06:46:38

score: Fix plain priority thread queues (SMP)

We must add/remove the priority queue to the FIFO of priority queues.

  • Property mode set to 100644
File size: 29.0 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 chosen 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_two_scheduler_instances_sem_with_inheritance(test_context *ctx)
691{
692  sem_obtain(ctx);
693
694  request(ctx, B_4, REQ_MTX_OBTAIN);
695  check_generations(ctx, B_4, NONE);
696  assert_prio_by_scheduler(ctx, B_4, SCHED_A, PRIO_NONE);
697  assert_prio_by_scheduler(ctx, B_4, SCHED_B, 4);
698
699  request(ctx, B_4, REQ_SEM_OBTAIN_RELEASE);
700  check_generations(ctx, NONE, NONE);
701
702  request(ctx, A_1, REQ_MTX_OBTAIN);
703  check_generations(ctx, NONE, NONE);
704  assert_prio_by_scheduler(ctx, B_4, SCHED_A, 1);
705  assert_prio_by_scheduler(ctx, B_4, SCHED_B, 4);
706
707  sem_release(ctx);
708  sync_with_helper(ctx);
709  check_generations(ctx, B_4, NONE);
710
711  request(ctx, B_4, REQ_MTX_RELEASE);
712  check_generations(ctx, B_4, A_1);
713  assert_prio_by_scheduler(ctx, B_4, SCHED_A, PRIO_NONE);
714  assert_prio_by_scheduler(ctx, B_4, SCHED_B, 4);
715
716  request(ctx, A_1, REQ_MTX_RELEASE);
717  check_generations(ctx, A_1, NONE);
718}
719
720static void test_two_scheduler_instances_sem_with_inheritance_timeout(test_context *ctx)
721{
722  sem_obtain(ctx);
723
724  request(ctx, B_4, REQ_MTX_OBTAIN);
725  check_generations(ctx, B_4, NONE);
726  assert_prio_by_scheduler(ctx, B_4, SCHED_A, PRIO_NONE);
727  assert_prio_by_scheduler(ctx, B_4, SCHED_B, 4);
728
729  request(ctx, B_4, REQ_SEM_OBTAIN_RELEASE);
730  check_generations(ctx, NONE, NONE);
731
732  request(ctx, A_1, REQ_MTX_OBTAIN_TIMEOUT);
733  check_generations(ctx, NONE, NONE);
734  assert_prio_by_scheduler(ctx, B_4, SCHED_A, 1);
735  assert_prio_by_scheduler(ctx, B_4, SCHED_B, 4);
736  wait();
737  check_generations(ctx, A_1, NONE);
738  assert_prio_by_scheduler(ctx, B_4, SCHED_A, PRIO_NONE);
739  assert_prio_by_scheduler(ctx, B_4, SCHED_B, 4);
740
741  sem_release(ctx);
742  sync_with_helper(ctx);
743  check_generations(ctx, B_4, NONE);
744
745  request(ctx, B_4, REQ_MTX_RELEASE);
746  check_generations(ctx, B_4, NONE);
747  assert_prio_by_scheduler(ctx, B_4, SCHED_A, PRIO_NONE);
748  assert_prio_by_scheduler(ctx, B_4, SCHED_B, 4);
749}
750
751static void test_simple_inheritance_two_scheduler_instances(test_context *ctx)
752{
753  obtain(ctx);
754  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
755  assert_prio_by_scheduler(ctx, M, SCHED_B, PRIO_NONE);
756
757  request(ctx, B_5_0, REQ_MTX_OBTAIN);
758  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
759  assert_prio_by_scheduler(ctx, M, SCHED_B, 5);
760
761  request(ctx, B_4, REQ_MTX_OBTAIN);
762  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
763  assert_prio_by_scheduler(ctx, M, SCHED_B, 4);
764
765  request(ctx, B_5_1, REQ_MTX_OBTAIN);
766  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
767  assert_prio_by_scheduler(ctx, M, SCHED_B, 4);
768  check_generations(ctx, NONE, NONE);
769
770  release(ctx);
771  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
772  assert_prio_by_scheduler(ctx, M, SCHED_B, PRIO_NONE);
773  sync_with_helper(ctx);
774  check_generations(ctx, B_4, NONE);
775
776  request(ctx, B_4, REQ_MTX_RELEASE);
777  check_generations(ctx, B_4, B_5_0);
778
779  request(ctx, B_5_0, REQ_MTX_RELEASE);
780  check_generations(ctx, B_5_0, B_5_1);
781
782  request(ctx, B_5_1, REQ_MTX_RELEASE);
783  check_generations(ctx, B_5_1, NONE);
784}
785
786static void test_nested_inheritance_two_scheduler_instances(test_context *ctx)
787{
788  obtain_2(ctx);
789  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
790  assert_prio_by_scheduler(ctx, M, SCHED_B, PRIO_NONE);
791
792  request(ctx, B_5_0, REQ_MTX_OBTAIN);
793  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
794  assert_prio_by_scheduler(ctx, M, SCHED_B, PRIO_NONE);
795  assert_prio_by_scheduler(ctx, B_5_0, SCHED_A, PRIO_NONE);
796  assert_prio_by_scheduler(ctx, B_5_0, SCHED_B, 5);
797  check_generations(ctx, B_5_0, NONE);
798
799  request(ctx, B_5_0, REQ_MTX_2_OBTAIN);
800  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
801  assert_prio_by_scheduler(ctx, M, SCHED_B, 5);
802  assert_prio_by_scheduler(ctx, B_5_0, SCHED_A, PRIO_NONE);
803  assert_prio_by_scheduler(ctx, B_5_0, SCHED_B, 5);
804
805  request(ctx, B_4, REQ_MTX_OBTAIN_TIMEOUT);
806  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
807  assert_prio_by_scheduler(ctx, M, SCHED_B, 4);
808  assert_prio_by_scheduler(ctx, B_5_0, SCHED_A, PRIO_NONE);
809  assert_prio_by_scheduler(ctx, B_5_0, SCHED_B, 4);
810  wait();
811  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
812  assert_prio_by_scheduler(ctx, M, SCHED_B, 5);
813  assert_prio_by_scheduler(ctx, B_5_0, SCHED_A, PRIO_NONE);
814  assert_prio_by_scheduler(ctx, B_5_0, SCHED_B, 5);
815  check_generations(ctx, B_4, NONE);
816
817  request(ctx, B_4, REQ_MTX_OBTAIN);
818  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
819  assert_prio_by_scheduler(ctx, M, SCHED_B, 4);
820  assert_prio_by_scheduler(ctx, B_5_0, SCHED_A, PRIO_NONE);
821  assert_prio_by_scheduler(ctx, B_5_0, SCHED_B, 4);
822
823  request(ctx, B_5_1, REQ_MTX_2_OBTAIN);
824  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
825  assert_prio_by_scheduler(ctx, M, SCHED_B, 4);
826  assert_prio_by_scheduler(ctx, B_5_0, SCHED_A, PRIO_NONE);
827  assert_prio_by_scheduler(ctx, B_5_0, SCHED_B, 4);
828  check_generations(ctx, NONE, NONE);
829
830  release_2(ctx);
831  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
832  assert_prio_by_scheduler(ctx, M, SCHED_B, PRIO_NONE);
833  assert_prio_by_scheduler(ctx, B_5_0, SCHED_A, PRIO_NONE);
834  assert_prio_by_scheduler(ctx, B_5_0, SCHED_B, 4);
835  sync_with_helper(ctx);
836  check_generations(ctx, B_5_0, NONE);
837
838  request(ctx, B_5_0, REQ_MTX_RELEASE);
839  assert_prio_by_scheduler(ctx, B_5_0, SCHED_A, PRIO_NONE);
840  assert_prio_by_scheduler(ctx, B_5_0, SCHED_B, 5);
841  check_generations(ctx, B_4, B_5_0);
842
843  request(ctx, B_4, REQ_MTX_RELEASE);
844  check_generations(ctx, B_4, NONE);
845
846  request(ctx, B_5_0, REQ_MTX_2_RELEASE);
847  check_generations(ctx, B_5_0, B_5_1);
848
849  request(ctx, B_5_1, REQ_MTX_2_RELEASE);
850  check_generations(ctx, B_5_1, NONE);
851}
852
853static void test_dequeue_order_two_scheduler_instances(test_context *ctx)
854{
855  obtain(ctx);
856  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
857  assert_prio_by_scheduler(ctx, M, SCHED_B, PRIO_NONE);
858
859  request(ctx, A_2_0, REQ_MTX_OBTAIN);
860  assert_prio_by_scheduler(ctx, M, SCHED_A, 2);
861  assert_prio_by_scheduler(ctx, M, SCHED_B, PRIO_NONE);
862  check_generations(ctx, NONE, NONE);
863
864  request(ctx, B_5_0, REQ_MTX_OBTAIN);
865  assert_prio_by_scheduler(ctx, M, SCHED_A, 2);
866  assert_prio_by_scheduler(ctx, M, SCHED_B, 5);
867  check_generations(ctx, NONE, NONE);
868
869  request(ctx, B_5_1, REQ_MTX_OBTAIN);
870  assert_prio_by_scheduler(ctx, M, SCHED_A, 2);
871  assert_prio_by_scheduler(ctx, M, SCHED_B, 5);
872
873  request(ctx, B_4, REQ_MTX_OBTAIN);
874  assert_prio_by_scheduler(ctx, M, SCHED_A, 2);
875  assert_prio_by_scheduler(ctx, M, SCHED_B, 4);
876
877  request(ctx, A_2_1, REQ_MTX_OBTAIN);
878  assert_prio_by_scheduler(ctx, M, SCHED_A, 2);
879  assert_prio_by_scheduler(ctx, M, SCHED_B, 4);
880
881  request(ctx, A_1, REQ_MTX_OBTAIN);
882  assert_prio_by_scheduler(ctx, M, SCHED_A, 1);
883  assert_prio_by_scheduler(ctx, M, SCHED_B, 4);
884  check_generations(ctx, NONE, NONE);
885
886  release(ctx);
887  sync_with_helper(ctx);
888  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
889  assert_prio_by_scheduler(ctx, M, SCHED_B, PRIO_NONE);
890  assert_prio_by_scheduler(ctx, A_1, SCHED_A, 1);
891  assert_prio_by_scheduler(ctx, A_1, SCHED_B, 4);
892  check_generations(ctx, A_1, NONE);
893
894  request(ctx, A_1, REQ_MTX_RELEASE);
895  assert_prio_by_scheduler(ctx, A_1, SCHED_A, 1);
896  assert_prio_by_scheduler(ctx, A_1, SCHED_B, PRIO_NONE);
897  assert_prio_by_scheduler(ctx, B_4, SCHED_A, 2);
898  assert_prio_by_scheduler(ctx, B_4, SCHED_B, 4);
899  check_generations(ctx, A_1, B_4);
900
901  request(ctx, B_4, REQ_MTX_RELEASE);
902  assert_prio_by_scheduler(ctx, B_4, SCHED_A, PRIO_NONE);
903  assert_prio_by_scheduler(ctx, B_4, SCHED_B, 4);
904  assert_prio_by_scheduler(ctx, A_2_0, SCHED_A, 2);
905  assert_prio_by_scheduler(ctx, A_2_0, SCHED_B, 5);
906  check_generations(ctx, B_4, A_2_0);
907
908  request(ctx, A_2_0, REQ_MTX_RELEASE);
909  assert_prio_by_scheduler(ctx, A_2_0, SCHED_A, 2);
910  assert_prio_by_scheduler(ctx, A_2_0, SCHED_B, PRIO_NONE);
911  assert_prio_by_scheduler(ctx, B_5_0, SCHED_A, 2);
912  assert_prio_by_scheduler(ctx, B_5_0, SCHED_B, 5);
913  check_generations(ctx, A_2_0, B_5_0);
914
915  request(ctx, B_5_0, REQ_MTX_RELEASE);
916  assert_prio_by_scheduler(ctx, B_5_0, SCHED_A, PRIO_NONE);
917  assert_prio_by_scheduler(ctx, B_5_0, SCHED_B, 5);
918  assert_prio_by_scheduler(ctx, A_2_1, SCHED_A, 2);
919  assert_prio_by_scheduler(ctx, A_2_1, SCHED_B, 5);
920  check_generations(ctx, B_5_0, A_2_1);
921
922  request(ctx, A_2_1, REQ_MTX_RELEASE);
923  assert_prio_by_scheduler(ctx, A_2_1, SCHED_A, 2);
924  assert_prio_by_scheduler(ctx, A_2_1, SCHED_B, PRIO_NONE);
925  assert_prio_by_scheduler(ctx, B_5_1, SCHED_A, PRIO_NONE);
926  assert_prio_by_scheduler(ctx, B_5_1, SCHED_B, 5);
927  check_generations(ctx, A_2_1, B_5_1);
928
929  request(ctx, B_5_1, REQ_MTX_RELEASE);
930  assert_prio_by_scheduler(ctx, B_5_1, SCHED_A, PRIO_NONE);
931  assert_prio_by_scheduler(ctx, B_5_1, SCHED_B, 5);
932  check_generations(ctx, B_5_1, NONE);
933}
934
935static void test_omip_pre_emption(test_context *ctx)
936{
937  assert_cpu(0);
938  obtain(ctx);
939  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
940  assert_prio_by_scheduler(ctx, M, SCHED_B, PRIO_NONE);
941
942  request(ctx, B_5_0, REQ_MTX_OBTAIN);
943  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
944  assert_prio_by_scheduler(ctx, M, SCHED_B, 5);
945  check_generations(ctx, NONE, NONE);
946
947  request_pre_emption(ctx, A_1);
948  assert_cpu(1);
949
950  request_pre_emption(ctx, B_4);
951  assert_cpu(0);
952
953  request_pre_emption(ctx, A_1);
954  assert_cpu(1);
955
956  release(ctx);
957  assert_cpu(0);
958  sync_with_helper(ctx);
959  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
960  assert_prio_by_scheduler(ctx, M, SCHED_B, PRIO_NONE);
961  check_generations(ctx, B_5_0, NONE);
962
963  request(ctx, B_5_0, REQ_MTX_RELEASE);
964  assert_prio_by_scheduler(ctx, B_5_0, SCHED_A, PRIO_NONE);
965  assert_prio_by_scheduler(ctx, B_5_0, SCHED_B, 5);
966  check_generations(ctx, B_5_0, NONE);
967}
968
969static void test_omip_rescue(test_context *ctx)
970{
971  assert_cpu(0);
972  obtain(ctx);
973  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
974  assert_prio_by_scheduler(ctx, M, SCHED_B, PRIO_NONE);
975
976  clear_done(ctx);
977  set_event_3(ctx, H_B, REQ_SET_DONE);
978  set_event_2(ctx, B_5_0, REQ_SEND_EVENT_3 | REQ_MTX_OBTAIN);
979  send_event(ctx, A_1, REQ_SEND_EVENT_2 | REQ_WAIT_FOR_DONE);
980  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
981  assert_prio_by_scheduler(ctx, M, SCHED_B, 5);
982  assert_cpu(1);
983
984  release(ctx);
985  assert_cpu(0);
986  sync_with_helper(ctx);
987  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
988  assert_prio_by_scheduler(ctx, M, SCHED_B, PRIO_NONE);
989  check_generations(ctx, B_5_0, NONE);
990
991  request(ctx, B_5_0, REQ_MTX_RELEASE);
992  assert_prio_by_scheduler(ctx, B_5_0, SCHED_A, PRIO_NONE);
993  assert_prio_by_scheduler(ctx, B_5_0, SCHED_B, 5);
994  check_generations(ctx, B_5_0, NONE);
995}
996
997static void test_omip_timeout(test_context *ctx)
998{
999  assert_cpu(0);
1000  obtain(ctx);
1001  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
1002  assert_prio_by_scheduler(ctx, M, SCHED_B, PRIO_NONE);
1003
1004  clear_done(ctx);
1005  set_event_3(ctx, H_B, REQ_SET_DONE);
1006  set_event_2(ctx, B_5_0, REQ_SEND_EVENT_3 | REQ_MTX_OBTAIN_TIMEOUT);
1007  send_event(ctx, A_1, REQ_SEND_EVENT_2 | REQ_WAIT_FOR_DONE);
1008  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
1009  assert_prio_by_scheduler(ctx, M, SCHED_B, 5);
1010  assert_cpu(1);
1011
1012  wait();
1013  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
1014  assert_prio_by_scheduler(ctx, M, SCHED_B, PRIO_NONE);
1015  check_generations(ctx, B_5_0, NONE);
1016  assert_cpu(0);
1017
1018  release(ctx);
1019}
1020
1021static void test_omip_yield(test_context *ctx)
1022{
1023  assert_cpu(0);
1024  obtain(ctx);
1025  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
1026  assert_prio_by_scheduler(ctx, M, SCHED_B, PRIO_NONE);
1027
1028  request(ctx, B_5_0, REQ_MTX_OBTAIN);
1029  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
1030  assert_prio_by_scheduler(ctx, M, SCHED_B, 5);
1031  check_generations(ctx, NONE, NONE);
1032
1033  clear_done(ctx);
1034  send_event(ctx, H_A, REQ_SET_DONE);
1035  yield();
1036  assert_cpu(1);
1037  wait_for_done(ctx);
1038
1039  clear_done(ctx);
1040  send_event(ctx, H_B, REQ_SET_DONE);
1041  set_prio(ctx, H_B, 5);
1042  yield();
1043  assert_cpu(1);
1044  rtems_test_assert(!is_done(ctx));
1045
1046  set_prio(ctx, H_B, 4);
1047  assert_cpu(0);
1048
1049  wait_for_done(ctx);
1050  set_prio(ctx, H_B, 6);
1051
1052  release(ctx);
1053  sync_with_helper(ctx);
1054  assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
1055  assert_prio_by_scheduler(ctx, M, SCHED_B, PRIO_NONE);
1056  check_generations(ctx, B_5_0, NONE);
1057
1058  request(ctx, B_5_0, REQ_MTX_RELEASE);
1059  assert_prio_by_scheduler(ctx, B_5_0, SCHED_A, PRIO_NONE);
1060  assert_prio_by_scheduler(ctx, B_5_0, SCHED_B, 5);
1061  check_generations(ctx, B_5_0, NONE);
1062}
1063
1064static void test(test_context *ctx)
1065{
1066  test_init(ctx);
1067
1068  if (rtems_get_processor_count() >= PART_COUNT) {
1069    test_task_get_priority_not_defined(ctx);
1070    test_simple_inheritance(ctx);
1071    test_dequeue_order_one_scheduler_instance(ctx);
1072    test_mixed_queue_two_scheduler_instances(ctx);
1073    test_mixed_queue_two_scheduler_instances_sem_only(ctx);
1074    test_two_scheduler_instances_sem_with_inheritance(ctx);
1075    test_two_scheduler_instances_sem_with_inheritance_timeout(ctx);
1076    test_simple_inheritance_two_scheduler_instances(ctx);
1077    test_nested_inheritance_two_scheduler_instances(ctx);
1078    test_dequeue_order_two_scheduler_instances(ctx);
1079    test_omip_pre_emption(ctx);
1080    test_omip_rescue(ctx);
1081    test_omip_timeout(ctx);
1082    test_omip_yield(ctx);
1083  }
1084
1085  test_flush_inheritance(ctx);
1086  test_ceiling_mutex(ctx);
1087}
1088
1089static void Init(rtems_task_argument arg)
1090{
1091  TEST_BEGIN();
1092  test(&test_instance);
1093  TEST_END();
1094  rtems_test_exit(0);
1095}
1096
1097#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
1098#define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
1099
1100#define CONFIGURE_MAXIMUM_PROCESSORS PART_COUNT
1101
1102#define CONFIGURE_SCHEDULER_SIMPLE_SMP
1103
1104#include <rtems/scheduler.h>
1105
1106RTEMS_SCHEDULER_SIMPLE_SMP(a);
1107
1108RTEMS_SCHEDULER_SIMPLE_SMP(b);
1109
1110#define CONFIGURE_SCHEDULER_TABLE_ENTRIES \
1111  RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(a, SCHED_A), \
1112  RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(b, SCHED_B)
1113
1114#define CONFIGURE_SCHEDULER_ASSIGNMENTS \
1115  RTEMS_SCHEDULER_ASSIGN(0, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_MANDATORY), \
1116  RTEMS_SCHEDULER_ASSIGN(1, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL)
1117
1118#define CONFIGURE_MAXIMUM_TASKS TASK_COUNT
1119
1120#define CONFIGURE_MAXIMUM_SEMAPHORES 4
1121
1122#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
1123
1124#define CONFIGURE_INIT_TASK_PRIORITY 3
1125
1126#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
1127
1128#define CONFIGURE_INIT
1129
1130#include <rtems/confdefs.h>
Note: See TracBrowser for help on using the repository browser.