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

4.115
Last change on this file since a75242eb was a75242eb, checked in by Sebastian Huber <sebastian.huber@…>, on 03/25/14 at 13:15:52

tmtests/tmcontext01: Use <rtems/test.h>

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