source: rtems/testsuites/tmtests/tmcontext01/init.c @ 28779c7

4.11
Last change on this file since 28779c7 was 28779c7, checked in by Sebastian Huber <sebastian.huber@…>, on Mar 7, 2014 at 11:53:41 AM

score: Add function to destroy SMP locks

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