File indexing completed on 2025-05-11 08:24:22
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
0029
0030
0031
0032
0033
0034
0035
0036
0037 #ifdef HAVE_CONFIG_H
0038 #include "config.h"
0039 #endif
0040
0041 #include <rtems/profiling.h>
0042
0043 #ifdef RTEMS_PROFILING
0044
0045 #include <inttypes.h>
0046
0047 typedef struct {
0048 const rtems_printer *printer;
0049 uint32_t indentation_level;
0050 const char *indentation;
0051 int retval;
0052 } context;
0053
0054 static void update_retval(context *ctx, int rv)
0055 {
0056 if (rv > 0 && ctx->retval >= 0) {
0057 ctx->retval += rv;
0058 }
0059 }
0060
0061 static void indent(context *ctx, uint32_t indentation_level)
0062 {
0063 uint32_t n = ctx->indentation_level + indentation_level;
0064 uint32_t i;
0065
0066 for (i = 0; i < n; ++i) {
0067 int rv = rtems_printf(ctx->printer, "%s", ctx->indentation);
0068
0069 update_retval(ctx, rv);
0070 }
0071 }
0072
0073 static uint64_t arithmetic_mean(uint64_t total, uint64_t count)
0074 {
0075 return count != 0 ? total / count : 0;
0076 }
0077
0078 static void report_per_cpu(context *ctx, const rtems_profiling_per_cpu *per_cpu)
0079 {
0080 int rv;
0081
0082 indent(ctx, 1);
0083 rv = rtems_printf(
0084 ctx->printer,
0085 "<PerCPUProfilingReport processorIndex=\"%" PRIu32 "\">\n",
0086 per_cpu->processor_index
0087 );
0088 update_retval(ctx, rv);
0089
0090 indent(ctx, 2);
0091 rv = rtems_printf(
0092 ctx->printer,
0093 "<MaxThreadDispatchDisabledTime unit=\"ns\">%" PRIu32
0094 "</MaxThreadDispatchDisabledTime>\n",
0095 per_cpu->max_thread_dispatch_disabled_time
0096 );
0097 update_retval(ctx, rv);
0098
0099 indent(ctx, 2);
0100 rv = rtems_printf(
0101 ctx->printer,
0102 "<MeanThreadDispatchDisabledTime unit=\"ns\">%" PRIu64
0103 "</MeanThreadDispatchDisabledTime>\n",
0104 arithmetic_mean(
0105 per_cpu->total_thread_dispatch_disabled_time,
0106 per_cpu->thread_dispatch_disabled_count
0107 )
0108 );
0109 update_retval(ctx, rv);
0110
0111 indent(ctx, 2);
0112 rv = rtems_printf(
0113 ctx->printer,
0114 "<TotalThreadDispatchDisabledTime unit=\"ns\">%" PRIu64
0115 "</TotalThreadDispatchDisabledTime>\n",
0116 per_cpu->total_thread_dispatch_disabled_time
0117 );
0118 update_retval(ctx, rv);
0119
0120 indent(ctx, 2);
0121 rv = rtems_printf(
0122 ctx->printer,
0123 "<ThreadDispatchDisabledCount>%" PRIu64 "</ThreadDispatchDisabledCount>\n",
0124 per_cpu->thread_dispatch_disabled_count
0125 );
0126 update_retval(ctx, rv);
0127
0128 indent(ctx, 2);
0129 rv = rtems_printf(
0130 ctx->printer,
0131 "<MaxInterruptDelay unit=\"ns\">%" PRIu32 "</MaxInterruptDelay>\n",
0132 per_cpu->max_interrupt_delay
0133 );
0134 update_retval(ctx, rv);
0135
0136 indent(ctx, 2);
0137 rv = rtems_printf(
0138 ctx->printer,
0139 "<MaxInterruptTime unit=\"ns\">%" PRIu32
0140 "</MaxInterruptTime>\n",
0141 per_cpu->max_interrupt_time
0142 );
0143 update_retval(ctx, rv);
0144
0145 indent(ctx, 2);
0146 rv = rtems_printf(
0147 ctx->printer,
0148 "<MeanInterruptTime unit=\"ns\">%" PRIu64
0149 "</MeanInterruptTime>\n",
0150 arithmetic_mean(
0151 per_cpu->total_interrupt_time,
0152 per_cpu->interrupt_count
0153 )
0154 );
0155 update_retval(ctx, rv);
0156
0157 indent(ctx, 2);
0158 rv = rtems_printf(
0159 ctx->printer,
0160 "<TotalInterruptTime unit=\"ns\">%" PRIu64 "</TotalInterruptTime>\n",
0161 per_cpu->total_interrupt_time
0162 );
0163 update_retval(ctx, rv);
0164
0165 indent(ctx, 2);
0166 rv = rtems_printf(
0167 ctx->printer,
0168 "<InterruptCount>%" PRIu64 "</InterruptCount>\n",
0169 per_cpu->interrupt_count
0170 );
0171 update_retval(ctx, rv);
0172
0173 indent(ctx, 1);
0174 rv = rtems_printf(
0175 ctx->printer,
0176 "</PerCPUProfilingReport>\n"
0177 );
0178 update_retval(ctx, rv);
0179 }
0180
0181 static void report_smp_lock(context *ctx, const rtems_profiling_smp_lock *smp_lock)
0182 {
0183 int rv;
0184 uint32_t i;
0185
0186 indent(ctx, 1);
0187 rv = rtems_printf(
0188 ctx->printer,
0189 "<SMPLockProfilingReport name=\"%s\">\n",
0190 smp_lock->name
0191 );
0192 update_retval(ctx, rv);
0193
0194 indent(ctx, 2);
0195 rv = rtems_printf(
0196 ctx->printer,
0197 "<MaxAcquireTime unit=\"ns\">%" PRIu32 "</MaxAcquireTime>\n",
0198 smp_lock->max_acquire_time
0199 );
0200 update_retval(ctx, rv);
0201
0202 indent(ctx, 2);
0203 rv = rtems_printf(
0204 ctx->printer,
0205 "<MaxSectionTime unit=\"ns\">%" PRIu32 "</MaxSectionTime>\n",
0206 smp_lock->max_section_time
0207 );
0208 update_retval(ctx, rv);
0209
0210 indent(ctx, 2);
0211 rv = rtems_printf(
0212 ctx->printer,
0213 "<MeanAcquireTime unit=\"ns\">%" PRIu64
0214 "</MeanAcquireTime>\n",
0215 arithmetic_mean(
0216 smp_lock->total_acquire_time,
0217 smp_lock->usage_count
0218 )
0219 );
0220 update_retval(ctx, rv);
0221
0222 indent(ctx, 2);
0223 rv = rtems_printf(
0224 ctx->printer,
0225 "<MeanSectionTime unit=\"ns\">%" PRIu64
0226 "</MeanSectionTime>\n",
0227 arithmetic_mean(
0228 smp_lock->total_section_time,
0229 smp_lock->usage_count
0230 )
0231 );
0232 update_retval(ctx, rv);
0233
0234 indent(ctx, 2);
0235 rv = rtems_printf(
0236 ctx->printer,
0237 "<TotalAcquireTime unit=\"ns\">%" PRIu64 "</TotalAcquireTime>\n",
0238 smp_lock->total_acquire_time
0239 );
0240 update_retval(ctx, rv);
0241
0242 indent(ctx, 2);
0243 rv = rtems_printf(
0244 ctx->printer,
0245 "<TotalSectionTime unit=\"ns\">%" PRIu64 "</TotalSectionTime>\n",
0246 smp_lock->total_section_time
0247 );
0248 update_retval(ctx, rv);
0249
0250 indent(ctx, 2);
0251 rv = rtems_printf(
0252 ctx->printer,
0253 "<UsageCount>%" PRIu64 "</UsageCount>\n",
0254 smp_lock->usage_count
0255 );
0256 update_retval(ctx, rv);
0257
0258 for (i = 0; i < RTEMS_PROFILING_SMP_LOCK_CONTENTION_COUNTS; ++i) {
0259 indent(ctx, 2);
0260 rv = rtems_printf(
0261 ctx->printer,
0262 "<ContentionCount initialQueueLength=\"%" PRIu32 "\">%"
0263 PRIu64 "</ContentionCount>\n",
0264 i,
0265 smp_lock->contention_counts[i]
0266 );
0267 update_retval(ctx, rv);
0268 }
0269
0270 indent(ctx, 1);
0271 rv = rtems_printf(
0272 ctx->printer,
0273 "</SMPLockProfilingReport>\n"
0274 );
0275 update_retval(ctx, rv);
0276 }
0277
0278 static void report(void *arg, const rtems_profiling_data *data)
0279 {
0280 context *ctx = arg;
0281
0282 switch (data->header.type) {
0283 case RTEMS_PROFILING_PER_CPU:
0284 report_per_cpu(ctx, &data->per_cpu);
0285 break;
0286 case RTEMS_PROFILING_SMP_LOCK:
0287 report_smp_lock(ctx, &data->smp_lock);
0288 break;
0289 }
0290 }
0291
0292 #endif
0293
0294 int rtems_profiling_report_xml(
0295 const char *name,
0296 const rtems_printer *printer,
0297 uint32_t indentation_level,
0298 const char *indentation
0299 )
0300 {
0301 #ifdef RTEMS_PROFILING
0302 context ctx_instance = {
0303 .printer = printer,
0304 .indentation_level = indentation_level,
0305 .indentation = indentation,
0306 .retval = 0
0307 };
0308 context *ctx = &ctx_instance;
0309 int rv;
0310
0311 indent(ctx, 0);
0312 rv = rtems_printf(printer, "<ProfilingReport name=\"%s\">\n", name);
0313 update_retval(ctx, rv);
0314
0315 rtems_profiling_iterate(report, ctx);
0316
0317 indent(ctx, 0);
0318 rv = rtems_printf(printer, "</ProfilingReport>\n");
0319 update_retval(ctx, rv);
0320
0321 return ctx->retval;
0322 #else
0323 (void) name;
0324 (void) printer;
0325 (void) indentation_level;
0326 (void) indentation;
0327
0328 return 0;
0329 #endif
0330 }