source: rtems/testsuites/tmtests/tmcontext01/init.c @ 8d30713d

4.115
Last change on this file since 8d30713d was 8d30713d, checked in by Sebastian Huber <sebastian.huber@…>, on 09/05/14 at 11:33:57

tmtests/tmcontext01: Improve cache dirty function

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