source: rtems/testsuites/smptests/smpmrsp01/init.c @ cceb19f4

4.115
Last change on this file since cceb19f4 was cceb19f4, checked in by Luca Bonato <lohathe@…>, on 11/21/14 at 10:01:34

smp: Fix scheduler helping protocol

New test case for smptests/smpmrsp01.

Fix _Scheduler_Block_node() in case the node is in the
SCHEDULER_HELP_ACTIVE_RIVAL helping state. For example a
rtems_task_suspend() on a task waiting for a MrsP semaphore.

Fix _Scheduler_Unblock_node() in case the node is in the
SCHEDULER_SMP_NODE_READY state. For example a rtems_task_resume() on a
task owning or waiting for a MrsP semaphore.

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