source: rtems/testsuites/smptests/smpmrsp01/init.c @ 6771359f

5
Last change on this file since 6771359f was 6771359f, checked in by Sebastian Huber <sebastian.huber@…>, on Oct 27, 2016 at 4:42:06 AM

score: Second part of new MrsP implementation

Update #2556.

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