source: rtems/cpukit/sapi/src/profilingreportxml.c

Last change on this file was bcef89f2, checked in by Sebastian Huber <sebastian.huber@…>, on 05/19/23 at 06:18:25

Update company name

The embedded brains GmbH & Co. KG is the legal successor of embedded
brains GmbH.

  • Property mode set to 100644
File size: 7.8 KB
Line 
1/* SPDX-License-Identifier: BSD-2-Clause */
2
3/**
4 * @file
5 *
6 * @ingroup RTEMSAPIProfiling
7 *
8 * @brief This source file contains the implementation of
9 *   rtems_profiling_report_xml().
10 */
11
12/*
13 * Copyright (c) 2014 embedded brains GmbH & Co. KG
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 * 1. Redistributions of source code must retain the above copyright
19 *    notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 *    notice, this list of conditions and the following disclaimer in the
22 *    documentation and/or other materials provided with the distribution.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#ifdef HAVE_CONFIG_H
38#include "config.h"
39#endif
40
41#include <rtems/profiling.h>
42
43#ifdef RTEMS_PROFILING
44
45#include <inttypes.h>
46
47typedef struct {
48  const rtems_printer *printer;
49  uint32_t indentation_level;
50  const char *indentation;
51  int retval;
52} context;
53
54static void update_retval(context *ctx, int rv)
55{
56  if (rv > 0 && ctx->retval >= 0) {
57    ctx->retval += rv;
58  }
59}
60
61static void indent(context *ctx, uint32_t indentation_level)
62{
63  uint32_t n = ctx->indentation_level + indentation_level;
64  uint32_t i;
65
66  for (i = 0; i < n; ++i) {
67    int rv = rtems_printf(ctx->printer, "%s", ctx->indentation);
68
69    update_retval(ctx, rv);
70  }
71}
72
73static uint64_t arithmetic_mean(uint64_t total, uint64_t count)
74{
75  return count != 0 ? total / count : 0;
76}
77
78static void report_per_cpu(context *ctx, const rtems_profiling_per_cpu *per_cpu)
79{
80  int rv;
81
82  indent(ctx, 1);
83  rv = rtems_printf(
84    ctx->printer,
85    "<PerCPUProfilingReport processorIndex=\"%" PRIu32 "\">\n",
86    per_cpu->processor_index
87  );
88  update_retval(ctx, rv);
89
90  indent(ctx, 2);
91  rv = rtems_printf(
92    ctx->printer,
93    "<MaxThreadDispatchDisabledTime unit=\"ns\">%" PRIu32
94      "</MaxThreadDispatchDisabledTime>\n",
95    per_cpu->max_thread_dispatch_disabled_time
96  );
97  update_retval(ctx, rv);
98
99  indent(ctx, 2);
100  rv = rtems_printf(
101    ctx->printer,
102    "<MeanThreadDispatchDisabledTime unit=\"ns\">%" PRIu64
103      "</MeanThreadDispatchDisabledTime>\n",
104    arithmetic_mean(
105      per_cpu->total_thread_dispatch_disabled_time,
106      per_cpu->thread_dispatch_disabled_count
107    )
108  );
109  update_retval(ctx, rv);
110
111  indent(ctx, 2);
112  rv = rtems_printf(
113    ctx->printer,
114    "<TotalThreadDispatchDisabledTime unit=\"ns\">%" PRIu64
115      "</TotalThreadDispatchDisabledTime>\n",
116    per_cpu->total_thread_dispatch_disabled_time
117  );
118  update_retval(ctx, rv);
119
120  indent(ctx, 2);
121  rv = rtems_printf(
122    ctx->printer,
123    "<ThreadDispatchDisabledCount>%" PRIu64 "</ThreadDispatchDisabledCount>\n",
124    per_cpu->thread_dispatch_disabled_count
125  );
126  update_retval(ctx, rv);
127
128  indent(ctx, 2);
129  rv = rtems_printf(
130    ctx->printer,
131    "<MaxInterruptDelay unit=\"ns\">%" PRIu32 "</MaxInterruptDelay>\n",
132    per_cpu->max_interrupt_delay
133  );
134  update_retval(ctx, rv);
135
136  indent(ctx, 2);
137  rv = rtems_printf(
138    ctx->printer,
139    "<MaxInterruptTime unit=\"ns\">%" PRIu32
140      "</MaxInterruptTime>\n",
141    per_cpu->max_interrupt_time
142  );
143  update_retval(ctx, rv);
144
145  indent(ctx, 2);
146  rv = rtems_printf(
147    ctx->printer,
148    "<MeanInterruptTime unit=\"ns\">%" PRIu64
149      "</MeanInterruptTime>\n",
150    arithmetic_mean(
151      per_cpu->total_interrupt_time,
152      per_cpu->interrupt_count
153    )
154  );
155  update_retval(ctx, rv);
156
157  indent(ctx, 2);
158  rv = rtems_printf(
159    ctx->printer,
160    "<TotalInterruptTime unit=\"ns\">%" PRIu64 "</TotalInterruptTime>\n",
161    per_cpu->total_interrupt_time
162  );
163  update_retval(ctx, rv);
164
165  indent(ctx, 2);
166  rv = rtems_printf(
167    ctx->printer,
168    "<InterruptCount>%" PRIu64 "</InterruptCount>\n",
169    per_cpu->interrupt_count
170  );
171  update_retval(ctx, rv);
172
173  indent(ctx, 1);
174  rv = rtems_printf(
175    ctx->printer,
176    "</PerCPUProfilingReport>\n"
177  );
178  update_retval(ctx, rv);
179}
180
181static void report_smp_lock(context *ctx, const rtems_profiling_smp_lock *smp_lock)
182{
183  int rv;
184  uint32_t i;
185
186  indent(ctx, 1);
187  rv = rtems_printf(
188    ctx->printer,
189    "<SMPLockProfilingReport name=\"%s\">\n",
190    smp_lock->name
191  );
192  update_retval(ctx, rv);
193
194  indent(ctx, 2);
195  rv = rtems_printf(
196    ctx->printer,
197    "<MaxAcquireTime unit=\"ns\">%" PRIu32 "</MaxAcquireTime>\n",
198    smp_lock->max_acquire_time
199  );
200  update_retval(ctx, rv);
201
202  indent(ctx, 2);
203  rv = rtems_printf(
204    ctx->printer,
205    "<MaxSectionTime unit=\"ns\">%" PRIu32 "</MaxSectionTime>\n",
206    smp_lock->max_section_time
207  );
208  update_retval(ctx, rv);
209
210  indent(ctx, 2);
211  rv = rtems_printf(
212    ctx->printer,
213    "<MeanAcquireTime unit=\"ns\">%" PRIu64
214      "</MeanAcquireTime>\n",
215    arithmetic_mean(
216      smp_lock->total_acquire_time,
217      smp_lock->usage_count
218    )
219  );
220  update_retval(ctx, rv);
221
222  indent(ctx, 2);
223  rv = rtems_printf(
224    ctx->printer,
225    "<MeanSectionTime unit=\"ns\">%" PRIu64
226      "</MeanSectionTime>\n",
227    arithmetic_mean(
228      smp_lock->total_section_time,
229      smp_lock->usage_count
230    )
231  );
232  update_retval(ctx, rv);
233
234  indent(ctx, 2);
235  rv = rtems_printf(
236    ctx->printer,
237    "<TotalAcquireTime unit=\"ns\">%" PRIu64 "</TotalAcquireTime>\n",
238    smp_lock->total_acquire_time
239  );
240  update_retval(ctx, rv);
241
242  indent(ctx, 2);
243  rv = rtems_printf(
244    ctx->printer,
245    "<TotalSectionTime unit=\"ns\">%" PRIu64 "</TotalSectionTime>\n",
246    smp_lock->total_section_time
247  );
248  update_retval(ctx, rv);
249
250  indent(ctx, 2);
251  rv = rtems_printf(
252    ctx->printer,
253    "<UsageCount>%" PRIu64 "</UsageCount>\n",
254    smp_lock->usage_count
255  );
256  update_retval(ctx, rv);
257
258  for (i = 0; i < RTEMS_PROFILING_SMP_LOCK_CONTENTION_COUNTS; ++i) {
259    indent(ctx, 2);
260    rv = rtems_printf(
261      ctx->printer,
262      "<ContentionCount initialQueueLength=\"%" PRIu32 "\">%"
263        PRIu64 "</ContentionCount>\n",
264      i,
265      smp_lock->contention_counts[i]
266    );
267    update_retval(ctx, rv);
268  }
269
270  indent(ctx, 1);
271  rv = rtems_printf(
272    ctx->printer,
273    "</SMPLockProfilingReport>\n"
274  );
275  update_retval(ctx, rv);
276}
277
278static void report(void *arg, const rtems_profiling_data *data)
279{
280  context *ctx = arg;
281
282  switch (data->header.type) {
283    case RTEMS_PROFILING_PER_CPU:
284      report_per_cpu(ctx, &data->per_cpu);
285      break;
286    case RTEMS_PROFILING_SMP_LOCK:
287      report_smp_lock(ctx, &data->smp_lock);
288      break;
289  }
290}
291
292#endif /* RTEMS_PROFILING */
293
294int rtems_profiling_report_xml(
295  const char *name,
296  const rtems_printer *printer,
297  uint32_t indentation_level,
298  const char *indentation
299)
300{
301#ifdef RTEMS_PROFILING
302  context ctx_instance = {
303    .printer = printer,
304    .indentation_level = indentation_level,
305    .indentation = indentation,
306    .retval = 0
307  };
308  context *ctx = &ctx_instance;
309  int rv;
310
311  indent(ctx, 0);
312  rv = rtems_printf(printer, "<ProfilingReport name=\"%s\">\n", name);
313  update_retval(ctx, rv);
314
315  rtems_profiling_iterate(report, ctx);
316
317  indent(ctx, 0);
318  rv = rtems_printf(printer, "</ProfilingReport>\n");
319  update_retval(ctx, rv);
320
321  return ctx->retval;
322#else /* RTEMS_PROFILING */
323  (void) name;
324  (void) printer;
325  (void) indentation_level;
326  (void) indentation;
327
328  return 0;
329#endif /* RTEMS_PROFILING */
330}
Note: See TracBrowser for help on using the repository browser.