source: rtems/testsuites/smptests/smpcache01/init.c @ e90486a

5
Last change on this file since e90486a was e90486a, checked in by Sebastian Huber <sebastian.huber@…>, on 04/11/19 at 13:16:40

score: Rework SMP multicast action

Use a FIFO list of jobs per processor to carry out the SMP multicast
action. Use a done indicator per job to reduce the bus traffic a bit.

  • Property mode set to 100644
File size: 5.8 KB
Line 
1/*
2 * Copyright (c) 2014 Aeroflex Gaisler AB.  All rights reserved.
3 * Copyright (c) 2017 embedded brains GmbH.
4 *
5 * The license and distribution terms for this file may be
6 * found in the file LICENSE in this distribution or at
7 * http://www.rtems.org/license/LICENSE.
8 */
9
10#ifdef HAVE_CONFIG_H
11  #include "config.h"
12#endif
13
14#include <rtems/score/atomic.h>
15#include <rtems/score/smpbarrier.h>
16#include <rtems/score/smpimpl.h>
17#include <rtems.h>
18#include <limits.h>
19#include <setjmp.h>
20#include <string.h>
21
22#include "tmacros.h"
23
24const char rtems_test_name[] = "SMPCACHE 1";
25
26#define CPU_COUNT 32
27
28#define WORKER_PRIORITY 100
29
30typedef struct {
31  SMP_barrier_Control barrier;
32  uint32_t count[CPU_COUNT];
33  bool do_longjmp[CPU_COUNT];
34  jmp_buf instruction_invalidate_return_context[CPU_COUNT];
35} test_context;
36
37static test_context ctx = {
38  .barrier = SMP_BARRIER_CONTROL_INITIALIZER,
39};
40
41static void function_to_flush( void )
42{
43  /* Does nothing. Used to give a pointer to instruction address space. */
44}
45
46static void test_action( void *arg )
47{
48  rtems_test_assert(arg == &ctx);
49
50  ctx.count[rtems_scheduler_get_processor()]++;
51}
52
53typedef void ( *test_case )( void );
54
55static void test_cache_invalidate_entire_instruction( void )
56{
57  rtems_cache_invalidate_entire_instruction();
58}
59
60static void test_cache_invalidate_multiple_instruction_lines( void )
61{
62  uint32_t self = rtems_scheduler_get_processor();
63
64  ctx.do_longjmp[self] = true;
65
66  if (setjmp(ctx.instruction_invalidate_return_context[self]) == 0) {
67    rtems_cache_invalidate_multiple_instruction_lines( &function_to_flush,
68        4 /* arbitrary size */ );
69  }
70
71  ctx.do_longjmp[self] = false;
72}
73
74static void barrier( SMP_barrier_State *bs )
75{
76  _SMP_barrier_Wait(
77    &ctx.barrier,
78    bs,
79    rtems_scheduler_get_processor_maximum()
80  );
81}
82
83static void broadcast_test_init( void )
84{
85  ctx.count[rtems_scheduler_get_processor()] = 0;
86}
87
88static void broadcast_test_body( void )
89{
90  _SMP_Multicast_action( NULL, test_action, &ctx );
91}
92
93static void broadcast_test_fini( void )
94{
95  rtems_test_assert(
96    ctx.count[rtems_scheduler_get_processor()]
97      == rtems_scheduler_get_processor_maximum()
98  );
99}
100
101static test_case test_cases[] = {
102  test_cache_invalidate_entire_instruction,
103  test_cache_invalidate_multiple_instruction_lines,
104  broadcast_test_body
105};
106
107static void call_tests( SMP_barrier_State *bs )
108{
109  size_t i;
110
111  broadcast_test_init();
112
113  for (i = 0; i < RTEMS_ARRAY_SIZE( test_cases ); ++i) {
114    barrier( bs );
115    ( *test_cases[ i ] )();
116    barrier( bs );
117  }
118
119  broadcast_test_fini();
120}
121
122static void call_tests_isr_disabled( SMP_barrier_State *bs )
123{
124  size_t i;
125
126  broadcast_test_init();
127
128  for (i = 0; i < RTEMS_ARRAY_SIZE( test_cases ); ++i) {
129    Per_CPU_Control *cpu_self;
130    ISR_Level        isr_level;
131
132    cpu_self = _Thread_Dispatch_disable();
133    _ISR_Local_disable( isr_level );
134    barrier( bs );
135    ( *test_cases[ i ] )();
136    _ISR_Local_enable( isr_level );
137    _Thread_Dispatch_enable( cpu_self );
138    barrier( bs );
139  }
140
141  broadcast_test_fini();
142}
143
144static void call_tests_with_thread_dispatch_disabled( SMP_barrier_State *bs )
145{
146  size_t i;
147
148  broadcast_test_init();
149
150  for (i = 0; i < RTEMS_ARRAY_SIZE( test_cases ); ++i) {
151    Per_CPU_Control *cpu_self;
152
153    cpu_self = _Thread_Dispatch_disable();
154    barrier( bs );
155    ( *test_cases[ i ] )();
156    barrier( bs );
157    _Thread_Dispatch_enable( cpu_self );
158  }
159
160  broadcast_test_fini();
161}
162
163static void cmlog(  const char* str )
164{
165  if ( rtems_scheduler_get_processor() == 0 )
166    printf( "%s", str );
167}
168
169static void all_tests( void )
170{
171  SMP_barrier_State bs = SMP_BARRIER_STATE_INITIALIZER;
172
173  /* Call test cases */
174  cmlog( "Calling test cases. " );
175  call_tests( &bs );
176  cmlog( "Done!\n");
177
178  /* Call test cases with ISR disabled */
179  cmlog( "Calling test cases with ISR disabled. " );
180  call_tests_isr_disabled( &bs );
181  cmlog( "Done!\n" );
182
183  /* Call test cases with thread dispatch disabled */
184  cmlog( "Calling test cases with thread_dispatch_disabled. ");
185  call_tests_with_thread_dispatch_disabled( &bs );
186  cmlog( "Done!\n");
187
188  /* Done. Free up memory. */
189  _SMP_barrier_Wait(
190    &ctx.barrier,
191    &bs,
192    rtems_scheduler_get_processor_maximum()
193  );
194}
195
196static void worker_task(rtems_task_argument arg)
197{
198  rtems_status_code sc;
199
200  all_tests();
201
202  sc = rtems_task_suspend(RTEMS_SELF);
203  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
204}
205
206static void test_smp_cache_manager( void )
207{
208  rtems_status_code sc;
209  size_t worker_index;
210  uint32_t cpu_count = rtems_scheduler_get_processor_maximum();
211
212  for (worker_index = 1; worker_index < cpu_count; ++worker_index) {
213    rtems_id worker_id;
214
215    sc = rtems_task_create(
216      rtems_build_name('W', 'R', 'K', '0'+worker_index),
217      WORKER_PRIORITY,
218      RTEMS_MINIMUM_STACK_SIZE,
219      RTEMS_DEFAULT_MODES,
220      RTEMS_DEFAULT_ATTRIBUTES,
221      &worker_id
222    );
223    rtems_test_assert( sc == RTEMS_SUCCESSFUL );
224
225    sc = rtems_task_start( worker_id, worker_task, 0 );
226    rtems_test_assert( sc == RTEMS_SUCCESSFUL );
227  }
228
229  all_tests();
230}
231
232
233static void Init(rtems_task_argument arg)
234{
235  TEST_BEGIN();
236
237  test_smp_cache_manager();
238
239  TEST_END();
240  rtems_test_exit(0);
241}
242
243static void fatal_extension(
244  rtems_fatal_source source,
245  bool always_set_to_false,
246  rtems_fatal_code error
247)
248{
249  uint32_t self = rtems_scheduler_get_processor();
250
251  if (source == RTEMS_FATAL_SOURCE_EXCEPTION && ctx.do_longjmp[self]) {
252    _ISR_Set_level(0);
253    longjmp(ctx.instruction_invalidate_return_context[self], 1);
254  }
255}
256
257#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
258#define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
259
260#define CONFIGURE_MAXIMUM_PROCESSORS CPU_COUNT
261
262#define CONFIGURE_MAXIMUM_TASKS CPU_COUNT
263
264#define CONFIGURE_MAXIMUM_TIMERS 1
265
266#define CONFIGURE_INITIAL_EXTENSIONS \
267  { .fatal = fatal_extension }, \
268  RTEMS_TEST_INITIAL_EXTENSION
269
270#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
271
272#define CONFIGURE_INIT
273
274#include <rtems/confdefs.h>
Note: See TracBrowser for help on using the repository browser.