source: rtems/testsuites/smptests/smpcache01/init.c @ 9b91c84

Last change on this file since 9b91c84 was 9b91c84, checked in by Sebastian Huber <sebastian.huber@…>, on Apr 5, 2017 at 9:29:02 AM

smpcache01: Fix test to run on QorIQ T4240

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