source: rtems/testsuites/tmtests/tmcontext01/init.c @ 6fd5b4e

4.115
Last change on this file since 6fd5b4e was d0061287, checked in by Sebastian Huber <sebastian.huber@…>, on Mar 5, 2015 at 9:11:23 AM

tests: Fix warnings

  • Property mode set to 100644
File size: 5.9 KB
Line 
1/*
2 * Copyright (c) 2014 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 bool always_true = true;
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 prevent_opt_func(int m, int n)
63{
64  if (m == 0) {
65    return n + 1;
66  } else if (m > 0 && n == 0) {
67    return prevent_opt_func(m - 1, 1);
68  } else {
69    return prevent_opt_func(m - 1, prevent_opt_func(m, n - 1));
70  }
71}
72
73static int call_at_level(int start, int fl, int s, bool dirty)
74{
75  if (fl == start) {
76    /*
77     * Some architectures like the SPARC have register windows.  A side-effect
78     * of this context switch is that we start with a fresh window set.  On
79     * architectures like ARM or PowerPC this context switch has no effect.
80     */
81    _Context_Switch(&ctx, &ctx);
82  }
83
84  if (fl > 0) {
85    if (always_true) {
86      return call_at_level(start, fl - 1, s, dirty);
87    } else {
88      return prevent_opt_func(fl - 1, fl - 2);
89    }
90  } else {
91    char *volatile space;
92    rtems_counter_ticks a;
93    rtems_counter_ticks b;
94
95    if (dirty) {
96      dirty_data_cache(main_data, data_size, cache_line_size, fl);
97      rtems_cache_invalidate_entire_instruction();
98    }
99
100    a = rtems_counter_read();
101
102    /* Ensure that we use an untouched stack area */
103    space = alloca(1024);
104    (void) space;
105
106    _Context_Switch(&ctx, &ctx);
107
108    b = rtems_counter_read();
109    t[s] = rtems_counter_difference(b, a);
110
111    return 0;
112  }
113}
114
115static void load_task(rtems_task_argument arg)
116{
117  volatile int *load_data = (volatile int *) arg;
118  size_t n = data_size;
119  size_t clsz = cache_line_size;
120  int j = (int) rtems_get_current_processor();
121
122  while (true) {
123    j = dirty_data_cache(load_data, n, clsz, j);
124  }
125}
126
127static int cmp(const void *ap, const void *bp)
128{
129  const rtems_counter_ticks *a = ap;
130  const rtems_counter_ticks *b = bp;
131
132  return *a - *b;
133}
134
135static void sort_t(void)
136{
137  qsort(&t[0], SAMPLES, sizeof(t[0]), cmp);
138}
139
140static void test_by_function_level(int fl, bool dirty)
141{
142  RTEMS_INTERRUPT_LOCK_DECLARE(, lock)
143  rtems_interrupt_lock_context lock_context;
144  int s;
145  uint64_t min;
146  uint64_t q1;
147  uint64_t q2;
148  uint64_t q3;
149  uint64_t max;
150
151  rtems_interrupt_lock_initialize(&lock, "test");
152  rtems_interrupt_lock_acquire(&lock, &lock_context);
153
154  for (s = 0; s < SAMPLES; ++s) {
155    call_at_level(fl, fl, s, dirty);
156  }
157
158  rtems_interrupt_lock_release(&lock, &lock_context);
159  rtems_interrupt_lock_destroy(&lock);
160
161  sort_t();
162
163  min = t[0];
164  q1 = t[(1 * SAMPLES) / 4];
165  q2 = t[SAMPLES / 2];
166  q3 = t[(3 * SAMPLES) / 4];
167  max = t[SAMPLES - 1];
168
169  printf(
170    "    <Sample functionNestLevel=\"%i\">\n"
171    "      <Min unit=\"ns\">%" PRIu64 "</Min>"
172      "<Q1 unit=\"ns\">%" PRIu64 "</Q1>"
173      "<Q2 unit=\"ns\">%" PRIu64 "</Q2>"
174      "<Q3 unit=\"ns\">%" PRIu64 "</Q3>"
175      "<Max unit=\"ns\">%" PRIu64 "</Max>\n"
176    "    </Sample>\n",
177    fl,
178    rtems_counter_ticks_to_nanoseconds(min),
179    rtems_counter_ticks_to_nanoseconds(q1),
180    rtems_counter_ticks_to_nanoseconds(q2),
181    rtems_counter_ticks_to_nanoseconds(q3),
182    rtems_counter_ticks_to_nanoseconds(max)
183  );
184}
185
186static void test(bool dirty, uint32_t load)
187{
188  int fl;
189
190  printf(
191    "  <ContextSwitchTest environment=\"%s\"",
192    dirty ? "dirty" : "normal"
193  );
194
195  if (load > 0) {
196    printf(" load=\"%" PRIu32 "\"", load);
197  }
198
199  printf(">\n");
200
201  for (fl = 0; fl < FUNCTION_LEVELS; ++fl) {
202    test_by_function_level(fl, dirty);
203  }
204
205  printf("  </ContextSwitchTest>\n");
206}
207
208static void Init(rtems_task_argument arg)
209{
210  uint32_t load = 0;
211
212  TEST_BEGIN();
213
214  printf("<Test>\n");
215
216  cache_line_size = rtems_cache_get_data_line_size();
217  if (cache_line_size == 0) {
218    cache_line_size = 32;
219  }
220
221  data_size = rtems_cache_get_data_cache_size(0);
222  if (data_size == 0) {
223    data_size = cache_line_size;
224  }
225
226  main_data = malloc(data_size);
227  rtems_test_assert(main_data != NULL);
228
229  test(false, load);
230  test(true, load);
231
232  for (load = 1; load < rtems_get_processor_count(); ++load) {
233    rtems_status_code sc;
234    rtems_id id;
235    volatile int *load_data = NULL;
236
237    load_data = malloc(data_size);
238    if (load_data == NULL) {
239      load_data = main_data;
240    }
241
242    sc = rtems_task_create(
243      rtems_build_name('L', 'O', 'A', 'D'),
244      1,
245      RTEMS_MINIMUM_STACK_SIZE,
246      RTEMS_DEFAULT_MODES,
247      RTEMS_DEFAULT_ATTRIBUTES,
248      &id
249    );
250    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
251
252    sc = rtems_task_start(id, load_task, (rtems_task_argument) load_data);
253    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
254
255    test(true, load);
256  }
257
258  printf("</Test>\n");
259
260  TEST_END();
261  rtems_test_exit(0);
262}
263
264/*
265 * Do not use a clock driver, since this will disturb the test in the "normal"
266 * environment.
267 */
268#define CONFIGURE_APPLICATION_DOES_NOT_NEED_CLOCK_DRIVER
269
270#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
271
272#define CONFIGURE_MAXIMUM_TASKS (1 + CPU_COUNT)
273
274#define CONFIGURE_INIT_TASK_STACK_SIZE (32 * 1024)
275
276#define CONFIGURE_SMP_APPLICATION
277
278#define CONFIGURE_SMP_MAXIMUM_PROCESSORS CPU_COUNT
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.