source: rtems/testsuites/smptests/smpmrsp01/init.c @ 9553e7a6

4.115
Last change on this file since 9553e7a6 was 9553e7a6, checked in by Sebastian Huber <sebastian.huber@…>, on 05/26/14 at 14:02:58

score: Use Resource Handler for MrsP semaphores

This enables proper resource dependency tracking and as a side-effect
deadlock detection.

  • Property mode set to 100644
File size: 25.8 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/smpbarrier.h>
25
26#define TESTS_USE_PRINTK
27#include "tmacros.h"
28
29const char rtems_test_name[] = "SMPMRSP 1";
30
31#define CPU_COUNT 32
32
33#define MRSP_COUNT 32
34
35typedef struct {
36  uint32_t sleep;
37  uint32_t timeout;
38  uint32_t obtain[MRSP_COUNT];
39} counter;
40
41typedef struct {
42  rtems_id main_task_id;
43  rtems_id counting_sem_id;
44  rtems_id mrsp_ids[MRSP_COUNT];
45  rtems_id scheduler_ids[CPU_COUNT];
46  rtems_id worker_ids[2 * CPU_COUNT];
47  rtems_id timer_id;
48  volatile bool stop_worker[CPU_COUNT];
49  counter counters[2 * CPU_COUNT];
50  Thread_Control *worker_task;
51  SMP_barrier_Control barrier;
52} test_context;
53
54static test_context test_instance = {
55  .barrier = SMP_BARRIER_CONTROL_INITIALIZER
56};
57
58static void barrier(test_context *ctx, SMP_barrier_State *bs)
59{
60  _SMP_barrier_Wait(&ctx->barrier, bs, 2);
61}
62
63static void assert_prio(rtems_id task_id, rtems_task_priority expected_prio)
64{
65  rtems_status_code sc;
66  rtems_task_priority prio;
67
68  sc = rtems_task_set_priority(task_id, RTEMS_CURRENT_PRIORITY, &prio);
69  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
70  rtems_test_assert(prio == expected_prio);
71}
72
73static void change_prio(rtems_id task_id, rtems_task_priority prio)
74{
75  rtems_status_code sc;
76
77  sc = rtems_task_set_priority(task_id, prio, &prio);
78  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
79}
80
81static void assert_executing_worker(test_context *ctx)
82{
83  rtems_test_assert(
84    _CPU_Context_Get_is_executing(&ctx->worker_task->Registers)
85  );
86}
87
88static void obtain_and_release_worker(rtems_task_argument arg)
89{
90  test_context *ctx = &test_instance;
91  rtems_status_code sc;
92  SMP_barrier_State barrier_state = SMP_BARRIER_STATE_INITIALIZER;
93
94  ctx->worker_task = _Thread_Get_executing();
95
96  assert_prio(RTEMS_SELF, 3);
97
98  /* Obtain with timeout (A) */
99  barrier(ctx, &barrier_state);
100
101  sc = rtems_semaphore_obtain(ctx->mrsp_ids[0], RTEMS_WAIT, 4);
102  rtems_test_assert(sc == RTEMS_TIMEOUT);
103
104  assert_prio(RTEMS_SELF, 3);
105
106  /* Obtain with priority change and timeout (B) */
107  barrier(ctx, &barrier_state);
108
109  sc = rtems_semaphore_obtain(ctx->mrsp_ids[0], RTEMS_WAIT, 4);
110  rtems_test_assert(sc == RTEMS_TIMEOUT);
111
112  assert_prio(RTEMS_SELF, 1);
113
114  /* Restore priority (C) */
115  barrier(ctx, &barrier_state);
116
117  /* Obtain without timeout (D) */
118  barrier(ctx, &barrier_state);
119
120  sc = rtems_semaphore_obtain(ctx->mrsp_ids[0], RTEMS_WAIT, RTEMS_NO_TIMEOUT);
121  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
122
123  assert_prio(RTEMS_SELF, 2);
124
125  sc = rtems_semaphore_release(ctx->mrsp_ids[0]);
126  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
127
128  assert_prio(RTEMS_SELF, 3);
129
130  /* Worker done (E) */
131  barrier(ctx, &barrier_state);
132
133  rtems_task_suspend(RTEMS_SELF);
134  rtems_test_assert(0);
135}
136
137static void test_mrsp_obtain_and_release(void)
138{
139  test_context *ctx = &test_instance;
140  rtems_status_code sc;
141  rtems_task_priority prio;
142  rtems_id scheduler_id;
143  SMP_barrier_State barrier_state = SMP_BARRIER_STATE_INITIALIZER;
144
145  puts("test MrsP obtain and release");
146
147  /* Check executing task parameters */
148
149  sc = rtems_task_get_scheduler(RTEMS_SELF, &scheduler_id);
150  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
151
152  rtems_test_assert(ctx->scheduler_ids[0] == scheduler_id);
153
154  assert_prio(RTEMS_SELF, 2);
155
156  /* Create a MrsP semaphore object and lock it */
157
158  sc = rtems_semaphore_create(
159    rtems_build_name('M', 'R', 'S', 'P'),
160    1,
161    RTEMS_MULTIPROCESSOR_RESOURCE_SHARING
162      | RTEMS_BINARY_SEMAPHORE,
163    1,
164    &ctx->mrsp_ids[0]
165  );
166  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
167
168  assert_prio(RTEMS_SELF, 2);
169
170  sc = rtems_semaphore_obtain(ctx->mrsp_ids[0], RTEMS_WAIT, RTEMS_NO_TIMEOUT);
171  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
172
173  assert_prio(RTEMS_SELF, 1);
174
175  /*
176   * The ceiling priority values per scheduler are equal to the value specified
177   * for object creation.
178   */
179
180  prio = RTEMS_CURRENT_PRIORITY;
181  sc = rtems_semaphore_set_priority(
182    ctx->mrsp_ids[0],
183    ctx->scheduler_ids[0],
184    prio,
185    &prio
186  );
187  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
188  rtems_test_assert(prio == 1);
189
190  /* Check the old value and set a new ceiling priority for scheduler B */
191
192  prio = 2;
193  sc = rtems_semaphore_set_priority(
194    ctx->mrsp_ids[0],
195    ctx->scheduler_ids[1],
196    prio,
197    &prio
198  );
199  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
200  rtems_test_assert(prio == 1);
201
202  /* Check the ceiling priority values */
203
204  prio = RTEMS_CURRENT_PRIORITY;
205  sc = rtems_semaphore_set_priority(
206    ctx->mrsp_ids[0],
207    ctx->scheduler_ids[0],
208    prio,
209    &prio
210  );
211  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
212  rtems_test_assert(prio == 1);
213
214  prio = RTEMS_CURRENT_PRIORITY;
215  sc = rtems_semaphore_set_priority(
216    ctx->mrsp_ids[0],
217    ctx->scheduler_ids[1],
218    prio,
219    &prio
220  );
221  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
222  rtems_test_assert(prio == 2);
223
224  /* Check that a thread waiting to get ownership remains executing */
225
226  sc = rtems_task_create(
227    rtems_build_name('W', 'O', 'R', 'K'),
228    3,
229    RTEMS_MINIMUM_STACK_SIZE,
230    RTEMS_DEFAULT_MODES,
231    RTEMS_DEFAULT_ATTRIBUTES,
232    &ctx->worker_ids[0]
233  );
234  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
235
236  sc = rtems_task_set_scheduler(ctx->worker_ids[0], ctx->scheduler_ids[1]);
237  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
238
239  sc = rtems_task_start(ctx->worker_ids[0], obtain_and_release_worker, 0);
240  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
241
242  /* Obtain with timeout (A) */
243  barrier(ctx, &barrier_state);
244
245  sc = rtems_task_wake_after(2);
246  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
247
248  assert_prio(ctx->worker_ids[0], 2);
249  assert_executing_worker(ctx);
250
251  /* Obtain with priority change and timeout (B) */
252  barrier(ctx, &barrier_state);
253
254  sc = rtems_task_wake_after(2);
255  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
256
257  assert_prio(ctx->worker_ids[0], 2);
258  change_prio(ctx->worker_ids[0], 1);
259  assert_executing_worker(ctx);
260
261  /* Restore priority (C) */
262  barrier(ctx, &barrier_state);
263
264  assert_prio(ctx->worker_ids[0], 1);
265  change_prio(ctx->worker_ids[0], 3);
266
267  /* Obtain without timeout (D) */
268  barrier(ctx, &barrier_state);
269
270  sc = rtems_task_wake_after(2);
271  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
272
273  assert_prio(ctx->worker_ids[0], 2);
274  assert_executing_worker(ctx);
275
276  sc = rtems_semaphore_release(ctx->mrsp_ids[0]);
277  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
278
279  /* Worker done (E) */
280  barrier(ctx, &barrier_state);
281
282  sc = rtems_task_delete(ctx->worker_ids[0]);
283  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
284
285  sc = rtems_semaphore_delete(ctx->mrsp_ids[0]);
286  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
287}
288
289static void test_mrsp_flush_error(void)
290{
291  rtems_status_code sc;
292  rtems_id id;
293
294  puts("test MrsP flush error");
295
296  sc = rtems_semaphore_create(
297    rtems_build_name('M', 'R', 'S', 'P'),
298    1,
299    RTEMS_MULTIPROCESSOR_RESOURCE_SHARING
300      | RTEMS_BINARY_SEMAPHORE,
301    1,
302    &id
303  );
304  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
305
306  sc = rtems_semaphore_flush(id);
307  rtems_test_assert(sc == RTEMS_NOT_DEFINED);
308
309  sc = rtems_semaphore_delete(id);
310  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
311}
312
313static void test_mrsp_initially_locked_error(void)
314{
315  rtems_status_code sc;
316  rtems_id id;
317
318  puts("test MrsP initially locked error");
319
320  sc = rtems_semaphore_create(
321    rtems_build_name('M', 'R', 'S', 'P'),
322    0,
323    RTEMS_MULTIPROCESSOR_RESOURCE_SHARING
324      | RTEMS_BINARY_SEMAPHORE,
325    1,
326    &id
327  );
328  rtems_test_assert(sc == RTEMS_INVALID_NUMBER);
329}
330
331static void test_mrsp_nested_obtain_error(void)
332{
333  rtems_status_code sc;
334  rtems_id id;
335
336  puts("test MrsP nested obtain error");
337
338  sc = rtems_semaphore_create(
339    rtems_build_name('M', 'R', 'S', 'P'),
340    1,
341    RTEMS_MULTIPROCESSOR_RESOURCE_SHARING
342      | RTEMS_BINARY_SEMAPHORE,
343    1,
344    &id
345  );
346  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
347
348  sc = rtems_semaphore_obtain(id, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
349  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
350
351  sc = rtems_semaphore_obtain(id, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
352  rtems_test_assert(sc == RTEMS_UNSATISFIED);
353
354  sc = rtems_semaphore_release(id);
355  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
356
357  sc = rtems_semaphore_delete(id);
358  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
359}
360
361static void test_mrsp_unlock_order_error(void)
362{
363  rtems_status_code sc;
364  rtems_id id_a;
365  rtems_id id_b;
366
367  puts("test MrsP unlock order error");
368
369  sc = rtems_semaphore_create(
370    rtems_build_name(' ', ' ', ' ', 'A'),
371    1,
372    RTEMS_MULTIPROCESSOR_RESOURCE_SHARING
373      | RTEMS_BINARY_SEMAPHORE,
374    1,
375    &id_a
376  );
377  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
378
379  sc = rtems_semaphore_create(
380    rtems_build_name(' ', ' ', ' ', 'B'),
381    1,
382    RTEMS_MULTIPROCESSOR_RESOURCE_SHARING
383      | RTEMS_BINARY_SEMAPHORE,
384    1,
385    &id_b
386  );
387  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
388
389  sc = rtems_semaphore_obtain(id_a, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
390  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
391
392  sc = rtems_semaphore_obtain(id_b, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
393  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
394
395  sc = rtems_semaphore_release(id_a);
396  rtems_test_assert(sc == RTEMS_INCORRECT_STATE);
397
398  sc = rtems_semaphore_release(id_b);
399  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
400
401  sc = rtems_semaphore_release(id_a);
402  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
403
404  sc = rtems_semaphore_delete(id_a);
405  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
406
407  sc = rtems_semaphore_delete(id_b);
408  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
409}
410
411static void deadlock_timer(rtems_id id, void *arg)
412{
413  test_context *ctx = &test_instance;
414  rtems_status_code sc;
415
416  sc = rtems_task_suspend(ctx->worker_ids[0]);
417  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
418}
419
420static void deadlock_worker(rtems_task_argument arg)
421{
422  test_context *ctx = &test_instance;
423  rtems_status_code sc;
424
425  sc = rtems_semaphore_obtain(ctx->mrsp_ids[1], RTEMS_WAIT, RTEMS_NO_TIMEOUT);
426  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
427
428  sc = rtems_timer_fire_after(ctx->timer_id, 2, deadlock_timer, NULL);
429  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
430
431  sc = rtems_semaphore_obtain(ctx->mrsp_ids[0], RTEMS_WAIT, RTEMS_NO_TIMEOUT);
432  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
433
434  sc = rtems_semaphore_release(ctx->mrsp_ids[0]);
435  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
436
437  sc = rtems_semaphore_release(ctx->mrsp_ids[1]);
438  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
439
440  sc = rtems_event_transient_send(ctx->main_task_id);
441  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
442
443  rtems_task_suspend(RTEMS_SELF);
444  rtems_test_assert(0);
445}
446
447static void test_mrsp_deadlock_error(void)
448{
449  test_context *ctx = &test_instance;
450  rtems_status_code sc;
451  rtems_task_priority prio = 2;
452
453  puts("test MrsP deadlock error");
454
455  assert_prio(RTEMS_SELF, prio);
456
457  sc = rtems_timer_create(
458    rtems_build_name('M', 'R', 'S', 'P'),
459    &ctx->timer_id
460  );
461  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
462
463  sc = rtems_semaphore_create(
464    rtems_build_name(' ', ' ', ' ', 'A'),
465    1,
466    RTEMS_MULTIPROCESSOR_RESOURCE_SHARING
467      | RTEMS_BINARY_SEMAPHORE,
468    prio,
469    &ctx->mrsp_ids[0]
470  );
471  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
472
473  sc = rtems_semaphore_create(
474    rtems_build_name(' ', ' ', ' ', 'B'),
475    1,
476    RTEMS_MULTIPROCESSOR_RESOURCE_SHARING
477      | RTEMS_BINARY_SEMAPHORE,
478    prio,
479    &ctx->mrsp_ids[1]
480  );
481  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
482
483  sc = rtems_task_create(
484    rtems_build_name('W', 'O', 'R', 'K'),
485    prio,
486    RTEMS_MINIMUM_STACK_SIZE,
487    RTEMS_DEFAULT_MODES,
488    RTEMS_DEFAULT_ATTRIBUTES,
489    &ctx->worker_ids[0]
490  );
491  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
492
493  sc = rtems_task_start(ctx->worker_ids[0], deadlock_worker, 0);
494  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
495
496  sc = rtems_semaphore_obtain(ctx->mrsp_ids[0], RTEMS_WAIT, RTEMS_NO_TIMEOUT);
497  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
498
499  sc = rtems_task_wake_after(RTEMS_YIELD_PROCESSOR);
500  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
501
502  sc = rtems_semaphore_obtain(ctx->mrsp_ids[1], RTEMS_WAIT, RTEMS_NO_TIMEOUT);
503  rtems_test_assert(sc == RTEMS_UNSATISFIED);
504
505  sc = rtems_semaphore_release(ctx->mrsp_ids[0]);
506  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
507
508  sc = rtems_task_resume(ctx->worker_ids[0]);
509  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
510
511  sc = rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT);
512  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
513
514  sc = rtems_task_delete(ctx->worker_ids[0]);
515  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
516
517  sc = rtems_semaphore_delete(ctx->mrsp_ids[0]);
518  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
519
520  sc = rtems_semaphore_delete(ctx->mrsp_ids[1]);
521  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
522
523  sc = rtems_timer_delete(ctx->timer_id);
524  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
525}
526
527static void test_mrsp_multiple_obtain(void)
528{
529  rtems_status_code sc;
530  rtems_id sem_a_id;
531  rtems_id sem_b_id;
532  rtems_id sem_c_id;
533
534  puts("test MrsP multiple obtain");
535
536  change_prio(RTEMS_SELF, 4);
537
538  sc = rtems_semaphore_create(
539    rtems_build_name(' ', ' ', ' ', 'A'),
540    1,
541    RTEMS_MULTIPROCESSOR_RESOURCE_SHARING
542      | RTEMS_BINARY_SEMAPHORE,
543    3,
544    &sem_a_id
545  );
546  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
547
548  sc = rtems_semaphore_create(
549    rtems_build_name(' ', ' ', ' ', 'B'),
550    1,
551    RTEMS_MULTIPROCESSOR_RESOURCE_SHARING
552      | RTEMS_BINARY_SEMAPHORE,
553    2,
554    &sem_b_id
555  );
556  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
557
558  sc = rtems_semaphore_create(
559    rtems_build_name(' ', ' ', ' ', 'C'),
560    1,
561    RTEMS_MULTIPROCESSOR_RESOURCE_SHARING
562      | RTEMS_BINARY_SEMAPHORE,
563    1,
564    &sem_c_id
565  );
566  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
567
568  assert_prio(RTEMS_SELF, 4);
569
570  sc = rtems_semaphore_obtain(sem_a_id, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
571  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
572
573  assert_prio(RTEMS_SELF, 3);
574
575  sc = rtems_semaphore_obtain(sem_b_id, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
576  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
577
578  assert_prio(RTEMS_SELF, 2);
579
580  sc = rtems_semaphore_obtain(sem_c_id, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
581  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
582
583  assert_prio(RTEMS_SELF, 1);
584
585  sc = rtems_semaphore_release(sem_c_id);
586  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
587
588  assert_prio(RTEMS_SELF, 2);
589
590  sc = rtems_semaphore_release(sem_b_id);
591  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
592
593  assert_prio(RTEMS_SELF, 3);
594
595  sc = rtems_semaphore_release(sem_a_id);
596  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
597
598  assert_prio(RTEMS_SELF, 4);
599
600  sc = rtems_semaphore_obtain(sem_a_id, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
601  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
602
603  assert_prio(RTEMS_SELF, 3);
604
605  sc = rtems_semaphore_obtain(sem_b_id, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
606  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
607
608  assert_prio(RTEMS_SELF, 2);
609
610  sc = rtems_semaphore_obtain(sem_c_id, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
611  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
612
613  assert_prio(RTEMS_SELF, 1);
614  change_prio(RTEMS_SELF, 3);
615  assert_prio(RTEMS_SELF, 1);
616
617  sc = rtems_semaphore_release(sem_c_id);
618  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
619
620  assert_prio(RTEMS_SELF, 2);
621
622  sc = rtems_semaphore_release(sem_b_id);
623  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
624
625  assert_prio(RTEMS_SELF, 3);
626
627  sc = rtems_semaphore_release(sem_a_id);
628  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
629
630  assert_prio(RTEMS_SELF, 3);
631
632  sc = rtems_semaphore_delete(sem_a_id);
633  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
634
635  sc = rtems_semaphore_delete(sem_b_id);
636  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
637
638  sc = rtems_semaphore_delete(sem_c_id);
639  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
640
641  change_prio(RTEMS_SELF, 2);
642  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
643}
644
645static uint32_t simple_random(uint32_t v)
646{
647  v *= 1664525;
648  v += 1013904223;
649
650  return v;
651}
652
653static rtems_interval timeout(uint32_t v)
654{
655  return (v >> 23) % 4;
656}
657
658static void load_worker(rtems_task_argument index)
659{
660  test_context *ctx = &test_instance;
661  rtems_status_code sc;
662  uint32_t v = index;
663
664  while (!ctx->stop_worker[index]) {
665    uint32_t i = (v >> 13) % MRSP_COUNT;
666
667    assert_prio(RTEMS_SELF, 3 + CPU_COUNT + index);
668
669    if ((v >> 7) % 1024 == 0) {
670      /* Give some time to the lower priority tasks */
671
672      ++ctx->counters[index].sleep;
673
674      sc = rtems_task_wake_after(1);
675      rtems_test_assert(sc == RTEMS_SUCCESSFUL);
676    } else {
677      uint32_t n = (v >> 17) % (i + 1);
678      uint32_t s;
679      uint32_t t;
680
681      /* Nested obtain */
682      for (s = 0; s <= n; ++s) {
683        uint32_t k = i - s;
684
685        sc = rtems_semaphore_obtain(ctx->mrsp_ids[k], RTEMS_WAIT, timeout(v));
686        if (sc == RTEMS_SUCCESSFUL) {
687          ++ctx->counters[index].obtain[n];
688
689          assert_prio(RTEMS_SELF, 3 + k);
690        } else {
691          rtems_test_assert(sc == RTEMS_TIMEOUT);
692
693          ++ctx->counters[index].timeout;
694
695          break;
696        }
697
698        v = simple_random(v);
699      }
700
701      /* Release in reverse obtain order */
702      for (t = 0; t < s; ++t) {
703        uint32_t k = i + t - s + 1;
704
705        sc = rtems_semaphore_release(ctx->mrsp_ids[k]);
706        rtems_test_assert(sc == RTEMS_SUCCESSFUL);
707      }
708    }
709
710    v = simple_random(v);
711  }
712
713  sc = rtems_semaphore_release(ctx->counting_sem_id);
714  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
715
716  rtems_task_suspend(RTEMS_SELF);
717  rtems_test_assert(0);
718}
719
720static void test_mrsp_load(void)
721{
722  test_context *ctx = &test_instance;
723  rtems_status_code sc;
724  uint32_t cpu_count = rtems_get_processor_count();
725  uint32_t index;
726
727  puts("test MrsP load");
728
729  assert_prio(RTEMS_SELF, 2);
730
731  sc = rtems_semaphore_create(
732    rtems_build_name('S', 'Y', 'N', 'C'),
733    0,
734    RTEMS_COUNTING_SEMAPHORE,
735    0,
736    &ctx->counting_sem_id
737  );
738  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
739
740  for (index = 0; index < MRSP_COUNT; ++index) {
741    sc = rtems_semaphore_create(
742      'A' + index,
743      1,
744      RTEMS_MULTIPROCESSOR_RESOURCE_SHARING
745        | RTEMS_BINARY_SEMAPHORE,
746      3 + index,
747      &ctx->mrsp_ids[index]
748    );
749    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
750  }
751
752  for (index = 0; index < cpu_count; ++index) {
753    uint32_t a = 2 * index;
754    uint32_t b = a + 1;
755
756    sc = rtems_task_create(
757      'A' + a,
758      3 + MRSP_COUNT + a,
759      RTEMS_MINIMUM_STACK_SIZE,
760      RTEMS_DEFAULT_MODES,
761      RTEMS_DEFAULT_ATTRIBUTES,
762      &ctx->worker_ids[a]
763    );
764    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
765
766    sc = rtems_task_set_scheduler(
767      ctx->worker_ids[a],
768      ctx->scheduler_ids[index]
769    );
770    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
771
772    sc = rtems_task_start(
773      ctx->worker_ids[a],
774      load_worker,
775      (rtems_task_argument) a
776    );
777    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
778
779    sc = rtems_task_create(
780      'A' + b,
781      3 + MRSP_COUNT + b,
782      RTEMS_MINIMUM_STACK_SIZE,
783      RTEMS_DEFAULT_MODES,
784      RTEMS_DEFAULT_ATTRIBUTES,
785      &ctx->worker_ids[b]
786    );
787    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
788
789    sc = rtems_task_set_scheduler(
790      ctx->worker_ids[b],
791      ctx->scheduler_ids[index]
792    );
793    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
794
795    sc = rtems_task_start(
796      ctx->worker_ids[b],
797      load_worker,
798      (rtems_task_argument) b
799    );
800    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
801  }
802
803  sc = rtems_task_wake_after(30 * rtems_clock_get_ticks_per_second());
804  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
805
806  for (index = 0; index < 2 * cpu_count; ++index) {
807    ctx->stop_worker[index] = true;
808  }
809
810  for (index = 0; index < 2 * cpu_count; ++index) {
811    sc = rtems_semaphore_obtain(
812      ctx->counting_sem_id,
813      RTEMS_WAIT,
814      RTEMS_NO_TIMEOUT
815    );
816    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
817  }
818
819  for (index = 0; index < 2 * cpu_count; ++index) {
820    sc = rtems_task_delete(ctx->worker_ids[index]);
821    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
822  }
823
824  for (index = 0; index < MRSP_COUNT; ++index) {
825    sc = rtems_semaphore_delete(ctx->mrsp_ids[index]);
826    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
827  }
828
829  sc = rtems_semaphore_delete(ctx->counting_sem_id);
830  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
831
832  for (index = 0; index < 2 * cpu_count; ++index) {
833    uint32_t nest_level;
834
835    printf(
836      "worker[%" PRIu32 "][%" PRIu32 "]\n"
837        "  sleep = %" PRIu32 "\n"
838        "  timeout = %" PRIu32 "\n",
839      index / 2,
840      index % 2,
841      ctx->counters[index].sleep,
842      ctx->counters[index].timeout
843    );
844
845    for (nest_level = 0; nest_level < MRSP_COUNT; ++nest_level) {
846      printf(
847        "  obtain[%" PRIu32 "] = %" PRIu32 "\n",
848        nest_level,
849        ctx->counters[index].obtain[nest_level]
850      );
851    }
852  }
853}
854
855static void Init(rtems_task_argument arg)
856{
857  test_context *ctx = &test_instance;
858  rtems_status_code sc;
859  rtems_resource_snapshot snapshot;
860  uint32_t cpu_count = rtems_get_processor_count();
861  uint32_t cpu_index;
862
863  TEST_BEGIN();
864
865  rtems_resource_snapshot_take(&snapshot);
866
867  ctx->main_task_id = rtems_task_self();
868
869  for (cpu_index = 0; cpu_index < cpu_count; ++cpu_index) {
870    sc = rtems_scheduler_ident(cpu_index, &ctx->scheduler_ids[cpu_index]);
871    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
872  }
873
874  test_mrsp_flush_error();
875  test_mrsp_initially_locked_error();
876  test_mrsp_nested_obtain_error();
877  test_mrsp_unlock_order_error();
878  test_mrsp_deadlock_error();
879  test_mrsp_multiple_obtain();
880  test_mrsp_obtain_and_release();
881  test_mrsp_load();
882
883  rtems_test_assert(rtems_resource_snapshot_check(&snapshot));
884
885  TEST_END();
886  rtems_test_exit(0);
887}
888
889#define CONFIGURE_SMP_APPLICATION
890
891#define CONFIGURE_MICROSECONDS_PER_TICK 1000
892
893#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
894#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
895
896#define CONFIGURE_MAXIMUM_TASKS (2 * CPU_COUNT + 1)
897#define CONFIGURE_MAXIMUM_SEMAPHORES (MRSP_COUNT + 1)
898#define CONFIGURE_MAXIMUM_MRSP_SEMAPHORES MRSP_COUNT
899#define CONFIGURE_MAXIMUM_TIMERS 1
900
901#define CONFIGURE_SMP_MAXIMUM_PROCESSORS CPU_COUNT
902
903#define CONFIGURE_SCHEDULER_SIMPLE_SMP
904
905#include <rtems/scheduler.h>
906
907RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(0);
908RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(1);
909RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(2);
910RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(3);
911RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(4);
912RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(5);
913RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(6);
914RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(7);
915RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(8);
916RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(9);
917RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(10);
918RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(11);
919RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(12);
920RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(13);
921RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(14);
922RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(15);
923RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(16);
924
925#define CONFIGURE_SCHEDULER_CONTROLS \
926  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(0, 0), \
927  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(1, 1), \
928  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(2, 2), \
929  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(3, 3), \
930  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(4, 4), \
931  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(5, 5), \
932  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(6, 6), \
933  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(7, 7), \
934  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(8, 8), \
935  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(9, 9), \
936  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(10, 10), \
937  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(11, 11), \
938  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(12, 12), \
939  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(13, 13), \
940  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(14, 14), \
941  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(15, 15), \
942  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(16, 16)
943
944#define CONFIGURE_SMP_SCHEDULER_ASSIGNMENTS \
945  RTEMS_SCHEDULER_ASSIGN(0, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_MANDATORY), \
946  RTEMS_SCHEDULER_ASSIGN(1, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_MANDATORY), \
947  RTEMS_SCHEDULER_ASSIGN(2, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
948  RTEMS_SCHEDULER_ASSIGN(2, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
949  RTEMS_SCHEDULER_ASSIGN(3, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
950  RTEMS_SCHEDULER_ASSIGN(3, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
951  RTEMS_SCHEDULER_ASSIGN(4, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
952  RTEMS_SCHEDULER_ASSIGN(4, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
953  RTEMS_SCHEDULER_ASSIGN(5, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
954  RTEMS_SCHEDULER_ASSIGN(5, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
955  RTEMS_SCHEDULER_ASSIGN(6, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
956  RTEMS_SCHEDULER_ASSIGN(6, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
957  RTEMS_SCHEDULER_ASSIGN(7, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
958  RTEMS_SCHEDULER_ASSIGN(7, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
959  RTEMS_SCHEDULER_ASSIGN(8, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
960  RTEMS_SCHEDULER_ASSIGN(8, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
961  RTEMS_SCHEDULER_ASSIGN(9, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
962  RTEMS_SCHEDULER_ASSIGN(9, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
963  RTEMS_SCHEDULER_ASSIGN(10, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
964  RTEMS_SCHEDULER_ASSIGN(10, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
965  RTEMS_SCHEDULER_ASSIGN(11, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
966  RTEMS_SCHEDULER_ASSIGN(11, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
967  RTEMS_SCHEDULER_ASSIGN(12, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
968  RTEMS_SCHEDULER_ASSIGN(12, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
969  RTEMS_SCHEDULER_ASSIGN(13, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
970  RTEMS_SCHEDULER_ASSIGN(13, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
971  RTEMS_SCHEDULER_ASSIGN(14, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
972  RTEMS_SCHEDULER_ASSIGN(14, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
973  RTEMS_SCHEDULER_ASSIGN(15, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
974  RTEMS_SCHEDULER_ASSIGN(15, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
975  RTEMS_SCHEDULER_ASSIGN(16, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
976  RTEMS_SCHEDULER_ASSIGN(16, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL)
977
978#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
979
980#define CONFIGURE_INIT_TASK_PRIORITY 2
981
982#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
983
984#define CONFIGURE_INIT
985
986#include <rtems/confdefs.h>
Note: See TracBrowser for help on using the repository browser.