source: rtems/testsuites/smptests/smpmrsp01/init.c @ 0ff1c29

4.11
Last change on this file since 0ff1c29 was 0ff1c29, checked in by Sebastian Huber <sebastian.huber@…>, on Nov 27, 2014 at 7:45:10 AM

smptests/smpmrsp01: Use busy waits

Use busy waits instead of sleeps to avoid unnecessary switches to the
idle thread.

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