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

5
Last change on this file since f9219db was f9219db, checked in by Sebastian Huber <sebastian.huber@…>, on 04/05/19 at 06:16:05

rtems: Add rtems_scheduler_get_processor_maximum()

Add rtems_scheduler_get_processor_maximum() as a replacement for
rtems_get_processor_count(). The rtems_get_processor_count() is a bit
orphaned. Adopt it by the Scheduler Manager. The count is also
misleading, since the processor set may have gaps and the actual count
of online processors may be less than the value returned by
rtems_get_processor_count().

Update #3732.

  • Property mode set to 100644
File size: 6.3 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 )(
54  size_t set_size,
55  const cpu_set_t *cpu_set
56);
57
58static void test_cache_invalidate_entire_instruction(
59  size_t set_size,
60  const cpu_set_t *cpu_set
61)
62{
63  rtems_cache_invalidate_entire_instruction();
64}
65
66static void test_cache_invalidate_multiple_instruction_lines(
67  size_t set_size,
68  const cpu_set_t *cpu_set
69)
70{
71  uint32_t self = rtems_scheduler_get_processor();
72
73  ctx.do_longjmp[self] = true;
74
75  if (setjmp(ctx.instruction_invalidate_return_context[self]) == 0) {
76    rtems_cache_invalidate_multiple_instruction_lines( &function_to_flush,
77        4 /* arbitrary size */ );
78  }
79
80  ctx.do_longjmp[self] = false;
81}
82
83static void barrier( SMP_barrier_State *bs )
84{
85  _SMP_barrier_Wait(
86    &ctx.barrier,
87    bs,
88    rtems_scheduler_get_processor_maximum()
89  );
90}
91
92static void broadcast_test_init( void )
93{
94  ctx.count[rtems_scheduler_get_processor()] = 0;
95}
96
97static void broadcast_test_body(
98  size_t set_size,
99  const cpu_set_t *cpu_set
100)
101{
102  _SMP_Multicast_action( set_size, cpu_set, test_action, &ctx );
103}
104
105static void broadcast_test_fini( void )
106{
107  rtems_test_assert(
108    ctx.count[rtems_scheduler_get_processor()]
109      == rtems_scheduler_get_processor_maximum()
110  );
111}
112
113static test_case test_cases[] = {
114  test_cache_invalidate_entire_instruction,
115  test_cache_invalidate_multiple_instruction_lines,
116  broadcast_test_body
117};
118
119static void call_tests( size_t set_size,
120    const cpu_set_t *cpu_set, SMP_barrier_State *bs  )
121{
122  size_t i;
123
124  broadcast_test_init();
125
126  for (i = 0; i < RTEMS_ARRAY_SIZE( test_cases ); ++i) {
127    barrier( bs );
128    ( *test_cases[ i ] )( set_size, cpu_set );
129    barrier( bs );
130  }
131
132  broadcast_test_fini();
133}
134
135static void call_tests_isr_disabled( size_t set_size,
136    const cpu_set_t *cpu_set, SMP_barrier_State *bs  )
137{
138  size_t i;
139
140  broadcast_test_init();
141
142  for (i = 0; i < RTEMS_ARRAY_SIZE( test_cases ); ++i) {
143    ISR_Level isr_level;
144
145    _ISR_Local_disable( isr_level );
146    barrier( bs );
147    ( *test_cases[ i ] )( set_size, cpu_set );
148    _ISR_Local_enable( isr_level );
149    barrier( bs );
150  }
151
152  broadcast_test_fini();
153}
154
155static void call_tests_with_thread_dispatch_disabled( size_t set_size,
156    const cpu_set_t *cpu_set, SMP_barrier_State *bs )
157{
158  size_t i;
159
160  broadcast_test_init();
161
162  for (i = 0; i < RTEMS_ARRAY_SIZE( test_cases ); ++i) {
163    Per_CPU_Control *cpu_self;
164
165    cpu_self = _Thread_Dispatch_disable();
166    barrier( bs );
167    ( *test_cases[ i ] )( set_size, cpu_set );
168    barrier( bs );
169    _Thread_Dispatch_enable( cpu_self );
170  }
171
172  broadcast_test_fini();
173}
174
175static void cmlog(  const char* str )
176{
177  if ( rtems_scheduler_get_processor() == 0 )
178    printf( "%s", str );
179}
180
181static void all_tests( void )
182{
183  uint32_t cpu_count = rtems_scheduler_get_processor_maximum();
184  size_t set_size = CPU_ALLOC_SIZE( cpu_count );
185  cpu_set_t *cpu_set = CPU_ALLOC( cpu_count );
186  SMP_barrier_State bs = SMP_BARRIER_STATE_INITIALIZER;
187
188  /* Send message to all available CPUs */
189  CPU_FILL_S( set_size, cpu_set );
190
191  /* Call test cases */
192  cmlog( "Calling test cases. " );
193  call_tests( set_size, cpu_set, &bs );
194  cmlog( "Done!\n");
195
196  /* Call test cases with ISR disabled */
197  cmlog( "Calling test cases with ISR disabled. " );
198  call_tests_isr_disabled( set_size, cpu_set, &bs );
199  cmlog( "Done!\n" );
200
201  /* Call test cases with thread dispatch disabled */
202  cmlog( "Calling test cases with thread_dispatch_disabled. ");
203  call_tests_with_thread_dispatch_disabled( set_size, cpu_set, &bs );
204  cmlog( "Done!\n");
205
206  /* Done. Free up memory. */
207  _SMP_barrier_Wait( &ctx.barrier, &bs, cpu_count);
208  CPU_FREE( cpu_set );
209}
210
211static void worker_task(rtems_task_argument arg)
212{
213  rtems_status_code sc;
214
215  all_tests();
216
217  sc = rtems_task_suspend(RTEMS_SELF);
218  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
219}
220
221static void test_smp_cache_manager( void )
222{
223  rtems_status_code sc;
224  size_t worker_index;
225  uint32_t cpu_count = rtems_scheduler_get_processor_maximum();
226
227  for (worker_index = 1; worker_index < cpu_count; ++worker_index) {
228    rtems_id worker_id;
229
230    sc = rtems_task_create(
231      rtems_build_name('W', 'R', 'K', '0'+worker_index),
232      WORKER_PRIORITY,
233      RTEMS_MINIMUM_STACK_SIZE,
234      RTEMS_DEFAULT_MODES,
235      RTEMS_DEFAULT_ATTRIBUTES,
236      &worker_id
237    );
238    rtems_test_assert( sc == RTEMS_SUCCESSFUL );
239
240    sc = rtems_task_start( worker_id, worker_task, 0 );
241    rtems_test_assert( sc == RTEMS_SUCCESSFUL );
242  }
243
244  all_tests();
245}
246
247
248static void Init(rtems_task_argument arg)
249{
250  TEST_BEGIN();
251
252  test_smp_cache_manager();
253
254  TEST_END();
255  rtems_test_exit(0);
256}
257
258static void fatal_extension(
259  rtems_fatal_source source,
260  bool always_set_to_false,
261  rtems_fatal_code error
262)
263{
264  uint32_t self = rtems_scheduler_get_processor();
265
266  if (source == RTEMS_FATAL_SOURCE_EXCEPTION && ctx.do_longjmp[self]) {
267    _ISR_Set_level(0);
268    longjmp(ctx.instruction_invalidate_return_context[self], 1);
269  }
270}
271
272#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
273#define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
274
275#define CONFIGURE_MAXIMUM_PROCESSORS CPU_COUNT
276
277#define CONFIGURE_MAXIMUM_TASKS CPU_COUNT
278
279#define CONFIGURE_MAXIMUM_TIMERS 1
280
281#define CONFIGURE_INITIAL_EXTENSIONS \
282  { .fatal = fatal_extension }, \
283  RTEMS_TEST_INITIAL_EXTENSION
284
285#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
286
287#define CONFIGURE_INIT
288
289#include <rtems/confdefs.h>
Note: See TracBrowser for help on using the repository browser.