source: rtems/testsuites/smptests/smpcache01/init.c @ 03c9f24

5
Last change on this file since 03c9f24 was 03c9f24, checked in by Sebastian Huber <sebastian.huber@…>, on Apr 5, 2019 at 6:03:12 AM

rtems: Add rtems_scheduler_get_processor()

Add rtems_scheduler_get_processor() as a replacement for
rtems_get_current_processor(). The rtems_get_current_processor() is a
bit orphaned. Adopt it by the Scheduler Manager. This is in line with
the glibc sched_getcpu() function.

Deprecate rtems_get_current_processor().

Update #3731.

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