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

5
Last change on this file since df8d7bd7 was df8d7bd7, checked in by Sebastian Huber <sebastian.huber@…>, on 04/09/19 at 08:58:35

score: Use processor mask in _SMP_Multicast_action

Processor_mask is the internal data type to deal with processor sets.

  • Property mode set to 100644
File size: 5.7 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    ISR_Level isr_level;
130
131    _ISR_Local_disable( isr_level );
132    barrier( bs );
133    ( *test_cases[ i ] )();
134    _ISR_Local_enable( isr_level );
135    barrier( bs );
136  }
137
138  broadcast_test_fini();
139}
140
141static void call_tests_with_thread_dispatch_disabled( SMP_barrier_State *bs )
142{
143  size_t i;
144
145  broadcast_test_init();
146
147  for (i = 0; i < RTEMS_ARRAY_SIZE( test_cases ); ++i) {
148    Per_CPU_Control *cpu_self;
149
150    cpu_self = _Thread_Dispatch_disable();
151    barrier( bs );
152    ( *test_cases[ i ] )();
153    barrier( bs );
154    _Thread_Dispatch_enable( cpu_self );
155  }
156
157  broadcast_test_fini();
158}
159
160static void cmlog(  const char* str )
161{
162  if ( rtems_scheduler_get_processor() == 0 )
163    printf( "%s", str );
164}
165
166static void all_tests( void )
167{
168  SMP_barrier_State bs = SMP_BARRIER_STATE_INITIALIZER;
169
170  /* Call test cases */
171  cmlog( "Calling test cases. " );
172  call_tests( &bs );
173  cmlog( "Done!\n");
174
175  /* Call test cases with ISR disabled */
176  cmlog( "Calling test cases with ISR disabled. " );
177  call_tests_isr_disabled( &bs );
178  cmlog( "Done!\n" );
179
180  /* Call test cases with thread dispatch disabled */
181  cmlog( "Calling test cases with thread_dispatch_disabled. ");
182  call_tests_with_thread_dispatch_disabled( &bs );
183  cmlog( "Done!\n");
184
185  /* Done. Free up memory. */
186  _SMP_barrier_Wait(
187    &ctx.barrier,
188    &bs,
189    rtems_scheduler_get_processor_maximum()
190  );
191}
192
193static void worker_task(rtems_task_argument arg)
194{
195  rtems_status_code sc;
196
197  all_tests();
198
199  sc = rtems_task_suspend(RTEMS_SELF);
200  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
201}
202
203static void test_smp_cache_manager( void )
204{
205  rtems_status_code sc;
206  size_t worker_index;
207  uint32_t cpu_count = rtems_scheduler_get_processor_maximum();
208
209  for (worker_index = 1; worker_index < cpu_count; ++worker_index) {
210    rtems_id worker_id;
211
212    sc = rtems_task_create(
213      rtems_build_name('W', 'R', 'K', '0'+worker_index),
214      WORKER_PRIORITY,
215      RTEMS_MINIMUM_STACK_SIZE,
216      RTEMS_DEFAULT_MODES,
217      RTEMS_DEFAULT_ATTRIBUTES,
218      &worker_id
219    );
220    rtems_test_assert( sc == RTEMS_SUCCESSFUL );
221
222    sc = rtems_task_start( worker_id, worker_task, 0 );
223    rtems_test_assert( sc == RTEMS_SUCCESSFUL );
224  }
225
226  all_tests();
227}
228
229
230static void Init(rtems_task_argument arg)
231{
232  TEST_BEGIN();
233
234  test_smp_cache_manager();
235
236  TEST_END();
237  rtems_test_exit(0);
238}
239
240static void fatal_extension(
241  rtems_fatal_source source,
242  bool always_set_to_false,
243  rtems_fatal_code error
244)
245{
246  uint32_t self = rtems_scheduler_get_processor();
247
248  if (source == RTEMS_FATAL_SOURCE_EXCEPTION && ctx.do_longjmp[self]) {
249    _ISR_Set_level(0);
250    longjmp(ctx.instruction_invalidate_return_context[self], 1);
251  }
252}
253
254#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
255#define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
256
257#define CONFIGURE_MAXIMUM_PROCESSORS CPU_COUNT
258
259#define CONFIGURE_MAXIMUM_TASKS CPU_COUNT
260
261#define CONFIGURE_MAXIMUM_TIMERS 1
262
263#define CONFIGURE_INITIAL_EXTENSIONS \
264  { .fatal = fatal_extension }, \
265  RTEMS_TEST_INITIAL_EXTENSION
266
267#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
268
269#define CONFIGURE_INIT
270
271#include <rtems/confdefs.h>
Note: See TracBrowser for help on using the repository browser.