Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:22

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSAPIProfiling
0007  *
0008  * @brief This source file contains the implementation of
0009  *   rtems_profiling_report_xml().
0010  */
0011 
0012 /*
0013  * Copyright (c) 2014 embedded brains GmbH & Co. KG
0014  *
0015  * Redistribution and use in source and binary forms, with or without
0016  * modification, are permitted provided that the following conditions
0017  * are met:
0018  * 1. Redistributions of source code must retain the above copyright
0019  *    notice, this list of conditions and the following disclaimer.
0020  * 2. Redistributions in binary form must reproduce the above copyright
0021  *    notice, this list of conditions and the following disclaimer in the
0022  *    documentation and/or other materials provided with the distribution.
0023  *
0024  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0025  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0026  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0027  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0028  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0029  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0030  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0031  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0032  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0033  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0034  * POSSIBILITY OF SUCH DAMAGE.
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 /* RTEMS_PROFILING */
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 /* RTEMS_PROFILING */
0323   (void) name;
0324   (void) printer;
0325   (void) indentation_level;
0326   (void) indentation;
0327 
0328   return 0;
0329 #endif /* RTEMS_PROFILING */
0330 }