source: rtems/testsuites/tmtests/tmcontext01/init.c @ c4b8b147

5
Last change on this file since c4b8b147 was c4b8b147, checked in by Sebastian Huber <sebastian.huber@…>, on 11/03/17 at 07:35:38

tests: Use simple console driver

Update #3170.
Update #3199.

  • Property mode set to 100644
File size: 5.7 KB
Line 
1/*
2 * Copyright (c) 2014, 2017 embedded brains GmbH.  All rights reserved.
3 *
4 *  embedded brains GmbH
5 *  Dornierstr. 4
6 *  82178 Puchheim
7 *  Germany
8 *  <rtems@embedded-brains.de>
9 *
10 * The license and distribution terms for this file may be
11 * found in the file LICENSE in this distribution or at
12 * http://www.rtems.org/license/LICENSE.
13 */
14
15#ifdef HAVE_CONFIG_H
16  #include "config.h"
17#endif
18
19#include <rtems/counter.h>
20#include <rtems.h>
21
22#include <stdio.h>
23#include <stdlib.h>
24#include <inttypes.h>
25#include <alloca.h>
26
27#include "tmacros.h"
28
29#define FUNCTION_LEVELS 16
30
31#define SAMPLES 123
32
33#define CPU_COUNT 32
34
35const char rtems_test_name[] = "TMCONTEXT 1";
36
37static rtems_counter_ticks t[SAMPLES];
38
39static volatile int prevent_optimization;
40
41static size_t cache_line_size;
42
43static size_t data_size;
44
45static volatile int *main_data;
46
47static Context_Control ctx;
48
49static int dirty_data_cache(volatile int *data, size_t n, size_t clsz, int j)
50{
51  size_t m = n / sizeof(*data);
52  size_t k = clsz / sizeof(*data);
53  size_t i;
54
55  for (i = 0; i < m; i += k) {
56    data[i] = i + j;
57  }
58
59  return i + j;
60}
61
62static int call_at_level(
63  int start,
64  int fl,
65  int s,
66  bool dirty
67)
68{
69  int prevent_optimization;;
70
71  prevent_optimization = start + fl;
72
73  if (fl == start) {
74    /*
75     * Some architectures like the SPARC have register windows.  A side-effect
76     * of this context switch is that we start with a fresh window set.  On
77     * architectures like ARM or PowerPC this context switch has no effect.
78     */
79    _Context_Switch(&ctx, &ctx);
80  }
81
82  if (fl > 0) {
83    call_at_level(
84      start,
85      fl - 1,
86      s,
87      dirty
88    );
89  } else {
90    char *volatile space;
91    rtems_counter_ticks a;
92    rtems_counter_ticks b;
93
94    if (dirty) {
95      dirty_data_cache(main_data, data_size, cache_line_size, fl);
96      rtems_cache_invalidate_entire_instruction();
97    }
98
99    a = rtems_counter_read();
100
101    /* Ensure that we use an untouched stack area */
102    space = alloca(1024);
103    (void) space;
104
105    _Context_Switch(&ctx, &ctx);
106
107    b = rtems_counter_read();
108    t[s] = rtems_counter_difference(b, a);
109  }
110
111  return prevent_optimization;
112}
113
114static void load_task(rtems_task_argument arg)
115{
116  volatile int *load_data = (volatile int *) arg;
117  size_t n = data_size;
118  size_t clsz = cache_line_size;
119  int j = (int) rtems_get_current_processor();
120
121  while (true) {
122    j = dirty_data_cache(load_data, n, clsz, j);
123  }
124}
125
126static int cmp(const void *ap, const void *bp)
127{
128  const rtems_counter_ticks *a = ap;
129  const rtems_counter_ticks *b = bp;
130
131  return *a - *b;
132}
133
134static void sort_t(void)
135{
136  qsort(&t[0], SAMPLES, sizeof(t[0]), cmp);
137}
138
139static void test_by_function_level(int fl, bool dirty)
140{
141  RTEMS_INTERRUPT_LOCK_DECLARE(, lock)
142  rtems_interrupt_lock_context lock_context;
143  int s;
144  uint64_t min;
145  uint64_t q1;
146  uint64_t q2;
147  uint64_t q3;
148  uint64_t max;
149
150  fl += prevent_optimization;
151
152  rtems_interrupt_lock_initialize(&lock, "test");
153  rtems_interrupt_lock_acquire(&lock, &lock_context);
154
155  for (s = 0; s < SAMPLES; ++s) {
156    call_at_level(fl, fl, s, dirty);
157  }
158
159  rtems_interrupt_lock_release(&lock, &lock_context);
160  rtems_interrupt_lock_destroy(&lock);
161
162  sort_t();
163
164  min = t[0];
165  q1 = t[(1 * SAMPLES) / 4];
166  q2 = t[SAMPLES / 2];
167  q3 = t[(3 * SAMPLES) / 4];
168  max = t[SAMPLES - 1];
169
170  printf(
171    "    <Sample functionNestLevel=\"%i\">\n"
172    "      <Min unit=\"ns\">%" PRIu64 "</Min>"
173      "<Q1 unit=\"ns\">%" PRIu64 "</Q1>"
174      "<Q2 unit=\"ns\">%" PRIu64 "</Q2>"
175      "<Q3 unit=\"ns\">%" PRIu64 "</Q3>"
176      "<Max unit=\"ns\">%" PRIu64 "</Max>\n"
177    "    </Sample>\n",
178    fl,
179    rtems_counter_ticks_to_nanoseconds(min),
180    rtems_counter_ticks_to_nanoseconds(q1),
181    rtems_counter_ticks_to_nanoseconds(q2),
182    rtems_counter_ticks_to_nanoseconds(q3),
183    rtems_counter_ticks_to_nanoseconds(max)
184  );
185}
186
187static void test(bool dirty, uint32_t load)
188{
189  int fl;
190
191  printf(
192    "  <ContextSwitchTest environment=\"%s\"",
193    dirty ? "dirty" : "normal"
194  );
195
196  if (load > 0) {
197    printf(" load=\"%" PRIu32 "\"", load);
198  }
199
200  printf(">\n");
201
202  for (fl = 0; fl < FUNCTION_LEVELS; ++fl) {
203    test_by_function_level(fl, dirty);
204  }
205
206  printf("  </ContextSwitchTest>\n");
207}
208
209static void Init(rtems_task_argument arg)
210{
211  uint32_t load = 0;
212
213  TEST_BEGIN();
214
215  printf("<Test>\n");
216
217  cache_line_size = rtems_cache_get_data_line_size();
218  if (cache_line_size == 0) {
219    cache_line_size = 32;
220  }
221
222  data_size = rtems_cache_get_data_cache_size(0);
223  if (data_size == 0) {
224    data_size = cache_line_size;
225  }
226
227  main_data = malloc(data_size);
228  rtems_test_assert(main_data != NULL);
229
230  test(false, load);
231  test(true, load);
232
233  for (load = 1; load < rtems_get_processor_count(); ++load) {
234    rtems_status_code sc;
235    rtems_id id;
236    volatile int *load_data = NULL;
237
238    load_data = malloc(data_size);
239    if (load_data == NULL) {
240      load_data = main_data;
241    }
242
243    sc = rtems_task_create(
244      rtems_build_name('L', 'O', 'A', 'D'),
245      1,
246      RTEMS_MINIMUM_STACK_SIZE,
247      RTEMS_DEFAULT_MODES,
248      RTEMS_DEFAULT_ATTRIBUTES,
249      &id
250    );
251    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
252
253    sc = rtems_task_start(id, load_task, (rtems_task_argument) load_data);
254    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
255
256    test(true, load);
257  }
258
259  printf("</Test>\n");
260
261  TEST_END();
262  rtems_test_exit(0);
263}
264
265/*
266 * Do not use a clock driver, since this will disturb the test in the "normal"
267 * environment.
268 */
269#define CONFIGURE_APPLICATION_DOES_NOT_NEED_CLOCK_DRIVER
270
271#define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
272
273#define CONFIGURE_MAXIMUM_TASKS (1 + CPU_COUNT)
274
275#define CONFIGURE_INIT_TASK_STACK_SIZE (32 * 1024)
276
277#define CONFIGURE_MAXIMUM_PROCESSORS CPU_COUNT
278
279#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
280
281#define CONFIGURE_INIT
282
283#include <rtems/confdefs.h>
Note: See TracBrowser for help on using the repository browser.