File indexing completed on 2025-05-11 08:24:18
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
0038
0039
0040
0041 #ifdef HAVE_CONFIG_H
0042 #include "config.h"
0043 #endif
0044
0045 #include <ctype.h>
0046 #include <stdlib.h>
0047 #include <stdio.h>
0048 #include <string.h>
0049 #include <inttypes.h>
0050
0051 #include <rtems.h>
0052 #include <rtems/monitor.h>
0053 #include <rtems/captureimpl.h>
0054
0055
0056
0057
0058
0059 typedef struct
0060 {
0061 const void* recs;
0062 size_t read;
0063 size_t printed;
0064 bool rec_valid;
0065 rtems_capture_record rec;
0066 } ctrace_per_cpu;
0067
0068
0069
0070
0071 #define CTRACE_TASK_BLOCK_SIZE (64)
0072
0073
0074
0075
0076 typedef struct
0077 {
0078 rtems_name name;
0079 rtems_id id;
0080 } ctrace_task_name;
0081
0082
0083
0084
0085 typedef struct
0086 {
0087 ctrace_task_name* tasks;
0088 size_t size;
0089 size_t count;
0090 } ctrace_tasks;
0091
0092
0093
0094
0095 static ctrace_tasks tasks;
0096
0097
0098
0099
0100 static void
0101 ctrace_task_name_add (rtems_id id, const rtems_name name)
0102 {
0103 if (tasks.tasks == NULL)
0104 {
0105 tasks.size = CTRACE_TASK_BLOCK_SIZE;
0106 tasks.tasks = calloc (tasks.size, sizeof (ctrace_task_name));
0107 }
0108 if (tasks.tasks != NULL)
0109 {
0110 if (rtems_object_id_get_api(id) != OBJECTS_POSIX_API)
0111 {
0112 size_t t;
0113 for (t = 0; t < tasks.count; ++t)
0114 {
0115 if (tasks.tasks[t].id == id)
0116 {
0117 tasks.tasks[t].name = name;
0118 break;
0119 }
0120 }
0121 if (t == tasks.count)
0122 {
0123 if (tasks.count >= tasks.size)
0124 {
0125 tasks.size += CTRACE_TASK_BLOCK_SIZE;
0126 tasks.tasks = realloc (tasks.tasks,
0127 tasks.size * sizeof (ctrace_task_name));
0128 }
0129 if (tasks.tasks != NULL)
0130 {
0131 tasks.tasks[tasks.count].name = name;
0132 tasks.tasks[tasks.count].id = id;
0133 ++tasks.count;
0134 }
0135 }
0136 }
0137 }
0138 }
0139
0140
0141
0142
0143 static void
0144 ctrace_task_name_remove (rtems_id id)
0145 {
0146 size_t t;
0147 for (t = 0; t < tasks.count; ++t)
0148 {
0149 if (tasks.tasks[t].id == id)
0150 {
0151 size_t count = tasks.count - t - 1;
0152 if (count != 0)
0153 memmove (&tasks.tasks[t],
0154 &tasks.tasks[t + 1],
0155 sizeof (ctrace_task_name) * count);
0156 --tasks.count;
0157 break;
0158 }
0159 }
0160 }
0161
0162
0163
0164
0165 static void
0166 ctrace_task_name_find (rtems_id id, const rtems_name** name)
0167 {
0168 size_t t;
0169 *name = NULL;
0170 for (t = 0; t < tasks.count; ++t)
0171 {
0172 if (tasks.tasks[t].id == id)
0173 {
0174 *name = &tasks.tasks[t].name;
0175 break;
0176 }
0177 }
0178 }
0179
0180
0181
0182
0183
0184
0185 void
0186 rtems_capture_print_timestamp (uint64_t uptime)
0187 {
0188 uint32_t hours;
0189 uint32_t minutes;
0190 uint32_t seconds;
0191 uint32_t nanosecs;
0192 uint64_t up_secs;
0193
0194 up_secs = uptime / 1000000000LLU;
0195 minutes = up_secs / 60;
0196 hours = minutes / 60;
0197 minutes = minutes % 60;
0198 seconds = up_secs % 60;
0199 nanosecs = uptime % 1000000000;
0200
0201 fprintf (stdout, "%5" PRIu32 ":%02" PRIu32 ":%02" PRIu32".%09" PRIu32,
0202 hours, minutes, seconds, nanosecs);
0203 }
0204
0205 void
0206 rtems_capture_print_record_task (int cpu,
0207 const rtems_capture_record* rec,
0208 const rtems_capture_task_record* task_rec)
0209 {
0210 fprintf(stdout,"%2i ", cpu);
0211 rtems_capture_print_timestamp (rec->time);
0212 fprintf (stdout, " ");
0213 rtems_monitor_dump_id (rec->task_id);
0214 if (rtems_object_id_get_api(rec->task_id) != OBJECTS_POSIX_API)
0215 {
0216 fprintf (stdout, " %c%c%c%c",
0217 (char) (task_rec->name >> 24) & 0xff,
0218 (char) (task_rec->name >> 16) & 0xff,
0219 (char) (task_rec->name >> 8) & 0xff,
0220 (char) (task_rec->name >> 0) & 0xff);
0221 }
0222 else
0223 {
0224 fprintf (stdout, " ____");
0225 }
0226 fprintf(stdout, " %3" PRId32 " %3" PRId32 " ",
0227 (rec->events >> RTEMS_CAPTURE_REAL_PRIORITY_EVENT) & 0xff,
0228 (rec->events >> RTEMS_CAPTURE_CURR_PRIORITY_EVENT) & 0xff);
0229 fprintf (stdout, "%3" PRId32 " %6" PRId32 " TASK_RECORD\n",
0230 task_rec->start_priority,
0231 task_rec->stack_size);
0232 }
0233
0234 void
0235 rtems_capture_print_record_capture(int cpu,
0236 const rtems_capture_record* rec,
0237 uint64_t diff,
0238 const rtems_name* name)
0239 {
0240 uint32_t event;
0241 int e;
0242
0243 event = rec->events >> RTEMS_CAPTURE_EVENT_START;
0244 for (e = RTEMS_CAPTURE_EVENT_START; e < RTEMS_CAPTURE_EVENT_END; e++)
0245 {
0246 if (event & 1)
0247 {
0248 fprintf(stdout,"%2i ", cpu);
0249 rtems_capture_print_timestamp (rec->time);
0250 fprintf (stdout, " %12" PRId32 " ", (uint32_t) diff);
0251 rtems_monitor_dump_id (rec->task_id);
0252 if (name != NULL)
0253 {
0254 fprintf (stdout, " %c%c%c%c",
0255 (char) (*name >> 24) & 0xff,
0256 (char) (*name >> 16) & 0xff,
0257 (char) (*name >> 8) & 0xff,
0258 (char) (*name >> 0) & 0xff);
0259 }
0260 else
0261 {
0262 fprintf(stdout, " ");
0263 }
0264 fprintf(stdout, " %3" PRId32 " %3" PRId32 " %s\n",
0265 (rec->events >> RTEMS_CAPTURE_REAL_PRIORITY_EVENT) & 0xff,
0266 (rec->events >> RTEMS_CAPTURE_CURR_PRIORITY_EVENT) & 0xff,
0267 rtems_capture_event_text (e));
0268 }
0269 event >>= 1;
0270 }
0271 }
0272
0273
0274
0275
0276
0277
0278
0279 void
0280 rtems_capture_print_trace_records (int total, bool csv)
0281 {
0282 ctrace_per_cpu* per_cpu;
0283 ctrace_per_cpu* cpu;
0284 int cpus;
0285 rtems_capture_time last_time = 0;
0286 int i;
0287
0288 cpus = rtems_scheduler_get_processor_maximum ();
0289
0290 per_cpu = calloc (cpus, sizeof(*per_cpu));
0291 if (per_cpu == NULL)
0292 {
0293 fprintf(stdout, "error: no memory\n");
0294 return;
0295 }
0296
0297 while (total)
0298 {
0299 const rtems_capture_record* rec_out = NULL;
0300 int cpu_out = -1;
0301 rtems_capture_time this_time = 0;
0302
0303
0304 for (i = 0; i < cpus; i++) {
0305 cpu = &per_cpu[i];
0306
0307 if (cpu->read == 0)
0308 {
0309 rtems_status_code sc;
0310 sc = rtems_capture_read (i, &cpu->read, &cpu->recs);
0311 if (sc != RTEMS_SUCCESSFUL)
0312 {
0313 fprintf (stdout,
0314 "error: trace read failed: %s\n", rtems_status_text (sc));
0315 rtems_capture_flush (0);
0316 free (per_cpu);
0317 return;
0318 }
0319
0320 if (cpu->read == 0)
0321 rtems_capture_release (i, 0);
0322 }
0323
0324
0325 if (!cpu->rec_valid && (cpu->read != 0))
0326 {
0327 cpu->recs = rtems_capture_record_extract (cpu->recs,
0328 &cpu->rec,
0329 sizeof (cpu->rec));
0330 cpu->rec_valid = true;
0331 }
0332
0333
0334 if ((cpu->rec_valid) && ((this_time == 0) || (cpu->rec.time < this_time)))
0335 {
0336 rec_out = &cpu->rec;
0337 cpu_out = i;
0338 this_time = rec_out->time;
0339 }
0340 }
0341
0342
0343 if (rec_out == NULL)
0344 break;
0345
0346 cpu = &per_cpu[cpu_out];
0347
0348
0349 if (csv)
0350 {
0351 fprintf(stdout,
0352 "%03i,%08" PRIu32 ",%03" PRIu32
0353 ",%03" PRIu32 ",%04" PRIx32 ",%" PRId64 "\n",
0354 cpu_out,
0355 (uint32_t) rec_out->task_id,
0356 (rec_out->events >> RTEMS_CAPTURE_REAL_PRIORITY_EVENT) & 0xff,
0357 (rec_out->events >> RTEMS_CAPTURE_CURR_PRIORITY_EVENT) & 0xff,
0358 (rec_out->events >> RTEMS_CAPTURE_EVENT_START),
0359 (uint64_t) rec_out->time);
0360 }
0361 else
0362 {
0363 if ((rec_out->events >> RTEMS_CAPTURE_EVENT_START) == 0)
0364 {
0365 rtems_capture_task_record task_rec;
0366 cpu->recs = rtems_capture_record_extract (cpu->recs,
0367 &task_rec,
0368 sizeof (task_rec));
0369 ctrace_task_name_add (rec_out->task_id, task_rec.name);
0370 rtems_capture_print_record_task (cpu_out, rec_out, &task_rec);
0371 }
0372 else
0373 {
0374 rtems_capture_time diff;
0375 const rtems_name* name = NULL;
0376 if (last_time != 0)
0377 diff = rec_out->time - last_time;
0378 else
0379 diff = 0;
0380 last_time = rec_out->time;
0381 ctrace_task_name_find (rec_out->task_id, &name);
0382 rtems_capture_print_record_capture (cpu_out, rec_out, diff, name);
0383 if ((rec_out->events &
0384 (RTEMS_CAPTURE_DELETED_BY_EVENT | RTEMS_CAPTURE_DELETED_EVENT)) != 0)
0385 ctrace_task_name_remove (rec_out->task_id);
0386 }
0387 }
0388
0389
0390
0391
0392
0393 cpu->rec_valid = false;
0394 ++cpu->printed;
0395 if (cpu->printed == cpu->read)
0396 {
0397 rtems_capture_release (cpu_out, cpu->printed);
0398 cpu->recs = NULL;
0399 cpu->read = 0;
0400 cpu->printed = 0;
0401 }
0402
0403 --total;
0404 }
0405
0406
0407 for (i = 0; i < cpus; i++)
0408 {
0409 cpu = &per_cpu[i];
0410 if (cpu->read != 0)
0411 {
0412 rtems_capture_release (i, cpu->printed);
0413 }
0414 }
0415
0416 free(per_cpu);
0417 }
0418
0419 void
0420 rtems_capture_print_watch_list (void)
0421 {
0422 rtems_capture_control* control = rtems_capture_get_control_list ();
0423 rtems_task_priority ceiling = rtems_capture_watch_get_ceiling ();
0424 rtems_task_priority floor = rtems_capture_watch_get_floor ();
0425
0426 fprintf (stdout, "watch priority ceiling is %" PRId32 "\n", ceiling);
0427 fprintf (stdout, "watch priority floor is %" PRId32 "\n", floor);
0428 fprintf (stdout, "global watch is %s\n",
0429 rtems_capture_watch_global_on () ? "enabled" : "disabled");
0430 fprintf (stdout, "total %" PRId32 "\n", rtems_capture_control_count ());
0431
0432 while (control)
0433 {
0434 uint32_t flags;
0435 int f;
0436 int fshowed;
0437 int lf;
0438
0439 fprintf (stdout, " ");
0440 rtems_monitor_dump_id (rtems_capture_control_id (control));
0441 fprintf (stdout, " ");
0442 rtems_monitor_dump_name (rtems_capture_control_name (control));
0443 flags = rtems_capture_control_flags (control);
0444 fprintf (stdout, " %c%c ",
0445 rtems_capture_watch_global_on () ? 'g' : '-',
0446 flags & RTEMS_CAPTURE_WATCH ? 'w' : '-');
0447 flags = rtems_capture_control_to_triggers (control);
0448 fprintf (stdout, " T:%c%c%c%c%c%c%c",
0449 flags & RTEMS_CAPTURE_SWITCH ? 'S' : '-',
0450 flags & RTEMS_CAPTURE_CREATE ? 'C' : '-',
0451 flags & RTEMS_CAPTURE_START ? 'S' : '-',
0452 flags & RTEMS_CAPTURE_RESTART ? 'R' : '-',
0453 flags & RTEMS_CAPTURE_DELETE ? 'D' : '-',
0454 flags & RTEMS_CAPTURE_BEGIN ? 'B' : '-',
0455 flags & RTEMS_CAPTURE_EXITTED ? 'E' : '-');
0456 flags = rtems_capture_control_from_triggers (control);
0457 fprintf (stdout, " F:%c%c%c%c%c",
0458 flags & RTEMS_CAPTURE_SWITCH ? 'S' : '-',
0459 flags & RTEMS_CAPTURE_CREATE ? 'C' : '-',
0460 flags & RTEMS_CAPTURE_START ? 'S' : '-',
0461 flags & RTEMS_CAPTURE_RESTART ? 'R' : '-',
0462 flags & RTEMS_CAPTURE_DELETE ? 'D' : '-');
0463
0464 for (f = 0, fshowed = 0, lf = 1; f < RTEMS_CAPTURE_TRIGGER_TASKS; f++)
0465 {
0466 if (rtems_capture_control_by_valid (control, f))
0467 {
0468 if (lf && ((fshowed % 3) == 0))
0469 {
0470 fprintf (stdout, "\n");
0471 lf = 0;
0472 }
0473
0474 fprintf (stdout, " %2i:", f);
0475 rtems_monitor_dump_name (rtems_capture_control_by_name (control, f));
0476 fprintf (stdout, "/");
0477 rtems_monitor_dump_id (rtems_capture_control_by_id (control, f));
0478 flags = rtems_capture_control_by_triggers (control, f);
0479 fprintf (stdout, ":%c%c%c%c%c",
0480 flags & RTEMS_CAPTURE_SWITCH ? 'S' : '-',
0481 flags & RTEMS_CAPTURE_CREATE ? 'C' : '-',
0482 flags & RTEMS_CAPTURE_START ? 'S' : '-',
0483 flags & RTEMS_CAPTURE_RESTART ? 'R' : '-',
0484 flags & RTEMS_CAPTURE_DELETE ? 'D' : '-');
0485 fshowed++;
0486 lf = 1;
0487 }
0488 }
0489
0490 if (lf)
0491 fprintf (stdout, "\n");
0492
0493 control = rtems_capture_next_control (control);
0494 }
0495 }