source: rtems/testsuites/smptests/smpmrsp01/init.c @ 03c9f24

5
Last change on this file since 03c9f24 was 03c9f24, checked in by Sebastian Huber <sebastian.huber@…>, on 04/05/19 at 06:03:12

rtems: Add rtems_scheduler_get_processor()

Add rtems_scheduler_get_processor() as a replacement for
rtems_get_current_processor(). The rtems_get_current_processor() is a
bit orphaned. Adopt it by the Scheduler Manager. This is in line with
the glibc sched_getcpu() function.

Deprecate rtems_get_current_processor().

Update #3731.

  • Property mode set to 100644
File size: 47.5 KB
Line 
1/*
2 * Copyright (c) 2014-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 <sys/param.h>
20
21#include <stdio.h>
22#include <inttypes.h>
23
24#include <rtems.h>
25#include <rtems/libcsupport.h>
26#include <rtems/score/schedulersmpimpl.h>
27#include <rtems/score/smpbarrier.h>
28#include <rtems/score/smplock.h>
29
30#include "tmacros.h"
31
32const char rtems_test_name[] = "SMPMRSP 1";
33
34#define CPU_COUNT 32
35
36#define MRSP_COUNT 32
37
38#define SWITCH_EVENT_COUNT 32
39
40typedef struct {
41  uint32_t sleep;
42  uint32_t timeout;
43  uint32_t obtain[MRSP_COUNT];
44  uint32_t cpu[CPU_COUNT];
45} counter;
46
47typedef struct {
48  uint32_t cpu_index;
49  const Thread_Control *executing;
50  const Thread_Control *heir;
51  const Thread_Control *heir_node;
52  Priority_Control heir_priority;
53} switch_event;
54
55typedef struct {
56  rtems_id main_task_id;
57  rtems_id migration_task_id;
58  rtems_id low_task_id[2];
59  rtems_id high_task_id[2];
60  rtems_id timer_id;
61  rtems_id counting_sem_id;
62  rtems_id mrsp_ids[MRSP_COUNT];
63  rtems_id scheduler_ids[CPU_COUNT];
64  rtems_id worker_ids[2 * CPU_COUNT];
65  volatile bool stop_worker[2 * CPU_COUNT];
66  counter counters[2 * CPU_COUNT];
67  uint32_t migration_counters[CPU_COUNT];
68  Thread_Control *worker_task;
69  SMP_barrier_Control barrier;
70  SMP_lock_Control switch_lock;
71  size_t switch_index;
72  switch_event switch_events[32];
73  volatile bool high_run[2];
74  volatile bool low_run[2];
75} test_context;
76
77static test_context test_instance = {
78  .switch_lock = SMP_LOCK_INITIALIZER("test instance switch lock")
79};
80
81static void busy_wait(void)
82{
83  rtems_interval later = rtems_clock_tick_later(2);
84
85  while (rtems_clock_tick_before(later)) {
86    /* Wait */
87  }
88}
89
90static void barrier_init(test_context *ctx)
91{
92  _SMP_barrier_Control_initialize(&ctx->barrier);
93}
94
95static void barrier(test_context *ctx, SMP_barrier_State *bs)
96{
97  _SMP_barrier_Wait(&ctx->barrier, bs, 2);
98}
99
100static void barrier_and_delay(test_context *ctx, SMP_barrier_State *bs)
101{
102  barrier(ctx, bs);
103  busy_wait();
104}
105
106static rtems_task_priority get_prio(rtems_id task_id)
107{
108  rtems_status_code sc;
109  rtems_task_priority prio;
110
111  sc = rtems_task_set_priority(task_id, RTEMS_CURRENT_PRIORITY, &prio);
112  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
113
114  return prio;
115}
116
117static void wait_for_prio(rtems_id task_id, rtems_task_priority prio)
118{
119  while (get_prio(task_id) != prio) {
120    /* Wait */
121  }
122}
123
124static void assert_prio(rtems_id task_id, rtems_task_priority expected_prio)
125{
126  rtems_test_assert(get_prio(task_id) == expected_prio);
127}
128
129static void change_prio(rtems_id task_id, rtems_task_priority prio)
130{
131  rtems_status_code sc;
132
133  sc = rtems_task_set_priority(task_id, prio, &prio);
134  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
135}
136
137static void assert_executing_worker(test_context *ctx)
138{
139  rtems_test_assert(
140    _CPU_Context_Get_is_executing(&ctx->worker_task->Registers)
141  );
142}
143
144static void switch_extension(Thread_Control *executing, Thread_Control *heir)
145{
146  test_context *ctx = &test_instance;
147  SMP_lock_Context lock_context;
148  size_t i;
149
150  _SMP_lock_ISR_disable_and_acquire(&ctx->switch_lock, &lock_context);
151
152  i = ctx->switch_index;
153  if (i < SWITCH_EVENT_COUNT) {
154    switch_event *e = &ctx->switch_events[i];
155    Scheduler_SMP_Node *node = _Scheduler_SMP_Thread_get_node(heir);
156
157    e->cpu_index = rtems_scheduler_get_processor();
158    e->executing = executing;
159    e->heir = heir;
160    e->heir_node = _Scheduler_Node_get_owner(&node->Base);
161    e->heir_priority = node->priority;
162
163    ctx->switch_index = i + 1;
164  }
165
166  _SMP_lock_Release_and_ISR_enable(&ctx->switch_lock, &lock_context);
167}
168
169static void reset_switch_events(test_context *ctx)
170{
171  SMP_lock_Context lock_context;
172
173  _SMP_lock_ISR_disable_and_acquire(&ctx->switch_lock, &lock_context);
174  ctx->switch_index = 0;
175  _SMP_lock_Release_and_ISR_enable(&ctx->switch_lock, &lock_context);
176}
177
178static size_t get_switch_events(test_context *ctx)
179{
180  SMP_lock_Context lock_context;
181  size_t events;
182
183  _SMP_lock_ISR_disable_and_acquire(&ctx->switch_lock, &lock_context);
184  events = ctx->switch_index;
185  _SMP_lock_Release_and_ISR_enable(&ctx->switch_lock, &lock_context);
186
187  return events;
188}
189
190static void print_switch_events(test_context *ctx)
191{
192  size_t n = get_switch_events(ctx);
193  size_t i;
194
195  for (i = 0; i < n; ++i) {
196    switch_event *e = &ctx->switch_events[i];
197    char ex[5];
198    char hr[5];
199    char hn[5];
200
201    rtems_object_get_name(e->executing->Object.id, sizeof(ex), &ex[0]);
202    rtems_object_get_name(e->heir->Object.id, sizeof(hr), &hr[0]);
203    rtems_object_get_name(e->heir_node->Object.id, sizeof(hn), &hn[0]);
204
205    printf(
206      "[%" PRIu32 "] %4s -> %4s (prio %3" PRIu64 ", node %4s)\n",
207      e->cpu_index,
208      &ex[0],
209      &hr[0],
210      e->heir_priority,
211      &hn[0]
212    );
213  }
214}
215
216static void create_timer(test_context *ctx)
217{
218  rtems_status_code sc;
219
220  sc = rtems_timer_create(
221    rtems_build_name('T', 'I', 'M', 'R'),
222    &ctx->timer_id
223  );
224  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
225}
226
227static void delete_timer(test_context *ctx)
228{
229  rtems_status_code sc;
230
231  sc = rtems_timer_delete(ctx->timer_id);
232  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
233}
234
235static void fire_timer(
236  test_context *ctx,
237  rtems_interval interval,
238  rtems_timer_service_routine_entry routine
239)
240{
241  rtems_status_code sc;
242
243  sc = rtems_timer_fire_after(ctx->timer_id, interval, routine, ctx);
244  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
245}
246
247static void create_mrsp_sema(
248  test_context *ctx,
249  rtems_id *id,
250  rtems_task_priority prio
251)
252{
253  uint32_t cpu_count = rtems_get_processor_count();
254  uint32_t index;
255  rtems_status_code sc;
256
257  sc = rtems_semaphore_create(
258    rtems_build_name('M', 'R', 'S', 'P'),
259    1,
260    RTEMS_MULTIPROCESSOR_RESOURCE_SHARING
261      | RTEMS_BINARY_SEMAPHORE,
262    prio,
263    id
264  );
265  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
266
267  for (index = 1; index < cpu_count; index = ((index + 2) & ~UINT32_C(1))) {
268    rtems_task_priority old_prio;
269
270    old_prio = 1;
271    sc = rtems_semaphore_set_priority(
272      *id,
273      ctx->scheduler_ids[index],
274      prio,
275      &old_prio
276    );
277    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
278    rtems_test_assert(old_prio == 0);
279  }
280}
281
282static void run_task(rtems_task_argument arg)
283{
284  volatile bool *run = (volatile bool *) arg;
285
286  *run = true;
287
288  while (true) {
289    /* Do nothing */
290  }
291}
292
293static void obtain_and_release_worker(rtems_task_argument arg)
294{
295  test_context *ctx = &test_instance;
296  rtems_status_code sc;
297  SMP_barrier_State barrier_state = SMP_BARRIER_STATE_INITIALIZER;
298
299  ctx->worker_task = _Thread_Get_executing();
300
301  assert_prio(RTEMS_SELF, 4);
302
303  /* Obtain with timeout (A) */
304  barrier(ctx, &barrier_state);
305
306  sc = rtems_semaphore_obtain(ctx->mrsp_ids[0], RTEMS_WAIT, 4);
307  rtems_test_assert(sc == RTEMS_TIMEOUT);
308
309  assert_prio(RTEMS_SELF, 4);
310
311  /* Obtain with priority change and timeout (B) */
312  barrier(ctx, &barrier_state);
313
314  sc = rtems_semaphore_obtain(ctx->mrsp_ids[0], RTEMS_WAIT, 4);
315  rtems_test_assert(sc == RTEMS_TIMEOUT);
316
317  assert_prio(RTEMS_SELF, 2);
318
319  /* Restore priority (C) */
320  barrier(ctx, &barrier_state);
321
322  /* Obtain without timeout (D) */
323  barrier(ctx, &barrier_state);
324
325  sc = rtems_semaphore_obtain(ctx->mrsp_ids[0], RTEMS_WAIT, RTEMS_NO_TIMEOUT);
326  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
327
328  assert_prio(RTEMS_SELF, 3);
329
330  sc = rtems_semaphore_release(ctx->mrsp_ids[0]);
331  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
332
333  assert_prio(RTEMS_SELF, 4);
334
335  /* Obtain and help with timeout (E) */
336  barrier(ctx, &barrier_state);
337
338  sc = rtems_semaphore_obtain(ctx->mrsp_ids[0], RTEMS_WAIT, 4);
339  rtems_test_assert(sc == RTEMS_TIMEOUT);
340
341  assert_prio(RTEMS_SELF, 4);
342
343  sc = rtems_task_suspend(ctx->high_task_id[0]);
344  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
345
346  /* Worker done (H) */
347  barrier(ctx, &barrier_state);
348
349  while (true) {
350    /* Wait for termination */
351  }
352}
353
354static void test_mrsp_obtain_and_release(test_context *ctx)
355{
356  rtems_status_code sc;
357  rtems_task_priority prio;
358  rtems_id scheduler_id;
359  SMP_barrier_State barrier_state = SMP_BARRIER_STATE_INITIALIZER;
360
361  puts("test MrsP obtain and release");
362
363  change_prio(RTEMS_SELF, 3);
364
365  barrier_init(ctx);
366  reset_switch_events(ctx);
367
368  ctx->high_run[0] = false;
369
370  sc = rtems_task_create(
371    rtems_build_name('H', 'I', 'G', '0'),
372    1,
373    RTEMS_MINIMUM_STACK_SIZE,
374    RTEMS_DEFAULT_MODES,
375    RTEMS_DEFAULT_ATTRIBUTES,
376    &ctx->high_task_id[0]
377  );
378  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
379
380  /* Check executing task parameters */
381
382  sc = rtems_task_get_scheduler(RTEMS_SELF, &scheduler_id);
383  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
384
385  rtems_test_assert(ctx->scheduler_ids[0] == scheduler_id);
386
387  /* Create a MrsP semaphore object and lock it */
388
389  create_mrsp_sema(ctx, &ctx->mrsp_ids[0], 2);
390
391  assert_prio(RTEMS_SELF, 3);
392
393  sc = rtems_semaphore_obtain(ctx->mrsp_ids[0], RTEMS_WAIT, RTEMS_NO_TIMEOUT);
394  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
395
396  assert_prio(RTEMS_SELF, 2);
397
398  /*
399   * The ceiling priority values per scheduler are equal to the value specified
400   * for object creation.
401   */
402
403  prio = RTEMS_CURRENT_PRIORITY;
404  sc = rtems_semaphore_set_priority(
405    ctx->mrsp_ids[0],
406    ctx->scheduler_ids[0],
407    prio,
408    &prio
409  );
410  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
411  rtems_test_assert(prio == 2);
412
413  /* Check the old value and set a new ceiling priority for scheduler B */
414
415  prio = 3;
416  sc = rtems_semaphore_set_priority(
417    ctx->mrsp_ids[0],
418    ctx->scheduler_ids[1],
419    prio,
420    &prio
421  );
422  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
423  rtems_test_assert(prio == 2);
424
425  /* Check the ceiling priority values */
426
427  prio = RTEMS_CURRENT_PRIORITY;
428  sc = rtems_semaphore_set_priority(
429    ctx->mrsp_ids[0],
430    ctx->scheduler_ids[0],
431    prio,
432    &prio
433  );
434  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
435  rtems_test_assert(prio == 2);
436
437  prio = RTEMS_CURRENT_PRIORITY;
438  sc = rtems_semaphore_set_priority(
439    ctx->mrsp_ids[0],
440    ctx->scheduler_ids[1],
441    prio,
442    &prio
443  );
444  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
445  rtems_test_assert(prio == 3);
446
447  /* Check that a thread waiting to get ownership remains executing */
448
449  sc = rtems_task_create(
450    rtems_build_name('W', 'O', 'R', 'K'),
451    255,
452    RTEMS_MINIMUM_STACK_SIZE,
453    RTEMS_DEFAULT_MODES,
454    RTEMS_DEFAULT_ATTRIBUTES,
455    &ctx->worker_ids[0]
456  );
457  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
458
459  sc = rtems_task_set_scheduler(ctx->worker_ids[0], ctx->scheduler_ids[1], 4);
460  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
461
462  sc = rtems_task_start(ctx->worker_ids[0], obtain_and_release_worker, 0);
463  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
464
465  /* Obtain with timeout (A) */
466  barrier_and_delay(ctx, &barrier_state);
467
468  assert_prio(ctx->worker_ids[0], 3);
469  assert_executing_worker(ctx);
470
471  /* Obtain with priority change and timeout (B) */
472  barrier_and_delay(ctx, &barrier_state);
473
474  assert_prio(ctx->worker_ids[0], 3);
475  change_prio(ctx->worker_ids[0], 2);
476  assert_executing_worker(ctx);
477
478  /* Restore priority (C) */
479  barrier(ctx, &barrier_state);
480
481  assert_prio(ctx->worker_ids[0], 2);
482  change_prio(ctx->worker_ids[0], 4);
483
484  /* Obtain without timeout (D) */
485  barrier_and_delay(ctx, &barrier_state);
486
487  assert_prio(ctx->worker_ids[0], 3);
488  assert_executing_worker(ctx);
489
490  sc = rtems_semaphore_release(ctx->mrsp_ids[0]);
491  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
492
493  /* Check that a timeout works in case the waiting thread actually helps */
494
495  sc = rtems_semaphore_obtain(ctx->mrsp_ids[0], RTEMS_WAIT, RTEMS_NO_TIMEOUT);
496  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
497
498  /* Obtain and help with timeout (E) */
499  barrier_and_delay(ctx, &barrier_state);
500
501  sc = rtems_task_start(
502    ctx->high_task_id[0],
503    run_task,
504    (rtems_task_argument) &ctx->high_run[0]
505  );
506  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
507
508  rtems_test_assert(rtems_scheduler_get_processor() == 1);
509
510  while (rtems_scheduler_get_processor() != 0) {
511    /* Wait */
512  }
513
514  rtems_test_assert(ctx->high_run[0]);
515
516  sc = rtems_semaphore_release(ctx->mrsp_ids[0]);
517  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
518
519  print_switch_events(ctx);
520
521  /* Worker done (H) */
522  barrier(ctx, &barrier_state);
523
524  sc = rtems_task_delete(ctx->worker_ids[0]);
525  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
526
527  sc = rtems_task_delete(ctx->high_task_id[0]);
528  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
529
530  sc = rtems_semaphore_delete(ctx->mrsp_ids[0]);
531  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
532}
533
534static void obtain_after_migration_worker(rtems_task_argument arg)
535{
536  test_context *ctx = &test_instance;
537  rtems_status_code sc;
538  SMP_barrier_State barrier_state = SMP_BARRIER_STATE_INITIALIZER;
539
540  assert_prio(RTEMS_SELF, 3);
541
542  sc = rtems_semaphore_obtain(ctx->mrsp_ids[0], RTEMS_WAIT, RTEMS_NO_TIMEOUT);
543  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
544
545  sc = rtems_semaphore_release(ctx->mrsp_ids[0]);
546  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
547
548  /* Worker done (K) */
549  barrier(ctx, &barrier_state);
550
551  while (true) {
552    /* Wait for termination */
553  }
554}
555
556static void obtain_after_migration_high(rtems_task_argument arg)
557{
558  test_context *ctx = &test_instance;
559  rtems_status_code sc;
560  SMP_barrier_State barrier_state = SMP_BARRIER_STATE_INITIALIZER;
561
562  assert_prio(RTEMS_SELF, 2);
563
564  sc = rtems_semaphore_obtain(ctx->mrsp_ids[1], RTEMS_WAIT, RTEMS_NO_TIMEOUT);
565  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
566
567  /* Obtain done (I) */
568  barrier(ctx, &barrier_state);
569
570  /* Ready to release (J) */
571  barrier(ctx, &barrier_state);
572
573  sc = rtems_semaphore_release(ctx->mrsp_ids[1]);
574  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
575
576  rtems_task_suspend(RTEMS_SELF);
577  rtems_test_assert(0);
578}
579
580static void test_mrsp_obtain_after_migration(test_context *ctx)
581{
582  rtems_status_code sc;
583  rtems_task_priority prio;
584  rtems_id scheduler_id;
585  SMP_barrier_State barrier_state;
586
587  puts("test MrsP obtain after migration");
588
589  change_prio(RTEMS_SELF, 3);
590
591  barrier_init(ctx);
592  reset_switch_events(ctx);
593
594  /* Create tasks */
595
596  sc = rtems_task_create(
597    rtems_build_name('H', 'I', 'G', '0'),
598    2,
599    RTEMS_MINIMUM_STACK_SIZE,
600    RTEMS_DEFAULT_MODES,
601    RTEMS_DEFAULT_ATTRIBUTES,
602    &ctx->high_task_id[0]
603  );
604  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
605
606  sc = rtems_task_create(
607    rtems_build_name('W', 'O', 'R', 'K'),
608    255,
609    RTEMS_MINIMUM_STACK_SIZE,
610    RTEMS_DEFAULT_MODES,
611    RTEMS_DEFAULT_ATTRIBUTES,
612    &ctx->worker_ids[0]
613  );
614  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
615
616  sc = rtems_task_set_scheduler(ctx->worker_ids[0], ctx->scheduler_ids[1], 3);
617  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
618
619  /* Create a MrsP semaphore objects */
620
621  create_mrsp_sema(ctx, &ctx->mrsp_ids[0], 3);
622  create_mrsp_sema(ctx, &ctx->mrsp_ids[1], 2);
623  create_mrsp_sema(ctx, &ctx->mrsp_ids[2], 1);
624
625  prio = 4;
626  sc = rtems_semaphore_set_priority(
627    ctx->mrsp_ids[2],
628    ctx->scheduler_ids[1],
629    prio,
630    &prio
631  );
632  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
633  rtems_test_assert(prio == 1);
634
635  /* Check executing task parameters */
636
637  sc = rtems_task_get_scheduler(RTEMS_SELF, &scheduler_id);
638  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
639
640  rtems_test_assert(ctx->scheduler_ids[0] == scheduler_id);
641
642  assert_prio(RTEMS_SELF, 3);
643
644  sc = rtems_semaphore_obtain(ctx->mrsp_ids[0], RTEMS_WAIT, RTEMS_NO_TIMEOUT);
645  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
646
647  assert_prio(RTEMS_SELF, 3);
648
649  /* Start other tasks */
650
651  sc = rtems_task_start(ctx->worker_ids[0], obtain_after_migration_worker, 0);
652  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
653
654  sc = rtems_task_start(ctx->high_task_id[0], obtain_after_migration_high, 0);
655  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
656
657  rtems_test_assert(rtems_scheduler_get_processor() == 1);
658
659  /* Obtain done (I) */
660  _SMP_barrier_State_initialize(&barrier_state);
661  barrier(ctx, &barrier_state);
662
663  sc = rtems_task_suspend(ctx->high_task_id[0]);
664  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
665
666  rtems_test_assert(rtems_scheduler_get_processor() == 1);
667
668  /*
669   * Obtain second MrsP semaphore and ensure that we change the priority of our
670   * own scheduler node and not the one we are currently using.
671   */
672
673  sc = rtems_semaphore_obtain(ctx->mrsp_ids[2], RTEMS_WAIT, RTEMS_NO_TIMEOUT);
674  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
675
676  assert_prio(RTEMS_SELF, 1);
677
678  rtems_test_assert(rtems_scheduler_get_processor() == 1);
679
680  sc = rtems_semaphore_release(ctx->mrsp_ids[2]);
681  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
682
683  sc = rtems_task_resume(ctx->high_task_id[0]);
684  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
685
686  /* Ready to release (J) */
687  barrier(ctx, &barrier_state);
688
689  rtems_test_assert(rtems_scheduler_get_processor() == 1);
690
691  /* Prepare barrier for worker */
692  barrier_init(ctx);
693  _SMP_barrier_State_initialize(&barrier_state);
694
695  sc = rtems_semaphore_release(ctx->mrsp_ids[0]);
696  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
697
698  rtems_test_assert(rtems_scheduler_get_processor() == 0);
699
700  print_switch_events(ctx);
701
702  /* Worker done (K) */
703  barrier(ctx, &barrier_state);
704
705  sc = rtems_task_delete(ctx->worker_ids[0]);
706  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
707
708  sc = rtems_task_delete(ctx->high_task_id[0]);
709  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
710
711  sc = rtems_semaphore_delete(ctx->mrsp_ids[0]);
712  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
713
714  sc = rtems_semaphore_delete(ctx->mrsp_ids[1]);
715  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
716
717  sc = rtems_semaphore_delete(ctx->mrsp_ids[2]);
718  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
719}
720
721static void test_mrsp_flush_error(test_context *ctx)
722{
723  rtems_status_code sc;
724  rtems_id id;
725
726  puts("test MrsP flush error");
727
728  create_mrsp_sema(ctx, &id, 1);
729
730  sc = rtems_semaphore_flush(id);
731  rtems_test_assert(sc == RTEMS_NOT_DEFINED);
732
733  sc = rtems_semaphore_delete(id);
734  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
735}
736
737static void test_mrsp_initially_locked_error(void)
738{
739  rtems_status_code sc;
740  rtems_id id;
741
742  puts("test MrsP initially locked error");
743
744  sc = rtems_semaphore_create(
745    rtems_build_name('M', 'R', 'S', 'P'),
746    0,
747    RTEMS_MULTIPROCESSOR_RESOURCE_SHARING
748      | RTEMS_BINARY_SEMAPHORE,
749    1,
750    &id
751  );
752  rtems_test_assert(sc == RTEMS_INVALID_NUMBER);
753}
754
755static void test_mrsp_nested_obtain_error(test_context *ctx)
756{
757  rtems_status_code sc;
758  rtems_id id;
759
760  puts("test MrsP nested obtain error");
761
762  create_mrsp_sema(ctx, &id, 1);
763
764  sc = rtems_semaphore_obtain(id, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
765  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
766
767  sc = rtems_semaphore_obtain(id, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
768  rtems_test_assert(sc == RTEMS_UNSATISFIED);
769
770  sc = rtems_semaphore_release(id);
771  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
772
773  sc = rtems_semaphore_delete(id);
774  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
775}
776
777static void deadlock_timer(rtems_id timer_id, void *arg)
778{
779  test_context *ctx = arg;
780
781  change_prio(ctx->main_task_id, 1);
782}
783
784static void deadlock_worker(rtems_task_argument arg)
785{
786  test_context *ctx = &test_instance;
787  rtems_status_code sc;
788
789  sc = rtems_semaphore_obtain(ctx->mrsp_ids[1], RTEMS_WAIT, RTEMS_NO_TIMEOUT);
790  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
791
792  fire_timer(ctx, 2, deadlock_timer);
793
794  sc = rtems_semaphore_obtain(ctx->mrsp_ids[0], RTEMS_WAIT, RTEMS_NO_TIMEOUT);
795  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
796
797  sc = rtems_semaphore_release(ctx->mrsp_ids[0]);
798  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
799
800  sc = rtems_semaphore_release(ctx->mrsp_ids[1]);
801  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
802
803  sc = rtems_event_transient_send(ctx->main_task_id);
804  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
805
806  rtems_task_suspend(RTEMS_SELF);
807  rtems_test_assert(0);
808}
809
810static void test_mrsp_deadlock_error(test_context *ctx)
811{
812  rtems_status_code sc;
813  rtems_task_priority prio = 2;
814
815  puts("test MrsP deadlock error");
816
817  change_prio(RTEMS_SELF, prio);
818
819  create_timer(ctx);
820  create_mrsp_sema(ctx, &ctx->mrsp_ids[0], prio);
821  create_mrsp_sema(ctx, &ctx->mrsp_ids[1], prio);
822
823  sc = rtems_task_create(
824    rtems_build_name('W', 'O', 'R', 'K'),
825    prio,
826    RTEMS_MINIMUM_STACK_SIZE,
827    RTEMS_DEFAULT_MODES,
828    RTEMS_DEFAULT_ATTRIBUTES,
829    &ctx->worker_ids[0]
830  );
831  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
832
833  sc = rtems_task_start(ctx->worker_ids[0], deadlock_worker, 0);
834  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
835
836  sc = rtems_semaphore_obtain(ctx->mrsp_ids[0], RTEMS_WAIT, RTEMS_NO_TIMEOUT);
837  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
838
839  sc = rtems_task_wake_after(RTEMS_YIELD_PROCESSOR);
840  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
841
842  prio = 1;
843  sc = rtems_semaphore_set_priority(
844    ctx->mrsp_ids[1],
845    ctx->scheduler_ids[0],
846    prio,
847    &prio
848  );
849  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
850  rtems_test_assert(prio == 2);
851
852  sc = rtems_semaphore_obtain(ctx->mrsp_ids[1], RTEMS_WAIT, RTEMS_NO_TIMEOUT);
853  rtems_test_assert(sc == RTEMS_INCORRECT_STATE);
854
855  sc = rtems_semaphore_set_priority(
856    ctx->mrsp_ids[1],
857    ctx->scheduler_ids[0],
858    prio,
859    &prio
860  );
861  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
862
863  sc = rtems_semaphore_release(ctx->mrsp_ids[0]);
864  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
865
866  sc = rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT);
867  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
868
869  sc = rtems_task_delete(ctx->worker_ids[0]);
870  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
871
872  sc = rtems_semaphore_delete(ctx->mrsp_ids[0]);
873  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
874
875  sc = rtems_semaphore_delete(ctx->mrsp_ids[1]);
876  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
877
878  delete_timer(ctx);
879}
880
881static void test_mrsp_multiple_obtain(test_context *ctx)
882{
883  rtems_status_code sc;
884  rtems_id sem_a_id;
885  rtems_id sem_b_id;
886  rtems_id sem_c_id;
887
888  puts("test MrsP multiple obtain");
889
890  change_prio(RTEMS_SELF, 4);
891
892  create_mrsp_sema(ctx, &sem_a_id, 3);
893  create_mrsp_sema(ctx, &sem_b_id, 2);
894  create_mrsp_sema(ctx, &sem_c_id, 1);
895
896  assert_prio(RTEMS_SELF, 4);
897
898  sc = rtems_semaphore_obtain(sem_a_id, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
899  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
900
901  assert_prio(RTEMS_SELF, 3);
902
903  sc = rtems_semaphore_obtain(sem_b_id, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
904  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
905
906  assert_prio(RTEMS_SELF, 2);
907
908  sc = rtems_semaphore_obtain(sem_c_id, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
909  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
910
911  assert_prio(RTEMS_SELF, 1);
912
913  sc = rtems_semaphore_release(sem_c_id);
914  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
915
916  assert_prio(RTEMS_SELF, 2);
917
918  sc = rtems_semaphore_release(sem_b_id);
919  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
920
921  assert_prio(RTEMS_SELF, 3);
922
923  sc = rtems_semaphore_release(sem_a_id);
924  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
925
926  assert_prio(RTEMS_SELF, 4);
927
928  sc = rtems_semaphore_obtain(sem_a_id, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
929  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
930
931  assert_prio(RTEMS_SELF, 3);
932
933  sc = rtems_semaphore_obtain(sem_b_id, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
934  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
935
936  assert_prio(RTEMS_SELF, 2);
937
938  sc = rtems_semaphore_obtain(sem_c_id, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
939  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
940
941  assert_prio(RTEMS_SELF, 1);
942  change_prio(RTEMS_SELF, 3);
943  assert_prio(RTEMS_SELF, 1);
944
945  sc = rtems_semaphore_release(sem_c_id);
946  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
947
948  assert_prio(RTEMS_SELF, 2);
949
950  sc = rtems_semaphore_release(sem_b_id);
951  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
952
953  assert_prio(RTEMS_SELF, 3);
954
955  sc = rtems_semaphore_release(sem_a_id);
956  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
957
958  assert_prio(RTEMS_SELF, 3);
959
960  sc = rtems_semaphore_delete(sem_a_id);
961  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
962
963  sc = rtems_semaphore_delete(sem_b_id);
964  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
965
966  sc = rtems_semaphore_delete(sem_c_id);
967  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
968}
969
970static void ready_unlock_worker(rtems_task_argument arg)
971{
972  test_context *ctx = &test_instance;
973  rtems_status_code sc;
974  SMP_barrier_State barrier_state = SMP_BARRIER_STATE_INITIALIZER;
975
976  assert_prio(RTEMS_SELF, 4);
977
978  /* Obtain (F) */
979  barrier(ctx, &barrier_state);
980
981  sc = rtems_semaphore_obtain(ctx->mrsp_ids[0], RTEMS_WAIT, RTEMS_NO_TIMEOUT);
982  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
983
984  sc = rtems_semaphore_release(ctx->mrsp_ids[0]);
985  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
986
987  assert_prio(RTEMS_SELF, 4);
988
989  /* Done (G) */
990  barrier(ctx, &barrier_state);
991
992  while (true) {
993    /* Do nothing */
994  }
995}
996
997static void unblock_ready_timer(rtems_id timer_id, void *arg)
998{
999  test_context *ctx = arg;
1000  rtems_status_code sc;
1001
1002  sc = rtems_task_start(
1003    ctx->high_task_id[0],
1004    run_task,
1005    (rtems_task_argument) &ctx->high_run[0]
1006  );
1007  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1008
1009  sc = rtems_task_suspend(ctx->high_task_id[0]);
1010  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1011
1012  sc = rtems_task_resume(ctx->high_task_id[0]);
1013  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1014
1015  /*
1016   * At this point the scheduler node of the main thread is in the
1017   * SCHEDULER_SMP_NODE_READY state and a _Scheduler_SMP_Unblock() operation is
1018   * performed.
1019   */
1020  sc = rtems_event_transient_send(ctx->main_task_id);
1021  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1022
1023  sc = rtems_task_suspend(ctx->high_task_id[0]);
1024  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1025}
1026
1027static void unblock_ready_owner(test_context *ctx)
1028{
1029  rtems_status_code sc;
1030
1031  sc = rtems_semaphore_obtain(ctx->mrsp_ids[0], RTEMS_WAIT, RTEMS_NO_TIMEOUT);
1032  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1033
1034  assert_prio(RTEMS_SELF, 3);
1035
1036  fire_timer(ctx, 2, unblock_ready_timer);
1037
1038  sc = rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT);
1039  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1040
1041  rtems_test_assert(!ctx->high_run[0]);
1042}
1043
1044static void unblock_owner_before_rival_timer(rtems_id timer_id, void *arg)
1045{
1046  test_context *ctx = arg;
1047  rtems_status_code sc;
1048
1049  sc = rtems_task_suspend(ctx->high_task_id[0]);
1050  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1051
1052  sc = rtems_task_suspend(ctx->high_task_id[1]);
1053  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1054}
1055
1056static void unblock_owner_after_rival_timer(rtems_id timer_id, void *arg)
1057{
1058  test_context *ctx = arg;
1059  rtems_status_code sc;
1060
1061  sc = rtems_task_suspend(ctx->high_task_id[1]);
1062  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1063
1064  sc = rtems_task_suspend(ctx->high_task_id[0]);
1065  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1066}
1067
1068static void various_block_unblock(test_context *ctx)
1069{
1070  rtems_status_code sc;
1071  SMP_barrier_State barrier_state = SMP_BARRIER_STATE_INITIALIZER;
1072
1073  /* Worker obtain (F) */
1074  barrier_and_delay(ctx, &barrier_state);
1075
1076  sc = rtems_task_suspend(ctx->worker_ids[0]);
1077  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1078
1079  busy_wait();
1080
1081  sc = rtems_task_start(
1082    ctx->high_task_id[1],
1083    run_task,
1084    (rtems_task_argument) &ctx->high_run[1]
1085  );
1086  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1087
1088  while (!ctx->high_run[1]) {
1089    /* Do noting */
1090  }
1091
1092  sc = rtems_task_resume(ctx->worker_ids[0]);
1093  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1094
1095  /* Try to schedule a blocked active rival */
1096
1097  sc = rtems_task_suspend(ctx->worker_ids[0]);
1098  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1099
1100  sc = rtems_task_suspend(ctx->high_task_id[1]);
1101  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1102
1103  sc = rtems_task_resume(ctx->high_task_id[1]);
1104  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1105
1106  sc = rtems_task_resume(ctx->worker_ids[0]);
1107  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1108
1109  rtems_test_assert(rtems_scheduler_get_processor() == 0);
1110
1111  /* Use node of the active rival */
1112
1113  sc = rtems_task_suspend(ctx->high_task_id[1]);
1114  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1115
1116  sc = rtems_task_resume(ctx->high_task_id[0]);
1117  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1118
1119  rtems_test_assert(rtems_scheduler_get_processor() == 1);
1120
1121  sc = rtems_task_suspend(ctx->worker_ids[0]);
1122  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1123
1124  sc = rtems_task_resume(ctx->worker_ids[0]);
1125  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1126
1127  /*
1128   * Try to schedule an active rival with an already scheduled active owner
1129   * user.
1130   */
1131
1132  fire_timer(ctx, 2, unblock_owner_before_rival_timer);
1133
1134  /* This will take the processor away from us, the timer will help later */
1135  sc = rtems_task_resume(ctx->high_task_id[1]);
1136  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1137
1138  /*
1139   * Try to schedule an active owner with an already scheduled active rival
1140   * user.
1141   */
1142
1143  sc = rtems_task_resume(ctx->high_task_id[0]);
1144  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1145
1146  fire_timer(ctx, 2, unblock_owner_after_rival_timer);
1147
1148  /* This will take the processor away from us, the timer will help later */
1149  sc = rtems_task_resume(ctx->high_task_id[1]);
1150  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1151
1152  sc = rtems_semaphore_release(ctx->mrsp_ids[0]);
1153  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1154
1155  rtems_test_assert(rtems_scheduler_get_processor() == 0);
1156
1157  assert_prio(RTEMS_SELF, 4);
1158
1159  /* Worker done (G) */
1160  barrier(ctx, &barrier_state);
1161}
1162
1163static void start_low_task(test_context *ctx, size_t i)
1164{
1165  rtems_status_code sc;
1166
1167  sc = rtems_task_create(
1168    rtems_build_name('L', 'O', 'W', '0' + i),
1169    255,
1170    RTEMS_MINIMUM_STACK_SIZE,
1171    RTEMS_DEFAULT_MODES,
1172    RTEMS_DEFAULT_ATTRIBUTES,
1173    &ctx->low_task_id[i]
1174  );
1175  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1176
1177  sc = rtems_task_set_scheduler(ctx->low_task_id[i], ctx->scheduler_ids[i], 5);
1178  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1179
1180  sc = rtems_task_start(
1181    ctx->low_task_id[i],
1182    run_task,
1183    (rtems_task_argument) &ctx->low_run[i]
1184  );
1185  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1186}
1187
1188static void test_mrsp_various_block_and_unblock(test_context *ctx)
1189{
1190  rtems_status_code sc;
1191
1192  puts("test MrsP various block and unblock");
1193
1194  change_prio(RTEMS_SELF, 4);
1195
1196  barrier_init(ctx);
1197  reset_switch_events(ctx);
1198
1199  ctx->low_run[0] = false;
1200  ctx->low_run[1] = false;
1201  ctx->high_run[0] = false;
1202  ctx->high_run[1] = false;
1203
1204  create_mrsp_sema(ctx, &ctx->mrsp_ids[0], 3);
1205  assert_prio(RTEMS_SELF, 4);
1206
1207  sc = rtems_task_create(
1208    rtems_build_name('H', 'I', 'G', '0'),
1209    2,
1210    RTEMS_MINIMUM_STACK_SIZE,
1211    RTEMS_DEFAULT_MODES,
1212    RTEMS_DEFAULT_ATTRIBUTES,
1213    &ctx->high_task_id[0]
1214  );
1215  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1216
1217  sc = rtems_task_create(
1218    rtems_build_name('H', 'I', 'G', '1'),
1219    255,
1220    RTEMS_MINIMUM_STACK_SIZE,
1221    RTEMS_DEFAULT_MODES,
1222    RTEMS_DEFAULT_ATTRIBUTES,
1223    &ctx->high_task_id[1]
1224  );
1225  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1226
1227  sc = rtems_task_set_scheduler(ctx->high_task_id[1], ctx->scheduler_ids[1], 2);
1228  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1229
1230  sc = rtems_task_create(
1231    rtems_build_name('W', 'O', 'R', 'K'),
1232    255,
1233    RTEMS_MINIMUM_STACK_SIZE,
1234    RTEMS_DEFAULT_MODES,
1235    RTEMS_DEFAULT_ATTRIBUTES,
1236    &ctx->worker_ids[0]
1237  );
1238  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1239
1240  sc = rtems_task_set_scheduler(ctx->worker_ids[0], ctx->scheduler_ids[1], 4);
1241  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1242
1243  sc = rtems_task_start(ctx->worker_ids[0], ready_unlock_worker, 0);
1244  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1245
1246  create_timer(ctx);
1247
1248  /* In case these tasks run, then we have a MrsP protocol violation */
1249  start_low_task(ctx, 0);
1250  start_low_task(ctx, 1);
1251
1252  unblock_ready_owner(ctx);
1253  various_block_unblock(ctx);
1254
1255  rtems_test_assert(!ctx->low_run[0]);
1256  rtems_test_assert(!ctx->low_run[1]);
1257
1258  print_switch_events(ctx);
1259  delete_timer(ctx);
1260
1261  sc = rtems_task_delete(ctx->high_task_id[0]);
1262  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1263
1264  sc = rtems_task_delete(ctx->high_task_id[1]);
1265  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1266
1267  sc = rtems_task_delete(ctx->worker_ids[0]);
1268  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1269
1270  sc = rtems_task_delete(ctx->low_task_id[0]);
1271  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1272
1273  sc = rtems_task_delete(ctx->low_task_id[1]);
1274  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1275
1276  sc = rtems_semaphore_delete(ctx->mrsp_ids[0]);
1277  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1278}
1279
1280static void test_mrsp_obtain_and_sleep_and_release(test_context *ctx)
1281{
1282  rtems_status_code sc;
1283  rtems_id sem_id;
1284  rtems_id run_task_id;
1285  volatile bool run = false;
1286
1287  puts("test MrsP obtain and sleep and release");
1288
1289  change_prio(RTEMS_SELF, 1);
1290
1291  reset_switch_events(ctx);
1292
1293  sc = rtems_task_create(
1294    rtems_build_name(' ', 'R', 'U', 'N'),
1295    2,
1296    RTEMS_MINIMUM_STACK_SIZE,
1297    RTEMS_DEFAULT_MODES,
1298    RTEMS_DEFAULT_ATTRIBUTES,
1299    &run_task_id
1300  );
1301  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1302
1303  sc = rtems_task_start(run_task_id, run_task, (rtems_task_argument) &run);
1304  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1305
1306  create_mrsp_sema(ctx, &sem_id, 1);
1307
1308  rtems_test_assert(!run);
1309
1310  sc = rtems_task_wake_after(2);
1311  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1312
1313  rtems_test_assert(run);
1314  run = false;
1315
1316  sc = rtems_semaphore_obtain(sem_id, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
1317  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1318
1319  rtems_test_assert(!run);
1320
1321  sc = rtems_task_wake_after(2);
1322  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1323
1324  rtems_test_assert(!run);
1325
1326  sc = rtems_semaphore_release(sem_id);
1327  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1328
1329  print_switch_events(ctx);
1330
1331  sc = rtems_semaphore_delete(sem_id);
1332  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1333
1334  sc = rtems_task_delete(run_task_id);
1335  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1336}
1337
1338static void help_task(rtems_task_argument arg)
1339{
1340  test_context *ctx = &test_instance;
1341  rtems_status_code sc;
1342
1343  sc = rtems_semaphore_obtain(ctx->mrsp_ids[0], RTEMS_WAIT, RTEMS_NO_TIMEOUT);
1344  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1345
1346  sc = rtems_semaphore_release(ctx->mrsp_ids[0]);
1347  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1348
1349  while (true) {
1350    /* Do nothing */
1351  }
1352}
1353
1354static void test_mrsp_obtain_and_release_with_help(test_context *ctx)
1355{
1356  rtems_status_code sc;
1357  rtems_id help_task_id;
1358  rtems_id run_task_id;
1359  volatile bool run = false;
1360
1361  puts("test MrsP obtain and release with help");
1362
1363  change_prio(RTEMS_SELF, 3);
1364
1365  reset_switch_events(ctx);
1366
1367  create_mrsp_sema(ctx, &ctx->mrsp_ids[0], 2);
1368
1369  sc = rtems_semaphore_obtain(ctx->mrsp_ids[0], RTEMS_WAIT, RTEMS_NO_TIMEOUT);
1370  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1371
1372  assert_prio(RTEMS_SELF, 2);
1373
1374  sc = rtems_task_create(
1375    rtems_build_name('H', 'E', 'L', 'P'),
1376    255,
1377    RTEMS_MINIMUM_STACK_SIZE,
1378    RTEMS_DEFAULT_MODES,
1379    RTEMS_DEFAULT_ATTRIBUTES,
1380    &help_task_id
1381  );
1382  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1383
1384  sc = rtems_task_set_scheduler(
1385    help_task_id,
1386    ctx->scheduler_ids[1],
1387    3
1388  );
1389  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1390
1391  sc = rtems_task_start(help_task_id, help_task, 0);
1392  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1393
1394  sc = rtems_task_create(
1395    rtems_build_name(' ', 'R', 'U', 'N'),
1396    4,
1397    RTEMS_MINIMUM_STACK_SIZE,
1398    RTEMS_DEFAULT_MODES,
1399    RTEMS_DEFAULT_ATTRIBUTES,
1400    &run_task_id
1401  );
1402  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1403
1404  sc = rtems_task_start(run_task_id, run_task, (rtems_task_argument) &run);
1405  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1406
1407  wait_for_prio(help_task_id, 2);
1408
1409  sc = rtems_task_wake_after(2);
1410  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1411
1412  rtems_test_assert(rtems_scheduler_get_processor() == 0);
1413  rtems_test_assert(!run);
1414
1415  change_prio(run_task_id, 1);
1416
1417  rtems_test_assert(rtems_scheduler_get_processor() == 1);
1418
1419  while (!run) {
1420    /* Wait */
1421  }
1422
1423  sc = rtems_task_wake_after(2);
1424  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1425
1426  rtems_test_assert(rtems_scheduler_get_processor() == 1);
1427
1428  change_prio(run_task_id, 4);
1429
1430  rtems_test_assert(rtems_scheduler_get_processor() == 1);
1431
1432  /*
1433   * With this operation the scheduler instance 0 has now only the main and the
1434   * idle threads in the ready set.
1435   */
1436  sc = rtems_task_suspend(run_task_id);
1437  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1438
1439  rtems_test_assert(rtems_scheduler_get_processor() == 1);
1440
1441  change_prio(RTEMS_SELF, 1);
1442  change_prio(RTEMS_SELF, 3);
1443
1444  sc = rtems_semaphore_release(ctx->mrsp_ids[0]);
1445  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1446
1447  rtems_test_assert(rtems_scheduler_get_processor() == 0);
1448
1449  assert_prio(RTEMS_SELF, 3);
1450
1451  wait_for_prio(help_task_id, 3);
1452
1453  print_switch_events(ctx);
1454
1455  sc = rtems_semaphore_delete(ctx->mrsp_ids[0]);
1456  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1457
1458  sc = rtems_task_delete(help_task_id);
1459  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1460
1461  sc = rtems_task_delete(run_task_id);
1462  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1463}
1464
1465static uint32_t simple_random(uint32_t v)
1466{
1467  v *= 1664525;
1468  v += 1013904223;
1469
1470  return v;
1471}
1472
1473static rtems_interval timeout(uint32_t v)
1474{
1475  return (v >> 23) % 4;
1476}
1477
1478static void load_worker(rtems_task_argument index)
1479{
1480  test_context *ctx = &test_instance;
1481  rtems_status_code sc;
1482  uint32_t v = index;
1483
1484  while (!ctx->stop_worker[index]) {
1485    uint32_t i = (v >> 13) % MRSP_COUNT;
1486
1487    assert_prio(RTEMS_SELF, 3 + CPU_COUNT + index);
1488
1489    if ((v >> 7) % 1024 == 0) {
1490      /* Give some time to the lower priority tasks */
1491
1492      ++ctx->counters[index].sleep;
1493
1494      sc = rtems_task_wake_after(1);
1495      rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1496
1497      ++ctx->counters[index].cpu[rtems_scheduler_get_processor()];
1498    } else {
1499      uint32_t n = (v >> 17) % (i + 1);
1500      uint32_t s;
1501      uint32_t t;
1502
1503      /* Nested obtain */
1504      for (s = 0; s <= n; ++s) {
1505        uint32_t k = i - s;
1506
1507        sc = rtems_semaphore_obtain(ctx->mrsp_ids[k], RTEMS_WAIT, timeout(v));
1508        if (sc == RTEMS_SUCCESSFUL) {
1509          ++ctx->counters[index].obtain[n];
1510
1511          assert_prio(RTEMS_SELF, 3 + k);
1512        } else {
1513          rtems_test_assert(sc == RTEMS_TIMEOUT);
1514
1515          ++ctx->counters[index].timeout;
1516
1517          break;
1518        }
1519
1520        ++ctx->counters[index].cpu[rtems_scheduler_get_processor()];
1521
1522        v = simple_random(v);
1523      }
1524
1525      /* Release in reverse obtain order */
1526      for (t = 0; t < s; ++t) {
1527        uint32_t k = i + t - s + 1;
1528
1529        sc = rtems_semaphore_release(ctx->mrsp_ids[k]);
1530        rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1531
1532        ++ctx->counters[index].cpu[rtems_scheduler_get_processor()];
1533      }
1534    }
1535
1536    v = simple_random(v);
1537  }
1538
1539  sc = rtems_semaphore_release(ctx->counting_sem_id);
1540  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1541
1542  rtems_task_suspend(RTEMS_SELF);
1543  rtems_test_assert(0);
1544}
1545
1546static void migration_task(rtems_task_argument arg)
1547{
1548  test_context *ctx = &test_instance;
1549  rtems_status_code sc;
1550  uint32_t cpu_count = rtems_get_processor_count();
1551  uint32_t v = 0xdeadbeef;
1552
1553  while (true) {
1554    uint32_t cpu_index = (v >> 5) % cpu_count;
1555
1556    sc = rtems_task_set_scheduler(RTEMS_SELF, ctx->scheduler_ids[cpu_index], 2);
1557    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1558
1559    ++ctx->migration_counters[rtems_scheduler_get_processor()];
1560
1561    v = simple_random(v);
1562  }
1563}
1564
1565static void test_mrsp_load(test_context *ctx)
1566{
1567  rtems_status_code sc;
1568  uint32_t cpu_count = rtems_get_processor_count();
1569  uint32_t index;
1570
1571  puts("test MrsP load");
1572
1573  change_prio(RTEMS_SELF, 2);
1574
1575  sc = rtems_task_create(
1576    rtems_build_name('M', 'I', 'G', 'R'),
1577    2,
1578    RTEMS_MINIMUM_STACK_SIZE,
1579    RTEMS_DEFAULT_MODES,
1580    RTEMS_DEFAULT_ATTRIBUTES,
1581    &ctx->migration_task_id
1582  );
1583  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1584
1585  sc = rtems_task_start(ctx->migration_task_id, migration_task, 0);
1586  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1587
1588  sc = rtems_semaphore_create(
1589    rtems_build_name('S', 'Y', 'N', 'C'),
1590    0,
1591    RTEMS_COUNTING_SEMAPHORE,
1592    0,
1593    &ctx->counting_sem_id
1594  );
1595  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1596
1597  for (index = 0; index < MRSP_COUNT; ++index) {
1598    create_mrsp_sema(ctx, &ctx->mrsp_ids[index], 3 + index);
1599  }
1600
1601  for (index = 0; index < cpu_count; ++index) {
1602    uint32_t a = 2 * index;
1603    uint32_t b = a + 1;
1604
1605    sc = rtems_task_create(
1606      'A' + a,
1607      255,
1608      RTEMS_MINIMUM_STACK_SIZE,
1609      RTEMS_DEFAULT_MODES,
1610      RTEMS_DEFAULT_ATTRIBUTES,
1611      &ctx->worker_ids[a]
1612    );
1613    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1614
1615    sc = rtems_task_set_scheduler(
1616      ctx->worker_ids[a],
1617      ctx->scheduler_ids[index],
1618      3 + MRSP_COUNT + a
1619    );
1620    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1621
1622    sc = rtems_task_start(
1623      ctx->worker_ids[a],
1624      load_worker,
1625      (rtems_task_argument) a
1626    );
1627    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1628
1629    sc = rtems_task_create(
1630      'A' + b,
1631      255,
1632      RTEMS_MINIMUM_STACK_SIZE,
1633      RTEMS_DEFAULT_MODES,
1634      RTEMS_DEFAULT_ATTRIBUTES,
1635      &ctx->worker_ids[b]
1636    );
1637    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1638
1639    sc = rtems_task_set_scheduler(
1640      ctx->worker_ids[b],
1641      ctx->scheduler_ids[index],
1642      3 + MRSP_COUNT + b
1643    );
1644    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1645
1646    sc = rtems_task_start(
1647      ctx->worker_ids[b],
1648      load_worker,
1649      (rtems_task_argument) b
1650    );
1651    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1652  }
1653
1654  sc = rtems_task_wake_after(30 * rtems_clock_get_ticks_per_second());
1655  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1656
1657  for (index = 0; index < 2 * cpu_count; ++index) {
1658    ctx->stop_worker[index] = true;
1659  }
1660
1661  for (index = 0; index < 2 * cpu_count; ++index) {
1662    sc = rtems_semaphore_obtain(
1663      ctx->counting_sem_id,
1664      RTEMS_WAIT,
1665      RTEMS_NO_TIMEOUT
1666    );
1667    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1668  }
1669
1670  for (index = 0; index < 2 * cpu_count; ++index) {
1671    sc = rtems_task_delete(ctx->worker_ids[index]);
1672    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1673  }
1674
1675  for (index = 0; index < MRSP_COUNT; ++index) {
1676    sc = rtems_semaphore_delete(ctx->mrsp_ids[index]);
1677    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1678  }
1679
1680  sc = rtems_semaphore_delete(ctx->counting_sem_id);
1681  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1682
1683  sc = rtems_task_delete(ctx->migration_task_id);
1684  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1685
1686  for (index = 0; index < 2 * cpu_count; ++index) {
1687    uint32_t nest_level;
1688    uint32_t cpu_index;
1689
1690    printf(
1691      "worker[%" PRIu32 "]\n"
1692        "  sleep = %" PRIu32 "\n"
1693        "  timeout = %" PRIu32 "\n",
1694      index,
1695      ctx->counters[index].sleep,
1696      ctx->counters[index].timeout
1697    );
1698
1699    for (nest_level = 0; nest_level < MRSP_COUNT; ++nest_level) {
1700      printf(
1701        "  obtain[%" PRIu32 "] = %" PRIu32 "\n",
1702        nest_level,
1703        ctx->counters[index].obtain[nest_level]
1704      );
1705    }
1706
1707    for (cpu_index = 0; cpu_index < cpu_count; ++cpu_index) {
1708      printf(
1709        "  cpu[%" PRIu32 "] = %" PRIu32 "\n",
1710        cpu_index,
1711        ctx->counters[index].cpu[cpu_index]
1712      );
1713    }
1714  }
1715
1716  for (index = 0; index < cpu_count; ++index) {
1717    printf(
1718      "migrations[%" PRIu32 "] = %" PRIu32 "\n",
1719      index,
1720      ctx->migration_counters[index]
1721    );
1722  }
1723}
1724
1725static void Init(rtems_task_argument arg)
1726{
1727  test_context *ctx = &test_instance;
1728  rtems_status_code sc;
1729  rtems_resource_snapshot snapshot;
1730  uint32_t cpu_count = rtems_get_processor_count();
1731  uint32_t cpu_index;
1732
1733  TEST_BEGIN();
1734
1735  rtems_resource_snapshot_take(&snapshot);
1736
1737  ctx->main_task_id = rtems_task_self();
1738
1739  for (cpu_index = 0; cpu_index < MIN(2, cpu_count); ++cpu_index) {
1740    sc = rtems_scheduler_ident(cpu_index, &ctx->scheduler_ids[cpu_index]);
1741    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1742  }
1743
1744  for (cpu_index = 2; cpu_index < cpu_count; ++cpu_index) {
1745    sc = rtems_scheduler_ident(
1746      cpu_index / 2 + 1,
1747      &ctx->scheduler_ids[cpu_index]
1748    );
1749    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
1750  }
1751
1752  test_mrsp_flush_error(ctx);
1753  test_mrsp_initially_locked_error();
1754  test_mrsp_nested_obtain_error(ctx);
1755  test_mrsp_deadlock_error(ctx);
1756  test_mrsp_multiple_obtain(ctx);
1757
1758  if (cpu_count > 1) {
1759    test_mrsp_various_block_and_unblock(ctx);
1760    test_mrsp_obtain_after_migration(ctx);
1761    test_mrsp_obtain_and_sleep_and_release(ctx);
1762    test_mrsp_obtain_and_release_with_help(ctx);
1763    test_mrsp_obtain_and_release(ctx);
1764    test_mrsp_load(ctx);
1765  }
1766
1767  rtems_test_assert(rtems_resource_snapshot_check(&snapshot));
1768
1769  TEST_END();
1770  rtems_test_exit(0);
1771}
1772
1773#define CONFIGURE_MICROSECONDS_PER_TICK 1000
1774
1775#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
1776#define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
1777
1778#define CONFIGURE_MAXIMUM_TASKS (2 * CPU_COUNT + 2)
1779#define CONFIGURE_MAXIMUM_SEMAPHORES (MRSP_COUNT + 1)
1780#define CONFIGURE_MAXIMUM_MRSP_SEMAPHORES MRSP_COUNT
1781#define CONFIGURE_MAXIMUM_TIMERS 1
1782
1783#define CONFIGURE_MAXIMUM_PROCESSORS CPU_COUNT
1784
1785#define CONFIGURE_SCHEDULER_SIMPLE_SMP
1786
1787#include <rtems/scheduler.h>
1788
1789RTEMS_SCHEDULER_SIMPLE_SMP(0);
1790RTEMS_SCHEDULER_SIMPLE_SMP(1);
1791RTEMS_SCHEDULER_SIMPLE_SMP(2);
1792RTEMS_SCHEDULER_SIMPLE_SMP(3);
1793RTEMS_SCHEDULER_SIMPLE_SMP(4);
1794RTEMS_SCHEDULER_SIMPLE_SMP(5);
1795RTEMS_SCHEDULER_SIMPLE_SMP(6);
1796RTEMS_SCHEDULER_SIMPLE_SMP(7);
1797RTEMS_SCHEDULER_SIMPLE_SMP(8);
1798RTEMS_SCHEDULER_SIMPLE_SMP(9);
1799RTEMS_SCHEDULER_SIMPLE_SMP(10);
1800RTEMS_SCHEDULER_SIMPLE_SMP(11);
1801RTEMS_SCHEDULER_SIMPLE_SMP(12);
1802RTEMS_SCHEDULER_SIMPLE_SMP(13);
1803RTEMS_SCHEDULER_SIMPLE_SMP(14);
1804RTEMS_SCHEDULER_SIMPLE_SMP(15);
1805RTEMS_SCHEDULER_SIMPLE_SMP(16);
1806
1807#define CONFIGURE_SCHEDULER_TABLE_ENTRIES \
1808  RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(0, 0), \
1809  RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(1, 1), \
1810  RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(2, 2), \
1811  RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(3, 3), \
1812  RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(4, 4), \
1813  RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(5, 5), \
1814  RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(6, 6), \
1815  RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(7, 7), \
1816  RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(8, 8), \
1817  RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(9, 9), \
1818  RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(10, 10), \
1819  RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(11, 11), \
1820  RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(12, 12), \
1821  RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(13, 13), \
1822  RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(14, 14), \
1823  RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(15, 15), \
1824  RTEMS_SCHEDULER_TABLE_SIMPLE_SMP(16, 16)
1825
1826#define CONFIGURE_SCHEDULER_ASSIGNMENTS \
1827  RTEMS_SCHEDULER_ASSIGN(0, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_MANDATORY), \
1828  RTEMS_SCHEDULER_ASSIGN(1, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
1829  RTEMS_SCHEDULER_ASSIGN(2, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
1830  RTEMS_SCHEDULER_ASSIGN(2, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
1831  RTEMS_SCHEDULER_ASSIGN(3, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
1832  RTEMS_SCHEDULER_ASSIGN(3, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
1833  RTEMS_SCHEDULER_ASSIGN(4, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
1834  RTEMS_SCHEDULER_ASSIGN(4, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
1835  RTEMS_SCHEDULER_ASSIGN(5, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
1836  RTEMS_SCHEDULER_ASSIGN(5, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
1837  RTEMS_SCHEDULER_ASSIGN(6, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
1838  RTEMS_SCHEDULER_ASSIGN(6, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
1839  RTEMS_SCHEDULER_ASSIGN(7, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
1840  RTEMS_SCHEDULER_ASSIGN(7, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
1841  RTEMS_SCHEDULER_ASSIGN(8, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
1842  RTEMS_SCHEDULER_ASSIGN(8, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
1843  RTEMS_SCHEDULER_ASSIGN(9, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
1844  RTEMS_SCHEDULER_ASSIGN(9, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
1845  RTEMS_SCHEDULER_ASSIGN(10, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
1846  RTEMS_SCHEDULER_ASSIGN(10, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
1847  RTEMS_SCHEDULER_ASSIGN(11, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
1848  RTEMS_SCHEDULER_ASSIGN(11, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
1849  RTEMS_SCHEDULER_ASSIGN(12, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
1850  RTEMS_SCHEDULER_ASSIGN(12, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
1851  RTEMS_SCHEDULER_ASSIGN(13, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
1852  RTEMS_SCHEDULER_ASSIGN(13, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
1853  RTEMS_SCHEDULER_ASSIGN(14, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
1854  RTEMS_SCHEDULER_ASSIGN(14, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
1855  RTEMS_SCHEDULER_ASSIGN(15, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
1856  RTEMS_SCHEDULER_ASSIGN(15, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
1857  RTEMS_SCHEDULER_ASSIGN(16, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
1858  RTEMS_SCHEDULER_ASSIGN(16, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL)
1859
1860#define CONFIGURE_INITIAL_EXTENSIONS \
1861  { .thread_switch = switch_extension }, \
1862  RTEMS_TEST_INITIAL_EXTENSION
1863
1864#define CONFIGURE_INIT_TASK_NAME rtems_build_name('M', 'A', 'I', 'N')
1865#define CONFIGURE_INIT_TASK_PRIORITY 2
1866
1867#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
1868
1869#define CONFIGURE_INIT
1870
1871#include <rtems/confdefs.h>
Note: See TracBrowser for help on using the repository browser.