File indexing completed on 2025-05-11 08:24:50
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028 #ifdef HAVE_CONFIG_H
0029 #include "config.h"
0030 #endif
0031
0032 #include <rtems/counter.h>
0033 #include <rtems.h>
0034
0035 #include <stdio.h>
0036 #include <stdlib.h>
0037 #include <inttypes.h>
0038 #include <alloca.h>
0039
0040 #include "tmacros.h"
0041
0042 #define FUNCTION_LEVELS 16
0043
0044 #define SAMPLES 123
0045
0046 #define CPU_COUNT 32
0047
0048 const char rtems_test_name[] = "TMCONTEXT 1";
0049
0050 static rtems_counter_ticks t[SAMPLES];
0051
0052 static size_t cache_line_size;
0053
0054 static size_t data_size;
0055
0056 static volatile int *main_data;
0057
0058 static Context_Control ctx;
0059
0060 static int dirty_data_cache(volatile int *data, size_t n, size_t clsz, int j)
0061 {
0062 size_t m = n / sizeof(*data);
0063 size_t k = clsz / sizeof(*data);
0064 size_t i;
0065
0066 for (i = 0; i < m; i += k) {
0067 data[i] = i + j;
0068 }
0069
0070 return i + j;
0071 }
0072
0073 static __attribute__((__noipa__)) void call_at_level(
0074 int start,
0075 int fl,
0076 int s
0077 )
0078 {
0079 #if defined(__sparc__)
0080 if (fl == start) {
0081
0082 __asm__ volatile ("ta 3" : : : "memory");
0083 }
0084 #endif
0085
0086 if (fl > 0) {
0087 call_at_level(
0088 start,
0089 fl - 1,
0090 s
0091 );
0092 __asm__ volatile ("" : : : "memory");
0093 } else {
0094 char *volatile space;
0095 rtems_counter_ticks a;
0096 rtems_counter_ticks b;
0097
0098 a = rtems_counter_read();
0099
0100
0101 space = alloca(1024);
0102 (void) space;
0103
0104 _Context_Switch(&ctx, &ctx);
0105
0106 b = rtems_counter_read();
0107 t[s] = rtems_counter_difference(b, a);
0108 }
0109 }
0110
0111 static void load_task(rtems_task_argument arg)
0112 {
0113 volatile int *load_data = (volatile int *) arg;
0114 size_t n = data_size;
0115 size_t clsz = cache_line_size;
0116 int j = (int) rtems_scheduler_get_processor();
0117
0118 while (true) {
0119 j = dirty_data_cache(load_data, n, clsz, j);
0120 }
0121 }
0122
0123 static int cmp(const void *ap, const void *bp)
0124 {
0125 const rtems_counter_ticks *a = ap;
0126 const rtems_counter_ticks *b = bp;
0127
0128 return *a - *b;
0129 }
0130
0131 static void sort_t(void)
0132 {
0133 qsort(&t[0], SAMPLES, sizeof(t[0]), cmp);
0134 }
0135
0136 static __attribute__((__noipa__)) void test_by_function_level(int fl, bool dirty)
0137 {
0138 RTEMS_INTERRUPT_LOCK_DECLARE(, lock)
0139 rtems_interrupt_lock_context lock_context;
0140 int s;
0141 uint64_t min;
0142 uint64_t q1;
0143 uint64_t q2;
0144 uint64_t q3;
0145 uint64_t max;
0146
0147 rtems_interrupt_lock_initialize(&lock, "test");
0148 rtems_interrupt_lock_acquire(&lock, &lock_context);
0149
0150 for (s = 0; s < SAMPLES; ++s) {
0151 if (dirty) {
0152 dirty_data_cache(main_data, data_size, cache_line_size, fl);
0153 rtems_cache_invalidate_entire_instruction();
0154 }
0155
0156 call_at_level(fl, fl, s);
0157 }
0158
0159 rtems_interrupt_lock_release(&lock, &lock_context);
0160 rtems_interrupt_lock_destroy(&lock);
0161
0162 sort_t();
0163
0164 min = t[0];
0165 q1 = t[(1 * SAMPLES) / 4];
0166 q2 = t[SAMPLES / 2];
0167 q3 = t[(3 * SAMPLES) / 4];
0168 max = t[SAMPLES - 1];
0169
0170 printf(
0171 "%s\n [%" PRIu64 ", %" PRIu64 ", %" PRIu64 ", %" PRIu64 ", %" PRIu64 "]",
0172 fl == 0 ? "" : ",",
0173 rtems_counter_ticks_to_nanoseconds(min),
0174 rtems_counter_ticks_to_nanoseconds(q1),
0175 rtems_counter_ticks_to_nanoseconds(q2),
0176 rtems_counter_ticks_to_nanoseconds(q3),
0177 rtems_counter_ticks_to_nanoseconds(max)
0178 );
0179 }
0180
0181 static void test(bool first, bool dirty, uint32_t load)
0182 {
0183 int fl;
0184
0185 printf(
0186 "\n %s{\n"
0187 " \"environment\": \"",
0188 first ? "" : "}, "
0189 );
0190
0191 if (dirty) {
0192 if (load > 0) {
0193 printf("Load/%" PRIu32 "", load);
0194 } else {
0195 printf("DirtyCache");
0196 }
0197 } else {
0198 printf("HotCache");
0199 }
0200
0201 printf(
0202 "\",\n"
0203 " \"stats-by-function-nest-level\": ["
0204 );
0205
0206 for (fl = 0; fl < FUNCTION_LEVELS; ++fl) {
0207 test_by_function_level(fl, dirty);
0208 }
0209
0210 printf(
0211 "\n ]"
0212 );
0213 }
0214
0215 static void Init(rtems_task_argument arg)
0216 {
0217 uint32_t load = 0;
0218
0219 TEST_BEGIN();
0220
0221 printf("*** BEGIN OF JSON DATA ***\n[");
0222
0223 cache_line_size = rtems_cache_get_data_line_size();
0224 if (cache_line_size == 0) {
0225 cache_line_size = 32;
0226 }
0227
0228 data_size = rtems_cache_get_data_cache_size(0);
0229 if (data_size == 0) {
0230 data_size = cache_line_size;
0231 }
0232
0233 main_data = malloc(data_size);
0234 rtems_test_assert(main_data != NULL);
0235
0236 test(true, false, load);
0237 test(false, true, load);
0238
0239 for (load = 1; load < rtems_scheduler_get_processor_maximum(); ++load) {
0240 rtems_status_code sc;
0241 rtems_id id;
0242 volatile int *load_data = NULL;
0243
0244 load_data = malloc(data_size);
0245 if (load_data == NULL) {
0246 load_data = main_data;
0247 }
0248
0249 sc = rtems_task_create(
0250 rtems_build_name('L', 'O', 'A', 'D'),
0251 1,
0252 RTEMS_MINIMUM_STACK_SIZE,
0253 RTEMS_DEFAULT_MODES,
0254 RTEMS_DEFAULT_ATTRIBUTES,
0255 &id
0256 );
0257 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0258
0259 sc = rtems_task_start(id, load_task, (rtems_task_argument) load_data);
0260 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0261
0262 test(false, true, load);
0263 }
0264
0265 printf("\n }\n]\n*** END OF JSON DATA ***\n");
0266
0267 TEST_END();
0268 rtems_test_exit(0);
0269 }
0270
0271
0272
0273
0274
0275 #define CONFIGURE_APPLICATION_DOES_NOT_NEED_CLOCK_DRIVER
0276
0277 #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
0278
0279 #define CONFIGURE_MAXIMUM_TASKS (1 + CPU_COUNT)
0280
0281 #define CONFIGURE_INIT_TASK_STACK_SIZE (32 * 1024)
0282
0283 #define CONFIGURE_MAXIMUM_PROCESSORS CPU_COUNT
0284
0285 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
0286
0287 #define CONFIGURE_INIT
0288
0289 #include <rtems/confdefs.h>