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

Last change on this file was c8acc75, checked in by Sebastian Huber <sebastian.huber@…>, on 01/09/24 at 09:27:39

tmcontext01: Convert to JSON data

This avoids a dependency on the non-standard libxml2 module.

  • Property mode set to 100644
File size: 6.5 KB
Line 
1/* SPDX-License-Identifier: BSD-2-Clause */
2
3/*
4 * Copyright (C) 2014, 2017 embedded brains GmbH & Co. KG
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#ifdef HAVE_CONFIG_H
29#include "config.h"
30#endif
31
32#include <rtems/counter.h>
33#include <rtems.h>
34
35#include <stdio.h>
36#include <stdlib.h>
37#include <inttypes.h>
38#include <alloca.h>
39
40#include "tmacros.h"
41
42#define FUNCTION_LEVELS 16
43
44#define SAMPLES 123
45
46#define CPU_COUNT 32
47
48const char rtems_test_name[] = "TMCONTEXT 1";
49
50static rtems_counter_ticks t[SAMPLES];
51
52static size_t cache_line_size;
53
54static size_t data_size;
55
56static volatile int *main_data;
57
58static Context_Control ctx;
59
60static int dirty_data_cache(volatile int *data, size_t n, size_t clsz, int j)
61{
62  size_t m = n / sizeof(*data);
63  size_t k = clsz / sizeof(*data);
64  size_t i;
65
66  for (i = 0; i < m; i += k) {
67    data[i] = i + j;
68  }
69
70  return i + j;
71}
72
73static __attribute__((__noipa__)) void call_at_level(
74  int start,
75  int fl,
76  int s
77)
78{
79#if defined(__sparc__)
80  if (fl == start) {
81    /* Flush register windows */
82    __asm__ volatile ("ta 3" : : : "memory");
83  }
84#endif
85
86  if (fl > 0) {
87    call_at_level(
88      start,
89      fl - 1,
90      s
91    );
92    __asm__ volatile ("" : : : "memory");
93  } else {
94    char *volatile space;
95    rtems_counter_ticks a;
96    rtems_counter_ticks b;
97
98    a = rtems_counter_read();
99
100    /* Ensure that we use an untouched stack area */
101    space = alloca(1024);
102    (void) space;
103
104    _Context_Switch(&ctx, &ctx);
105
106    b = rtems_counter_read();
107    t[s] = rtems_counter_difference(b, a);
108  }
109}
110
111static void load_task(rtems_task_argument arg)
112{
113  volatile int *load_data = (volatile int *) arg;
114  size_t n = data_size;
115  size_t clsz = cache_line_size;
116  int j = (int) rtems_scheduler_get_processor();
117
118  while (true) {
119    j = dirty_data_cache(load_data, n, clsz, j);
120  }
121}
122
123static int cmp(const void *ap, const void *bp)
124{
125  const rtems_counter_ticks *a = ap;
126  const rtems_counter_ticks *b = bp;
127
128  return *a - *b;
129}
130
131static void sort_t(void)
132{
133  qsort(&t[0], SAMPLES, sizeof(t[0]), cmp);
134}
135
136static __attribute__((__noipa__)) void test_by_function_level(int fl, bool dirty)
137{
138  RTEMS_INTERRUPT_LOCK_DECLARE(, lock)
139  rtems_interrupt_lock_context lock_context;
140  int s;
141  uint64_t min;
142  uint64_t q1;
143  uint64_t q2;
144  uint64_t q3;
145  uint64_t max;
146
147  rtems_interrupt_lock_initialize(&lock, "test");
148  rtems_interrupt_lock_acquire(&lock, &lock_context);
149
150  for (s = 0; s < SAMPLES; ++s) {
151    if (dirty) {
152      dirty_data_cache(main_data, data_size, cache_line_size, fl);
153      rtems_cache_invalidate_entire_instruction();
154    }
155
156    call_at_level(fl, fl, s);
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    "%s\n      [%" PRIu64 ", %" PRIu64 ", %" PRIu64 ", %" PRIu64 ", %" PRIu64 "]",
172    fl == 0 ? "" : ",",
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 first, bool dirty, uint32_t load)
182{
183  int fl;
184
185  printf(
186    "\n  %s{\n"
187    "    \"environment\": \"",
188    first ? "" : "}, "
189  );
190
191  if (dirty) {
192    if (load > 0) {
193      printf("Load/%" PRIu32 "", load);
194    } else {
195      printf("DirtyCache");
196    }
197  } else {
198    printf("HotCache");
199  }
200
201  printf(
202    "\",\n"
203    "    \"stats-by-function-nest-level\": ["
204  );
205
206  for (fl = 0; fl < FUNCTION_LEVELS; ++fl) {
207    test_by_function_level(fl, dirty);
208  }
209
210  printf(
211    "\n    ]"
212  );
213}
214
215static void Init(rtems_task_argument arg)
216{
217  uint32_t load = 0;
218
219  TEST_BEGIN();
220
221  printf("*** BEGIN OF JSON DATA ***\n[");
222
223  cache_line_size = rtems_cache_get_data_line_size();
224  if (cache_line_size == 0) {
225    cache_line_size = 32;
226  }
227
228  data_size = rtems_cache_get_data_cache_size(0);
229  if (data_size == 0) {
230    data_size = cache_line_size;
231  }
232
233  main_data = malloc(data_size);
234  rtems_test_assert(main_data != NULL);
235
236  test(true, false, load);
237  test(false, true, load);
238
239  for (load = 1; load < rtems_scheduler_get_processor_maximum(); ++load) {
240    rtems_status_code sc;
241    rtems_id id;
242    volatile int *load_data = NULL;
243
244    load_data = malloc(data_size);
245    if (load_data == NULL) {
246      load_data = main_data;
247    }
248
249    sc = rtems_task_create(
250      rtems_build_name('L', 'O', 'A', 'D'),
251      1,
252      RTEMS_MINIMUM_STACK_SIZE,
253      RTEMS_DEFAULT_MODES,
254      RTEMS_DEFAULT_ATTRIBUTES,
255      &id
256    );
257    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
258
259    sc = rtems_task_start(id, load_task, (rtems_task_argument) load_data);
260    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
261
262    test(false, true, load);
263  }
264
265  printf("\n  }\n]\n*** END OF JSON DATA ***\n");
266
267  TEST_END();
268  rtems_test_exit(0);
269}
270
271/*
272 * Do not use a clock driver, since this will disturb the test in the "normal"
273 * environment.
274 */
275#define CONFIGURE_APPLICATION_DOES_NOT_NEED_CLOCK_DRIVER
276
277#define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
278
279#define CONFIGURE_MAXIMUM_TASKS (1 + CPU_COUNT)
280
281#define CONFIGURE_INIT_TASK_STACK_SIZE (32 * 1024)
282
283#define CONFIGURE_MAXIMUM_PROCESSORS CPU_COUNT
284
285#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
286
287#define CONFIGURE_INIT
288
289#include <rtems/confdefs.h>
Note: See TracBrowser for help on using the repository browser.