File: | /home/joel/rtems-4.11-work/build/rtems/c/src/../../cpukit/libmisc/capture/capture-cli.c |
Location: | line 587, column 11 |
Description: | Value stored to 'lf' is never read |
1 | /* |
2 | ------------------------------------------------------------------------ |
3 | $Id: capture-cli.c,v 1.25 2010/03/12 16:26:14 joel Exp $ |
4 | ------------------------------------------------------------------------ |
5 | |
6 | Copyright Objective Design Systems Pty Ltd, 2002 |
7 | All rights reserved Objective Design Systems Pty Ltd, 2002 |
8 | Chris Johns (ccj@acm.org) |
9 | |
10 | COPYRIGHT (c) 1989-1998. |
11 | On-Line Applications Research Corporation (OAR). |
12 | |
13 | The license and distribution terms for this file may be |
14 | found in the file LICENSE in this distribution. |
15 | |
16 | This software with is provided ``as is'' and with NO WARRANTY. |
17 | |
18 | ------------------------------------------------------------------------ |
19 | |
20 | RTEMS Performance Monitoring and Measurement Framework. |
21 | |
22 | This is the Target Interface Command Line Interface. You need |
23 | start the RTEMS monitor. |
24 | |
25 | */ |
26 | |
27 | #ifdef HAVE_CONFIG_H1 |
28 | #include "config.h" |
29 | #endif |
30 | |
31 | #include <ctype.h> |
32 | #include <stdlib.h> |
33 | #include <stdio.h> |
34 | #include <string.h> |
35 | #include <inttypes.h> |
36 | |
37 | #include <rtems.h> |
38 | #include <rtems/capture-cli.h> |
39 | #include <rtems/monitor.h> |
40 | |
41 | #define RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS(20) (20) |
42 | |
43 | /* |
44 | * The user capture timestamper. |
45 | */ |
46 | static rtems_capture_timestamp capture_timestamp; |
47 | |
48 | /* |
49 | * Common variable to sync the load monitor task. |
50 | */ |
51 | static volatile int cli_load_thread_active; |
52 | |
53 | /* |
54 | * rtems_capture_cli_open |
55 | * |
56 | * DESCRIPTION: |
57 | * |
58 | * This function opens the capture engine. We need the size of the |
59 | * capture buffer. |
60 | * |
61 | */ |
62 | |
63 | static const char* open_usage = "usage: copen [-i] size\n"; |
64 | |
65 | static void |
66 | rtems_capture_cli_open (int argc, |
67 | char** argv, |
68 | const rtems_monitor_command_arg_t* command_arg __attribute__((unused)), |
69 | bool_Bool verbose __attribute__((unused))) |
70 | { |
71 | uint32_t size = 0; |
72 | bool_Bool enable = false0; |
73 | rtems_status_code sc; |
74 | int arg; |
75 | |
76 | if (argc <= 1) |
77 | { |
78 | fprintf (stdoutstdout, open_usage); |
79 | return; |
80 | } |
81 | |
82 | for (arg = 1; arg < argc; arg++) |
83 | { |
84 | if (argv[arg][0] == '-') |
85 | { |
86 | if (argv[arg][1] == 'i') |
87 | enable = true1; |
88 | else |
89 | fprintf (stdoutstdout, "warning: option -%c ignored\n", argv[arg][1]); |
90 | } |
91 | else |
92 | { |
93 | size = strtoul (argv[arg], 0, 0); |
94 | |
95 | if (size < 100) |
96 | { |
97 | fprintf (stdoutstdout, "error: size must be greater than or equal to 100\n"); |
98 | return; |
99 | } |
100 | } |
101 | } |
102 | |
103 | sc = rtems_capture_open (size, capture_timestamp); |
104 | |
105 | if (sc != RTEMS_SUCCESSFUL) |
106 | { |
107 | fprintf (stdoutstdout, "error: open failed: %s\n", rtems_status_text (sc)); |
108 | return; |
109 | } |
110 | |
111 | fprintf (stdoutstdout, "capture engine opened.\n"); |
112 | |
113 | if (!enable) |
114 | return; |
115 | |
116 | sc = rtems_capture_control (enable); |
117 | |
118 | if (sc != RTEMS_SUCCESSFUL) |
119 | { |
120 | fprintf (stdoutstdout, "error: open enable failed: %s\n", rtems_status_text (sc)); |
121 | return; |
122 | } |
123 | |
124 | fprintf (stdoutstdout, "capture engine enabled.\n"); |
125 | } |
126 | |
127 | /* |
128 | * rtems_capture_cli_close |
129 | * |
130 | * DESCRIPTION: |
131 | * |
132 | * This function closes the capture engine. |
133 | * |
134 | */ |
135 | |
136 | static void |
137 | rtems_capture_cli_close (int argc __attribute__((unused)), |
138 | char** argv __attribute__((unused)), |
139 | const rtems_monitor_command_arg_t* command_arg __attribute__((unused)), |
140 | bool_Bool verbose __attribute__((unused))) |
141 | { |
142 | rtems_status_code sc; |
143 | |
144 | sc = rtems_capture_close (); |
145 | |
146 | if (sc != RTEMS_SUCCESSFUL) |
147 | { |
148 | fprintf (stdoutstdout, "error: close failed: %s\n", rtems_status_text (sc)); |
149 | return; |
150 | } |
151 | |
152 | fprintf (stdoutstdout, "capture engine closed.\n"); |
153 | } |
154 | |
155 | /* |
156 | * rtems_capture_cli_enable |
157 | * |
158 | * DESCRIPTION: |
159 | * |
160 | * This function enables the capture engine. |
161 | * |
162 | */ |
163 | |
164 | static void |
165 | rtems_capture_cli_enable (int argc __attribute__((unused)), |
166 | char** argv __attribute__((unused)), |
167 | const rtems_monitor_command_arg_t* command_arg __attribute__((unused)), |
168 | bool_Bool verbose __attribute__((unused))) |
169 | { |
170 | rtems_status_code sc; |
171 | |
172 | sc = rtems_capture_control (1); |
173 | |
174 | if (sc != RTEMS_SUCCESSFUL) |
175 | { |
176 | fprintf (stdoutstdout, "error: enable failed: %s\n", rtems_status_text (sc)); |
177 | return; |
178 | } |
179 | |
180 | fprintf (stdoutstdout, "capture engine enabled.\n"); |
181 | } |
182 | |
183 | /* |
184 | * rtems_capture_cli_disable |
185 | * |
186 | * DESCRIPTION: |
187 | * |
188 | * This function disables the capture engine. |
189 | * |
190 | */ |
191 | |
192 | static void |
193 | rtems_capture_cli_disable (int argc __attribute__((unused)), |
194 | char** argv __attribute__((unused)), |
195 | const rtems_monitor_command_arg_t* command_arg __attribute__((unused)), |
196 | bool_Bool verbose __attribute__((unused))) |
197 | { |
198 | rtems_status_code sc; |
199 | |
200 | sc = rtems_capture_control (0); |
201 | |
202 | if (sc != RTEMS_SUCCESSFUL) |
203 | { |
204 | fprintf (stdoutstdout, "error: disable failed: %s\n", rtems_status_text (sc)); |
205 | return; |
206 | } |
207 | |
208 | fprintf (stdoutstdout, "capture engine disabled.\n"); |
209 | } |
210 | |
211 | /* |
212 | * rtems_capture_cli_task_list |
213 | * |
214 | * DESCRIPTION: |
215 | * |
216 | * This function lists the tasks the capture engine knows about. |
217 | * |
218 | */ |
219 | |
220 | static void |
221 | rtems_capture_cli_task_list (int argc __attribute__((unused)), |
222 | char** argv __attribute__((unused)), |
223 | const rtems_monitor_command_arg_t* command_arg __attribute__((unused)), |
224 | bool_Bool verbose __attribute__((unused))) |
225 | { |
226 | rtems_task_priority ceiling = rtems_capture_watch_get_ceiling (); |
227 | rtems_task_priority floor = rtems_capture_watch_get_floor (); |
228 | rtems_capture_task_t* task = rtems_capture_get_task_list (); |
229 | uint32_t ticks; |
230 | uint32_t tick_offset; |
231 | unsigned long long total_time; |
232 | int count = rtems_capture_task_count (); |
233 | |
234 | if (capture_timestamp) |
235 | capture_timestamp (&ticks, &tick_offset); |
236 | else |
237 | { |
238 | ticks = _Watchdog_Ticks_since_boot; |
239 | tick_offset = 0; |
240 | } |
241 | |
242 | fprintf (stdoutstdout, "total %i\n", count); |
243 | |
244 | while (task) |
245 | { |
246 | rtems_task_priority priority; |
247 | int32_t stack_used; |
248 | int32_t time_used; |
249 | |
250 | stack_used = rtems_capture_task_stack_usage (task); |
251 | if (stack_used) |
252 | stack_used = (stack_used * 100) / stack_used; |
253 | |
254 | if (stack_used > 100) |
255 | stack_used = 100; |
256 | |
257 | total_time = (ticks * rtems_capture_task_time (task)) + tick_offset; |
258 | |
259 | time_used = (rtems_capture_task_time (task) * 100) / total_time; |
260 | |
261 | if (time_used > 100) |
262 | time_used = 100; |
263 | |
264 | priority = rtems_capture_task_real_priority (task); |
265 | |
266 | fprintf (stdoutstdout, " "); |
267 | rtems_monitor_dump_id (rtems_capture_task_id (task)); |
268 | fprintf (stdoutstdout, " "); |
269 | rtems_monitor_dump_name (rtems_capture_task_name (task)); |
270 | fprintf (stdoutstdout, " "); |
271 | rtems_monitor_dump_priority (rtems_capture_task_start_priority (task)); |
272 | fprintf (stdoutstdout, " "); |
273 | rtems_monitor_dump_priority (rtems_capture_task_real_priority (task)); |
274 | fprintf (stdoutstdout, " "); |
275 | rtems_monitor_dump_priority (rtems_capture_task_curr_priority (task)); |
276 | fprintf (stdoutstdout, " "); |
277 | rtems_monitor_dump_state (rtems_capture_task_state (task)); |
278 | fprintf (stdoutstdout, " %c%c", |
279 | rtems_capture_task_valid (task) ? 'a' : 'd', |
280 | rtems_capture_task_flags (task) & RTEMS_CAPTURE_TRACED(1 << 0) ? 't' : '-'); |
281 | |
282 | if ((floor > ceiling) && (ceiling > priority)) |
283 | fprintf (stdoutstdout, "--"); |
284 | else |
285 | { |
286 | uint32_t flags = rtems_capture_task_control_flags (task); |
287 | fprintf (stdoutstdout, "%c%c", |
288 | rtems_capture_task_control (task) ? |
289 | (flags & RTEMS_CAPTURE_WATCH(1 << 0) ? 'w' : '+') : '-', |
290 | rtems_capture_watch_global_on () ? 'g' : '-'); |
291 | } |
292 | fprintf (stdoutstdout, " %3" PRId32"d" "%% %3" PRId32"d" "%% (%" PRIu32"u" ")\n", |
293 | stack_used, time_used, rtems_capture_task_ticks (task)); |
294 | |
295 | task = rtems_capture_next_task (task); |
296 | } |
297 | } |
298 | |
299 | /* |
300 | * rtems_capture_cli_task_load_thread |
301 | * |
302 | * DESCRIPTION: |
303 | * |
304 | * This function displays the load of the tasks on an ANSI terminal. |
305 | * |
306 | */ |
307 | |
308 | static void |
309 | rtems_capture_cli_task_load_thread (rtems_task_argument arg __attribute__((unused))) |
310 | { |
311 | rtems_task_priority ceiling = rtems_capture_watch_get_ceiling (); |
312 | rtems_task_priority floor = rtems_capture_watch_get_floor (); |
313 | int last_count = 0; |
314 | |
315 | for (;;) |
316 | { |
317 | rtems_capture_task_t* tasks[RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS(20) + 1]; |
318 | unsigned long long load[RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS(20) + 1]; |
319 | rtems_capture_task_t* task; |
320 | unsigned long long total_time; |
321 | int count = 0; |
322 | int i; |
323 | int j; |
324 | |
325 | cli_load_thread_active = 1; |
326 | |
327 | /* |
328 | * Iterate over the tasks and sort the highest load tasks |
329 | * into our local arrays. We only handle a limited number of |
330 | * tasks. |
331 | */ |
332 | |
333 | memset (tasks, 0, sizeof (tasks)); |
334 | memset (load, 0, sizeof (load)); |
335 | |
336 | task = rtems_capture_get_task_list (); |
337 | |
338 | total_time = 0; |
339 | |
340 | while (task) |
341 | { |
342 | if (rtems_capture_task_valid (task)) |
343 | { |
344 | unsigned long long l = rtems_capture_task_delta_time (task); |
345 | |
346 | count++; |
347 | |
348 | total_time += l; |
349 | |
350 | for (i = 0; i < RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS(20); i++) |
351 | { |
352 | if (tasks[i]) |
353 | { |
354 | if ((l == 0) || (l < load[i])) |
355 | continue; |
356 | |
357 | for (j = (RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS(20) - 1); j >= i; j--) |
358 | { |
359 | tasks[j + 1] = tasks[j]; |
360 | load[j + 1] = load[j]; |
361 | } |
362 | } |
363 | |
364 | tasks[i] = task; |
365 | load[i] = l; |
366 | break; |
367 | } |
368 | } |
369 | task = rtems_capture_next_task (task); |
370 | } |
371 | |
372 | fprintf (stdoutstdout, "\x1b[H\x1b[J Press ENTER to exit.\n\n"); |
373 | fprintf (stdoutstdout, |
374 | " PID NAME RPRI CPRI STATE %%CPU %%STK FLGS EXEC TIME\n"); |
375 | |
376 | if (count > last_count) |
377 | j = count; |
378 | else |
379 | j = last_count; |
380 | |
381 | for (i = 0; i < RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS(20); i++) |
382 | { |
383 | rtems_task_priority priority; |
384 | int stack_used; |
385 | int task_load; |
386 | int k; |
387 | |
388 | if (!tasks[i]) |
389 | break; |
390 | |
391 | j--; |
392 | |
393 | stack_used = rtems_capture_task_stack_usage (tasks[i]); |
394 | if (stack_used) |
395 | stack_used = (stack_used * 100) / stack_used; |
396 | |
397 | if (stack_used > 100) |
398 | stack_used = 100; |
399 | |
400 | task_load = (int) ((load[i] * 100000) / total_time); |
401 | |
402 | priority = rtems_capture_task_real_priority (tasks[i]); |
403 | |
404 | fprintf (stdoutstdout, "\x1b[K"); |
405 | rtems_monitor_dump_id (rtems_capture_task_id (tasks[i])); |
406 | fprintf (stdoutstdout, " "); |
407 | rtems_monitor_dump_name (rtems_capture_task_name (tasks[i])); |
408 | fprintf (stdoutstdout, " "); |
409 | rtems_monitor_dump_priority (priority); |
410 | fprintf (stdoutstdout, " "); |
411 | rtems_monitor_dump_priority (rtems_capture_task_curr_priority (tasks[i])); |
412 | fprintf (stdoutstdout, " "); |
413 | k = rtems_monitor_dump_state (rtems_capture_task_state (tasks[i])); |
414 | fprintf (stdoutstdout, "%*c %3i.%03i%% ", 6 - k, ' ', |
415 | task_load / 1000, task_load % 1000); |
416 | fprintf (stdoutstdout, "%3i%% %c%c", stack_used, |
417 | rtems_capture_task_valid (tasks[i]) ? 'a' : 'd', |
418 | rtems_capture_task_flags (tasks[i]) & RTEMS_CAPTURE_TRACED(1 << 0) ? 't' : '-'); |
419 | |
420 | if ((floor > ceiling) && (ceiling > priority)) |
421 | fprintf (stdoutstdout, "--"); |
422 | else |
423 | fprintf (stdoutstdout, "%c%c", |
424 | rtems_capture_task_control (tasks[i]) ? |
425 | (rtems_capture_task_control_flags (tasks[i]) & |
426 | RTEMS_CAPTURE_WATCH(1 << 0) ? 'w' : '+') : '-', |
427 | rtems_capture_watch_global_on () ? 'g' : '-'); |
428 | |
429 | fprintf (stdoutstdout, " %qi\n", rtems_capture_task_time (tasks[i])); |
430 | } |
431 | |
432 | if (count < RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS(20)) |
433 | { |
434 | j = RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS(20) - count; |
435 | while (j > 0) |
436 | { |
437 | fprintf (stdoutstdout, "\x1b[K\n"); |
438 | j--; |
439 | } |
440 | } |
441 | |
442 | last_count = count; |
443 | |
444 | cli_load_thread_active = 0; |
445 | |
446 | rtems_task_wake_after (RTEMS_MICROSECONDS_TO_TICKS (5000000)((5000000) / (Configuration.microseconds_per_tick))); |
447 | } |
448 | } |
449 | |
450 | /* |
451 | * rtems_capture_cli_task_load |
452 | * |
453 | * DESCRIPTION: |
454 | * |
455 | * This function is a monitor command. |
456 | * |
457 | */ |
458 | |
459 | static void |
460 | rtems_capture_cli_task_load (int argc __attribute__((unused)), |
461 | char** argv __attribute__((unused)), |
462 | const rtems_monitor_command_arg_t* command_arg __attribute__((unused)), |
463 | bool_Bool verbose __attribute__((unused))) |
464 | { |
465 | rtems_status_code sc; |
466 | rtems_task_priority priority; |
467 | rtems_name name; |
468 | rtems_id id; |
469 | |
470 | sc = rtems_task_set_priority (RTEMS_SELF((Objects_Id) 0), RTEMS_CURRENT_PRIORITY0, &priority); |
471 | |
472 | if (sc != RTEMS_SUCCESSFUL) |
473 | { |
474 | fprintf (stdoutstdout, "error: cannot obtain the current priority: %s\n", |
475 | rtems_status_text (sc)); |
476 | return; |
477 | } |
478 | |
479 | name = rtems_build_name('C', 'P', 'l', 't')( (uint32_t)('C') << 24 | (uint32_t)('P') << 16 | (uint32_t)('l') << 8 | (uint32_t)('t') ); |
480 | |
481 | sc = rtems_task_create (name, priority, 4 * 1024, |
482 | RTEMS_NO_FLOATING_POINT0x00000000 | RTEMS_LOCAL0x00000000, |
483 | RTEMS_PREEMPT0x00000000 | RTEMS_TIMESLICE0x00000200 | RTEMS_NO_ASR0x00000400, |
484 | &id); |
485 | |
486 | if (sc != RTEMS_SUCCESSFUL) |
487 | { |
488 | fprintf (stdoutstdout, "error: cannot create helper thread: %s\n", |
489 | rtems_status_text (sc)); |
490 | return; |
491 | } |
492 | |
493 | sc = rtems_task_start (id, rtems_capture_cli_task_load_thread, 0); |
494 | |
495 | if (sc != RTEMS_SUCCESSFUL) |
496 | { |
497 | fprintf (stdoutstdout, "error: cannot start helper thread: %s\n", |
498 | rtems_status_text (sc)); |
499 | rtems_task_delete (id); |
500 | return; |
501 | } |
502 | |
503 | for (;;) |
504 | { |
505 | int c = getchar (); |
506 | |
507 | if ((c == '\r') || (c == '\n')) |
508 | { |
509 | int loops = 20; |
510 | |
511 | while (loops && cli_load_thread_active) |
512 | rtems_task_wake_after (RTEMS_MICROSECONDS_TO_TICKS (100000)((100000) / (Configuration.microseconds_per_tick))); |
513 | |
514 | rtems_task_delete (id); |
515 | |
516 | fprintf (stdoutstdout, "load monitoring stopped.\n"); |
517 | |
518 | return; |
519 | } |
520 | } |
521 | } |
522 | |
523 | /* |
524 | * rtems_capture_cli_watch_list |
525 | * |
526 | * DESCRIPTION: |
527 | * |
528 | * This function lists the controls in the capture engine. |
529 | * |
530 | */ |
531 | |
532 | static void |
533 | rtems_capture_cli_watch_list (int argc __attribute__((unused)), |
534 | char** argv __attribute__((unused)), |
535 | const rtems_monitor_command_arg_t* command_arg __attribute__((unused)), |
536 | bool_Bool verbose __attribute__((unused))) |
537 | { |
538 | rtems_capture_control_t* control = rtems_capture_get_control_list (); |
539 | rtems_task_priority ceiling = rtems_capture_watch_get_ceiling (); |
540 | rtems_task_priority floor = rtems_capture_watch_get_floor (); |
541 | |
542 | fprintf (stdoutstdout, "watch priority ceiling is %" PRId32"d" "\n", ceiling); |
543 | fprintf (stdoutstdout, "watch priority floor is %" PRId32"d" "\n", floor); |
544 | fprintf (stdoutstdout, "global watch is %s\n", |
545 | rtems_capture_watch_global_on () ? "enabled" : "disabled"); |
546 | fprintf (stdoutstdout, "total %" PRId32"d" "\n", rtems_capture_control_count ()); |
547 | |
548 | while (control) |
549 | { |
550 | uint32_t flags; |
551 | int f; |
552 | int fshowed; |
553 | int lf; |
554 | |
555 | fprintf (stdoutstdout, " "); |
556 | rtems_monitor_dump_id (rtems_capture_control_id (control)); |
557 | fprintf (stdoutstdout, " "); |
558 | rtems_monitor_dump_name (rtems_capture_control_name (control)); |
559 | flags = rtems_capture_control_flags (control); |
560 | fprintf (stdoutstdout, " %c%c ", |
561 | rtems_capture_watch_global_on () ? 'g' : '-', |
562 | flags & RTEMS_CAPTURE_WATCH(1 << 0) ? 'w' : '-'); |
563 | flags = rtems_capture_control_to_triggers (control); |
564 | fprintf (stdoutstdout, " T:%c%c%c%c%c%c%c", |
565 | flags & RTEMS_CAPTURE_SWITCH(1 << 0) ? 'S' : '-', |
566 | flags & RTEMS_CAPTURE_CREATE(1 << 1) ? 'C' : '-', |
567 | flags & RTEMS_CAPTURE_START(1 << 2) ? 'S' : '-', |
568 | flags & RTEMS_CAPTURE_RESTART(1 << 3) ? 'R' : '-', |
569 | flags & RTEMS_CAPTURE_DELETE(1 << 4) ? 'D' : '-', |
570 | flags & RTEMS_CAPTURE_BEGIN(1 << 5) ? 'B' : '-', |
571 | flags & RTEMS_CAPTURE_EXITTED(1 << 6) ? 'E' : '-'); |
572 | flags = rtems_capture_control_from_triggers (control); |
573 | fprintf (stdoutstdout, " F:%c%c%c%c%c", |
574 | flags & RTEMS_CAPTURE_SWITCH(1 << 0) ? 'S' : '-', |
575 | flags & RTEMS_CAPTURE_CREATE(1 << 1) ? 'C' : '-', |
576 | flags & RTEMS_CAPTURE_START(1 << 2) ? 'S' : '-', |
577 | flags & RTEMS_CAPTURE_RESTART(1 << 3) ? 'R' : '-', |
578 | flags & RTEMS_CAPTURE_DELETE(1 << 4) ? 'D' : '-'); |
579 | |
580 | for (f = 0, fshowed = 0, lf = 1; f < RTEMS_CAPTURE_TRIGGER_TASKS(32); f++) |
581 | { |
582 | if (rtems_capture_control_by_valid (control, f)) |
583 | { |
584 | if (lf && ((fshowed % 3) == 0)) |
585 | { |
586 | fprintf (stdoutstdout, "\n"); |
587 | lf = 0; |
Value stored to 'lf' is never read | |
588 | } |
589 | |
590 | fprintf (stdoutstdout, " %2i:", f); |
591 | rtems_monitor_dump_name (rtems_capture_control_by_name (control, f)); |
592 | fprintf (stdoutstdout, "/"); |
593 | rtems_monitor_dump_id (rtems_capture_control_by_id (control, f)); |
594 | flags = rtems_capture_control_by_triggers (control, f); |
595 | fprintf (stdoutstdout, ":%c%c%c%c%c", |
596 | flags & RTEMS_CAPTURE_SWITCH(1 << 0) ? 'S' : '-', |
597 | flags & RTEMS_CAPTURE_CREATE(1 << 1) ? 'C' : '-', |
598 | flags & RTEMS_CAPTURE_START(1 << 2) ? 'S' : '-', |
599 | flags & RTEMS_CAPTURE_RESTART(1 << 3) ? 'R' : '-', |
600 | flags & RTEMS_CAPTURE_DELETE(1 << 4) ? 'D' : '-'); |
601 | fshowed++; |
602 | lf = 1; |
603 | } |
604 | } |
605 | |
606 | if (lf) |
607 | fprintf (stdoutstdout, "\n"); |
608 | |
609 | control = rtems_capture_next_control (control); |
610 | } |
611 | } |
612 | |
613 | /* |
614 | * rtems_capture_cli_get_name_id |
615 | * |
616 | * DESCRIPTION: |
617 | * |
618 | * This function checks arguments for a name or an id. |
619 | * |
620 | */ |
621 | |
622 | static bool_Bool |
623 | rtems_capture_cli_get_name_id (char* arg, |
624 | bool_Bool* valid_name, |
625 | bool_Bool* valid_id, |
626 | rtems_name* name, |
627 | rtems_id* id) |
628 | { |
629 | size_t l; |
630 | size_t i; |
631 | |
632 | if (*valid_name && *valid_id) |
633 | { |
634 | fprintf (stdoutstdout, "error: too many arguments\n"); |
635 | return 0; |
636 | } |
637 | |
638 | /* |
639 | * See if the arg is all hex digits. |
640 | */ |
641 | |
642 | l = strlen (arg); |
643 | |
644 | for (i = 0; i < l; i++) |
645 | if (!isxdigit ((unsigned char)arg[i])((*__ctype_b_loc ())[(int) (((unsigned char)arg[i]))] & ( unsigned short int) _ISxdigit)) |
646 | break; |
647 | |
648 | if (i == l) |
649 | { |
650 | *id = strtoul (arg, 0, 16); |
651 | *valid_id = true1; |
652 | } |
653 | else |
654 | { |
655 | /* |
656 | * This is a bit of hack but it should work on all platforms |
657 | * as it is what the score does with names. |
658 | * |
659 | * @warning The extra assigns play with the byte order so do not |
660 | * remove unless the score has been updated. |
661 | */ |
662 | rtems_name rname; |
663 | |
664 | rname = rtems_build_name(arg[0], arg[1], arg[2], arg[3])( (uint32_t)(arg[0]) << 24 | (uint32_t)(arg[1]) << 16 | (uint32_t)(arg[2]) << 8 | (uint32_t)(arg[3]) ); |
665 | *name = rname; |
666 | *valid_name = true1; |
667 | } |
668 | |
669 | return 1; |
670 | } |
671 | |
672 | /* |
673 | * rtems_capture_cli_watch_add |
674 | * |
675 | * DESCRIPTION: |
676 | * |
677 | * This function is a monitor command that add a watch to the capture |
678 | * engine. |
679 | * |
680 | */ |
681 | |
682 | static char const * watch_add_usage = "usage: cwadd [task name] [id]\n"; |
683 | |
684 | static void |
685 | rtems_capture_cli_watch_add (int argc, |
686 | char** argv, |
687 | const rtems_monitor_command_arg_t* command_arg __attribute__((unused)), |
688 | bool_Bool verbose __attribute__((unused))) |
689 | { |
690 | rtems_status_code sc; |
691 | int arg; |
692 | rtems_name name = 0; |
693 | rtems_id id = 0; |
694 | bool_Bool valid_name = false0; |
695 | bool_Bool valid_id = false0; |
696 | |
697 | if (argc <= 1) |
698 | { |
699 | fprintf (stdoutstdout, watch_add_usage); |
700 | return; |
701 | } |
702 | |
703 | for (arg = 1; arg < argc; arg++) |
704 | { |
705 | if (argv[arg][0] == '-') |
706 | { |
707 | fprintf (stdoutstdout, "warning: option -%c ignored\n", argv[arg][1]); |
708 | } |
709 | else |
710 | { |
711 | if (!rtems_capture_cli_get_name_id (argv[arg], &valid_name, &valid_id, |
712 | &name, &id)) |
713 | return; |
714 | } |
715 | } |
716 | |
717 | if (!valid_name && !valid_id) |
718 | { |
719 | fprintf (stdoutstdout, "error: no valid name or task id located\n"); |
720 | return; |
721 | } |
722 | |
723 | sc = rtems_capture_watch_add (name, id); |
724 | |
725 | if (sc != RTEMS_SUCCESSFUL) |
726 | { |
727 | fprintf (stdoutstdout, |
728 | "error: watch add failed: %s\n", rtems_status_text (sc)); |
729 | return; |
730 | } |
731 | |
732 | fprintf (stdoutstdout, "watch added.\n"); |
733 | } |
734 | |
735 | /* |
736 | * rtems_capture_cli_watch_del |
737 | * |
738 | * DESCRIPTION: |
739 | * |
740 | * This function is a monitor command that deletes a watch from the capture |
741 | * engine. |
742 | * |
743 | */ |
744 | |
745 | static char const * watch_del_usage = "usage: cwdel [task name] [id]\n"; |
746 | |
747 | static void |
748 | rtems_capture_cli_watch_del (int argc, |
749 | char** argv, |
750 | const rtems_monitor_command_arg_t* command_arg __attribute__((unused)), |
751 | bool_Bool verbose __attribute__((unused))) |
752 | { |
753 | rtems_status_code sc; |
754 | int arg; |
755 | rtems_name name = 0; |
756 | rtems_id id = 0; |
757 | bool_Bool valid_name = false0; |
758 | bool_Bool valid_id = false0; |
759 | |
760 | if (argc <= 1) |
761 | { |
762 | fprintf (stdoutstdout, watch_del_usage); |
763 | return; |
764 | } |
765 | |
766 | for (arg = 1; arg < argc; arg++) |
767 | { |
768 | if (argv[arg][0] == '-') |
769 | { |
770 | fprintf (stdoutstdout, "warning: option -%c ignored\n", argv[arg][1]); |
771 | } |
772 | else |
773 | { |
774 | if (!rtems_capture_cli_get_name_id (argv[arg], &valid_name, &valid_id, |
775 | &name, &id)) |
776 | return; |
777 | } |
778 | } |
779 | |
780 | if (!valid_name && !valid_id) |
781 | { |
782 | fprintf (stdoutstdout, "error: no valid name or task id located\n"); |
783 | return; |
784 | } |
785 | |
786 | sc = rtems_capture_watch_del (name, id); |
787 | |
788 | if (sc != RTEMS_SUCCESSFUL) |
789 | { |
790 | fprintf (stdoutstdout, "error: watch delete failed: %s\n", |
791 | rtems_status_text (sc)); |
792 | return; |
793 | } |
794 | |
795 | fprintf (stdoutstdout, "watch delete.\n"); |
796 | } |
797 | |
798 | /* |
799 | * rtems_capture_cli_watch_control |
800 | * |
801 | * DESCRIPTION: |
802 | * |
803 | * This function is a monitor command that controls a watch. |
804 | * |
805 | */ |
806 | |
807 | static char const * watch_control_usage = "usage: cwctl [task name] [id] on/off\n"; |
808 | |
809 | static void |
810 | rtems_capture_cli_watch_control (int argc, |
811 | char** argv, |
812 | const rtems_monitor_command_arg_t* command_arg __attribute__((unused)), |
813 | bool_Bool verbose __attribute__((unused))) |
814 | { |
815 | rtems_status_code sc; |
816 | int arg; |
817 | rtems_name name = 0; |
818 | rtems_id id = 0; |
819 | bool_Bool valid_name = false0; |
820 | bool_Bool valid_id = false0; |
821 | bool_Bool enable = false0; |
822 | |
823 | if (argc <= 2) |
824 | { |
825 | fprintf (stdoutstdout, watch_control_usage); |
826 | return; |
827 | } |
828 | |
829 | for (arg = 1; arg < argc; arg++) |
830 | { |
831 | if (argv[arg][0] == '-') |
832 | { |
833 | fprintf (stdoutstdout, "warning: option -%c ignored\n", argv[arg][1]); |
834 | } |
835 | else |
836 | { |
837 | if (strcmp (argv[arg], "on") == 0) |
838 | enable = true1; |
839 | else if (strcmp (argv[arg], "off") == 0) |
840 | enable = false0; |
841 | else if (!rtems_capture_cli_get_name_id (argv[arg], &valid_name, |
842 | &valid_id, &name, &id)) |
843 | return; |
844 | } |
845 | } |
846 | |
847 | if (!valid_name && !valid_id) |
848 | { |
849 | fprintf (stdoutstdout, "error: no valid name or task id located\n"); |
850 | return; |
851 | } |
852 | |
853 | sc = rtems_capture_watch_ctrl (name, id, enable); |
854 | |
855 | if (sc != RTEMS_SUCCESSFUL) |
856 | { |
857 | fprintf (stdoutstdout, "error: watch control failed: %s\n", |
858 | rtems_status_text (sc)); |
859 | return; |
860 | } |
861 | |
862 | fprintf (stdoutstdout, "watch %s.\n", enable ? "enabled" : "disabled"); |
863 | } |
864 | |
865 | /* |
866 | * rtems_capture_cli_watch_global |
867 | * |
868 | * DESCRIPTION: |
869 | * |
870 | * This function is a monitor command that sets a global watch. |
871 | * |
872 | */ |
873 | |
874 | static char const * watch_global_usage = "usage: cwglob on/off\n"; |
875 | |
876 | static void |
877 | rtems_capture_cli_watch_global (int argc, |
878 | char** argv, |
879 | const rtems_monitor_command_arg_t* command_arg __attribute__((unused)), |
880 | bool_Bool verbose __attribute__((unused))) |
881 | { |
882 | rtems_status_code sc; |
883 | int arg; |
884 | bool_Bool enable = false0; |
885 | |
886 | if (argc <= 1) |
887 | { |
888 | fprintf (stdoutstdout, watch_global_usage); |
889 | return; |
890 | } |
891 | |
892 | for (arg = 1; arg < argc; arg++) |
893 | { |
894 | if (argv[arg][0] == '-') |
895 | { |
896 | fprintf (stdoutstdout, "warning: option -%c ignored\n", argv[arg][1]); |
897 | } |
898 | else |
899 | { |
900 | if (strcmp (argv[arg], "on") == 0) |
901 | enable = true1; |
902 | else if (strcmp (argv[arg], "off") == 0) |
903 | enable = false0; |
904 | } |
905 | } |
906 | |
907 | sc = rtems_capture_watch_global (enable); |
908 | |
909 | if (sc != RTEMS_SUCCESSFUL) |
910 | { |
911 | fprintf (stdoutstdout, "error: global watch failed: %s\n", |
912 | rtems_status_text (sc)); |
913 | return; |
914 | } |
915 | |
916 | fprintf (stdoutstdout, "global watch %s.\n", enable ? "enabled" : "disabled"); |
917 | } |
918 | |
919 | /* |
920 | * rtems_capture_cli_watch_ceiling |
921 | * |
922 | * DESCRIPTION: |
923 | * |
924 | * This function is a monitor command that sets watch ceiling. |
925 | * |
926 | */ |
927 | |
928 | static char const * watch_ceiling_usage = "usage: cwceil priority\n"; |
929 | |
930 | static void |
931 | rtems_capture_cli_watch_ceiling (int argc, |
932 | char** argv, |
933 | const rtems_monitor_command_arg_t* command_arg __attribute__((unused)), |
934 | bool_Bool verbose __attribute__((unused))) |
935 | { |
936 | rtems_status_code sc; |
937 | int arg; |
938 | rtems_task_priority priority = 0; |
939 | |
940 | if (argc <= 1) |
941 | { |
942 | fprintf (stdoutstdout, watch_ceiling_usage); |
943 | return; |
944 | } |
945 | |
946 | for (arg = 1; arg < argc; arg++) |
947 | { |
948 | if (argv[arg][0] == '-') |
949 | { |
950 | fprintf (stdoutstdout, "warning: option -%c ignored\n", argv[arg][1]); |
951 | } |
952 | else |
953 | { |
954 | priority = strtoul (argv[arg], 0, 0); |
955 | } |
956 | } |
957 | |
958 | sc = rtems_capture_watch_ceiling (priority); |
959 | |
960 | if (sc != RTEMS_SUCCESSFUL) |
961 | { |
962 | fprintf (stdoutstdout, "error: watch ceiling failed: %s\n", |
963 | rtems_status_text (sc)); |
964 | return; |
965 | } |
966 | |
967 | fprintf (stdoutstdout, "watch ceiling is %" PRId32"d" ".\n", priority); |
968 | } |
969 | |
970 | /* |
971 | * rtems_capture_cli_watch_floor |
972 | * |
973 | * DESCRIPTION: |
974 | * |
975 | * This function is a monitor command that sets watch floor. |
976 | * |
977 | */ |
978 | |
979 | static char const * watch_floor_usage = "usage: cwfloor priority\n"; |
980 | |
981 | static void |
982 | rtems_capture_cli_watch_floor (int argc, |
983 | char** argv, |
984 | const rtems_monitor_command_arg_t* command_arg __attribute__((unused)), |
985 | bool_Bool verbose __attribute__((unused))) |
986 | { |
987 | rtems_status_code sc; |
988 | int arg; |
989 | rtems_task_priority priority = 0; |
990 | |
991 | if (argc <= 1) |
992 | { |
993 | fprintf (stdoutstdout, watch_floor_usage); |
994 | return; |
995 | } |
996 | |
997 | for (arg = 1; arg < argc; arg++) |
998 | { |
999 | if (argv[arg][0] == '-') |
1000 | { |
1001 | fprintf (stdoutstdout, "warning: option -%c ignored\n", argv[arg][1]); |
1002 | } |
1003 | else |
1004 | { |
1005 | priority = strtoul (argv[arg], 0, 0); |
1006 | } |
1007 | } |
1008 | |
1009 | sc = rtems_capture_watch_floor (priority); |
1010 | |
1011 | if (sc != RTEMS_SUCCESSFUL) |
1012 | { |
1013 | fprintf (stdoutstdout, "error: watch floor failed: %s\n", |
1014 | rtems_status_text (sc)); |
1015 | return; |
1016 | } |
1017 | |
1018 | fprintf (stdoutstdout, "watch floor is %" PRId32"d" ".\n", priority); |
1019 | } |
1020 | |
1021 | /* |
1022 | * rtems_capture_cli_trigger_worker |
1023 | * |
1024 | * DESCRIPTION: |
1025 | * |
1026 | * This function is a monitor command that sets or clears a trigger. |
1027 | * |
1028 | */ |
1029 | |
1030 | static char const *trigger_set_usage = |
1031 | "usage: %s [-?] type [to name/id] [from] [from name/id]\n"; |
1032 | |
1033 | static char const *trigger_set_types = |
1034 | " You can say 'type TASK' or 'type TO from FROM'\n" \ |
1035 | " where TASK is the task the event is happening to\n" \ |
1036 | " or you can say the event TO this task FROM this task.\n" \ |
1037 | " No type defaults to 'switch'.\n" \ |
1038 | " switch : context switch TASK or FROM or FROM->TO\n" \ |
1039 | " create : create TASK, or create TO from FROM\n" \ |
1040 | " start : start TASK, or start TO from FROM\n" \ |
1041 | " restart : restart TASK, or restart TO from FROM\n" \ |
1042 | " delete : delete TASK or delete TO from FROM\n" \ |
1043 | " begin : begin TASK\n" \ |
1044 | " exitted : exitted TASK\n"; |
1045 | |
1046 | /* |
1047 | * Structure to handle the parsing of the trigger command line. |
1048 | */ |
1049 | typedef struct rtems_capture_cli_triggers_s |
1050 | { |
1051 | char const * name; |
1052 | rtems_capture_trigger_t type; |
1053 | int to_only; |
1054 | } rtems_capture_cli_triggers_t; |
1055 | |
1056 | static rtems_capture_cli_triggers_t rtems_capture_cli_triggers[] = |
1057 | { |
1058 | { "switch", rtems_capture_switch, 0 }, /* must be first */ |
1059 | { "create", rtems_capture_create, 0 }, |
1060 | { "start", rtems_capture_start, 0 }, |
1061 | { "restart", rtems_capture_restart, 0 }, |
1062 | { "delete", rtems_capture_delete, 0 }, |
1063 | { "begin", rtems_capture_begin, 1 }, |
1064 | { "exitted", rtems_capture_exitted, 1 } |
1065 | }; |
1066 | |
1067 | typedef enum rtems_capture_cli_trig_state_e |
1068 | { |
1069 | trig_type, |
1070 | trig_to, |
1071 | trig_from_from, |
1072 | trig_from |
1073 | } rtems_capture_cli_trig_state_t; |
1074 | |
1075 | #define RTEMS_CAPTURE_CLI_TRIGGERS_NUM(sizeof (rtems_capture_cli_triggers) / sizeof (rtems_capture_cli_triggers_t )) \ |
1076 | (sizeof (rtems_capture_cli_triggers) / sizeof (rtems_capture_cli_triggers_t)) |
1077 | |
1078 | static void |
1079 | rtems_capture_cli_trigger_worker (int set, int argc, char** argv) |
1080 | { |
1081 | rtems_status_code sc; |
1082 | int arg; |
1083 | int trigger = 0; /* switch */ |
1084 | rtems_capture_trigger_mode_t trigger_mode = rtems_capture_from_any; |
1085 | bool_Bool trigger_set = false0; |
1086 | bool_Bool is_from = false0; |
1087 | rtems_name name = 0; |
1088 | rtems_id id = 0; |
1089 | bool_Bool valid_name = false0; |
1090 | bool_Bool valid_id = false0; |
1091 | rtems_name from_name = 0; |
1092 | rtems_id from_id = 0; |
1093 | bool_Bool from_valid_name = false0; |
1094 | bool_Bool from_valid_id = false0; |
1095 | rtems_name to_name = 0; |
1096 | rtems_id to_id = 0; |
1097 | bool_Bool to_valid_name = false0; |
1098 | bool_Bool to_valid_id = false0; |
1099 | |
1100 | for (arg = 1; arg < argc; arg++) |
1101 | { |
1102 | if (argv[arg][0] == '-') |
1103 | { |
1104 | switch (argv[arg][1]) |
1105 | { |
1106 | case '?': |
1107 | fprintf (stdoutstdout, trigger_set_usage, set ? "ctset" : "ctclear"); |
1108 | fprintf (stdoutstdout, trigger_set_types); |
1109 | return; |
1110 | default: |
1111 | fprintf (stdoutstdout, "warning: option -%c ignored\n", argv[arg][1]); |
1112 | break; |
1113 | } |
1114 | } |
1115 | else |
1116 | { |
1117 | if (!trigger_set) |
1118 | { |
1119 | bool_Bool found = false0; |
1120 | int t; |
1121 | |
1122 | for (t = 0; t < RTEMS_CAPTURE_CLI_TRIGGERS_NUM(sizeof (rtems_capture_cli_triggers) / sizeof (rtems_capture_cli_triggers_t )); t++) |
1123 | if (strcmp (argv[arg], rtems_capture_cli_triggers[t].name) == 0) |
1124 | { |
1125 | trigger = t; |
1126 | found = true1; |
1127 | break; |
1128 | } |
1129 | |
1130 | trigger_set = true1; |
1131 | |
1132 | /* |
1133 | * If a trigger was not found assume the default and |
1134 | * assume the parameter is a task name or id. |
1135 | */ |
1136 | if (found) |
1137 | continue; |
1138 | } |
1139 | |
1140 | if (strcmp (arg[argv], "from") == 0) |
1141 | { |
1142 | if (is_from) |
1143 | fprintf (stdoutstdout, "warning: extra 'from' ignored\n"); |
1144 | |
1145 | is_from = 1; |
1146 | continue; |
1147 | } |
1148 | |
1149 | if (!rtems_capture_cli_get_name_id (argv[arg], &valid_name, &valid_id, |
1150 | &name, &id)) |
1151 | return; |
1152 | |
1153 | if (valid_name) |
1154 | { |
1155 | if (is_from) |
1156 | { |
1157 | if (!from_valid_name && !from_valid_id) |
1158 | { |
1159 | from_valid_name = true1; |
1160 | from_name = name; |
1161 | } |
1162 | else |
1163 | fprintf (stdoutstdout, "warning: extra arguments ignored\n"); |
1164 | } |
1165 | else if (!to_valid_name && !to_valid_id) |
1166 | { |
1167 | to_valid_name = true1; |
1168 | to_name = name; |
1169 | } |
1170 | else |
1171 | fprintf (stdoutstdout, "warning: extra arguments ignored\n"); |
1172 | } |
1173 | |
1174 | if (valid_id) |
1175 | { |
1176 | if (is_from) |
1177 | { |
1178 | if (!from_valid_name && !from_valid_id) |
1179 | { |
1180 | from_valid_id = true1; |
1181 | from_id = id; |
1182 | } |
1183 | else |
1184 | fprintf (stdoutstdout, "warning: extra arguments ignored\n"); |
1185 | } |
1186 | else if (!to_valid_name && !to_valid_id) |
1187 | { |
1188 | to_valid_id = true1; |
1189 | to_id = id; |
1190 | } |
1191 | else |
1192 | fprintf (stdoutstdout, "warning: extra arguments ignored\n"); |
1193 | } |
1194 | } |
1195 | } |
1196 | |
1197 | if (is_from && rtems_capture_cli_triggers[trigger].to_only) |
1198 | { |
1199 | fprintf (stdoutstdout, "error: a %s trigger can be a TO trigger\n", |
1200 | rtems_capture_cli_triggers[trigger].name); |
1201 | return; |
1202 | } |
1203 | |
1204 | if (!to_valid_name && !to_valid_id && !from_valid_name && !from_valid_id) |
1205 | { |
1206 | fprintf (stdoutstdout, trigger_set_usage); |
1207 | return; |
1208 | } |
1209 | |
1210 | if (!is_from && !to_valid_name && !to_valid_id) |
1211 | { |
1212 | fprintf (stdoutstdout, "error: a %s trigger needs a TO name or id\n", |
1213 | rtems_capture_cli_triggers[trigger].name); |
1214 | return; |
1215 | } |
1216 | |
1217 | if (is_from && !from_valid_name && !from_valid_id) |
1218 | { |
1219 | fprintf (stdoutstdout, "error: a %s trigger needs a FROM name or id\n", |
1220 | rtems_capture_cli_triggers[trigger].name); |
1221 | return; |
1222 | } |
1223 | |
1224 | if ((from_valid_name || from_valid_id) && (to_valid_name || to_valid_id)) |
1225 | trigger_mode = rtems_capture_from_to; |
1226 | else if (from_valid_name || from_valid_id) |
1227 | trigger_mode = rtems_capture_to_any; |
1228 | else if (to_valid_name || to_valid_id) |
1229 | trigger_mode = rtems_capture_from_any; |
1230 | |
1231 | if (set) |
1232 | sc = rtems_capture_set_trigger (from_name, from_id, to_name, to_id, |
1233 | trigger_mode, |
1234 | rtems_capture_cli_triggers[trigger].type); |
1235 | else |
1236 | sc = rtems_capture_clear_trigger (from_name, from_id, to_name, to_id, |
1237 | trigger_mode, |
1238 | rtems_capture_cli_triggers[trigger].type); |
1239 | |
1240 | if (sc != RTEMS_SUCCESSFUL) |
1241 | { |
1242 | fprintf (stdoutstdout, "error: %sing the trigger failed: %s\n", |
1243 | set ? "sett" : "clear", rtems_status_text (sc)); |
1244 | return; |
1245 | } |
1246 | |
1247 | fprintf (stdoutstdout, "trigger %s.\n", set ? "set" : "cleared"); |
1248 | } |
1249 | |
1250 | /* |
1251 | * rtems_capture_cli_trigger_set |
1252 | * |
1253 | * DESCRIPTION: |
1254 | * |
1255 | * This function is a monitor command that sets a trigger. |
1256 | * |
1257 | */ |
1258 | |
1259 | static void |
1260 | rtems_capture_cli_trigger_set (int argc, |
1261 | char** argv, |
1262 | const rtems_monitor_command_arg_t* command_arg __attribute__((unused)), |
1263 | bool_Bool verbose __attribute__((unused))) |
1264 | { |
1265 | rtems_capture_cli_trigger_worker (1, argc, argv); |
1266 | } |
1267 | |
1268 | /* |
1269 | * rtems_capture_cli_trigger_clear |
1270 | * |
1271 | * DESCRIPTION: |
1272 | * |
1273 | * This function is a monitor command that clears a trigger. |
1274 | * |
1275 | */ |
1276 | |
1277 | static void |
1278 | rtems_capture_cli_trigger_clear (int argc, |
1279 | char** argv, |
1280 | const rtems_monitor_command_arg_t* command_arg __attribute__((unused)), |
1281 | bool_Bool verbose __attribute__((unused))) |
1282 | { |
1283 | rtems_capture_cli_trigger_worker (0, argc, argv); |
1284 | } |
1285 | |
1286 | /* |
1287 | * rtems_capture_cli_trace_records |
1288 | * |
1289 | * DESCRIPTION: |
1290 | * |
1291 | * This function is a monitor command that dumps trace records. |
1292 | * |
1293 | */ |
1294 | |
1295 | static void |
1296 | rtems_capture_cli_trace_records (int argc, |
1297 | char** argv, |
1298 | const rtems_monitor_command_arg_t* command_arg __attribute__((unused)), |
1299 | bool_Bool verbose __attribute__((unused))) |
1300 | { |
1301 | rtems_status_code sc; |
1302 | bool_Bool csv = false0; |
1303 | static int dump_total = 22; |
1304 | int total; |
1305 | int count; |
1306 | uint32_t read; |
1307 | rtems_capture_record_t* rec; |
1308 | int arg; |
1309 | |
1310 | for (arg = 1; arg < argc; arg++) |
1311 | { |
1312 | if (argv[arg][0] == '-') |
1313 | { |
1314 | if (argv[arg][1] == 'c') |
1315 | csv = true1; |
1316 | else |
1317 | fprintf (stdoutstdout, "warning: option -%c ignored\n", argv[arg][1]); |
1318 | } |
1319 | else |
1320 | { |
1321 | size_t i; |
1322 | size_t l; |
1323 | |
1324 | l = strlen (argv[arg]); |
1325 | |
1326 | for (i = 0; i < l; i++) |
1327 | if (!isdigit ((unsigned char)argv[arg][i])((*__ctype_b_loc ())[(int) (((unsigned char)argv[arg][i]))] & (unsigned short int) _ISdigit)) |
1328 | { |
1329 | fprintf (stdoutstdout, "error: not a number\n"); |
1330 | return; |
1331 | } |
1332 | |
1333 | dump_total = strtoul (argv[arg], 0, 0); |
1334 | } |
1335 | } |
1336 | |
1337 | total = dump_total; |
1338 | |
1339 | while (total) |
1340 | { |
1341 | sc = rtems_capture_read (0, 0, &read, &rec); |
1342 | |
1343 | if (sc != RTEMS_SUCCESSFUL) |
1344 | { |
1345 | fprintf (stdoutstdout, "error: trace read failed: %s\n", rtems_status_text (sc)); |
1346 | rtems_capture_flush (0); |
1347 | return; |
1348 | } |
1349 | |
1350 | /* |
1351 | * If we have no records then just exist. We still need to release |
1352 | * the reader lock. |
1353 | */ |
1354 | |
1355 | if (read == 0) |
1356 | { |
1357 | rtems_capture_release (read); |
1358 | break; |
1359 | } |
1360 | |
1361 | count = total < read ? total : read; |
1362 | |
1363 | while (count--) |
1364 | { |
1365 | if (csv) |
1366 | fprintf (stdoutstdout, "%08" PRIxPTR"x" ",%03" PRIu32"u" |
1367 | ",%03" PRIu32"u" ",%04" PRIx32"x" ",%" PRId32"d" ",%" PRId32"d" "\n", |
1368 | (uintptr_t) rec->task, |
1369 | (rec->events >> RTEMS_CAPTURE_REAL_PRIORITY_EVENT(0)) & 0xff, |
1370 | (rec->events >> RTEMS_CAPTURE_CURR_PRIORITY_EVENT(8)) & 0xff, |
1371 | (rec->events >> RTEMS_CAPTURE_EVENT_START(16)), |
1372 | rec->ticks, rec->tick_offset); |
1373 | else |
1374 | { |
1375 | unsigned long long t; |
1376 | uint32_t event; |
1377 | int e; |
1378 | |
1379 | event = rec->events >> RTEMS_CAPTURE_EVENT_START(16); |
1380 | |
1381 | t = rec->ticks; |
1382 | t *= rtems_capture_tick_time (); |
1383 | t += rec->tick_offset; |
1384 | |
1385 | for (e = RTEMS_CAPTURE_EVENT_START(16); e < RTEMS_CAPTURE_EVENT_END(28); e++) |
1386 | { |
1387 | if (event & 1) |
1388 | { |
1389 | fprintf (stdoutstdout, "%9li.%06li ", (unsigned long) (t / 1000000), |
1390 | (unsigned long) (t % 1000000)); |
1391 | rtems_monitor_dump_id (rtems_capture_task_id (rec->task)); |
1392 | fprintf (stdoutstdout, " "); |
1393 | rtems_monitor_dump_name (rtems_capture_task_name (rec->task)); |
1394 | fprintf (stdoutstdout, " %3" PRId32"d" " %3" PRId32"d" " %s\n", |
1395 | (rec->events >> RTEMS_CAPTURE_REAL_PRIORITY_EVENT(0)) & 0xff, |
1396 | (rec->events >> RTEMS_CAPTURE_CURR_PRIORITY_EVENT(8)) & 0xff, |
1397 | rtems_capture_event_text (e)); |
1398 | } |
1399 | event >>= 1; |
1400 | } |
1401 | } |
1402 | rec++; |
1403 | } |
1404 | |
1405 | count = total < read ? total : read; |
1406 | |
1407 | if (count < total) |
1408 | total -= count; |
1409 | else |
1410 | total = 0; |
1411 | |
1412 | rtems_capture_release (count); |
1413 | } |
1414 | } |
1415 | |
1416 | /* |
1417 | * rtems_capture_cli_flush |
1418 | * |
1419 | * DESCRIPTION: |
1420 | * |
1421 | * This function is a monitor command that flushes and primes the capture |
1422 | * engine. |
1423 | * |
1424 | */ |
1425 | |
1426 | static void |
1427 | rtems_capture_cli_flush (int argc, |
1428 | char** argv, |
1429 | const rtems_monitor_command_arg_t* command_arg __attribute__((unused)), |
1430 | bool_Bool verbose __attribute__((unused))) |
1431 | { |
1432 | rtems_status_code sc; |
1433 | bool_Bool prime = true1; |
1434 | int arg; |
1435 | |
1436 | for (arg = 1; arg < argc; arg++) |
1437 | { |
1438 | if (argv[arg][0] == '-') |
1439 | { |
1440 | if (argv[arg][1] == 'n') |
1441 | prime = false0; |
1442 | else |
1443 | fprintf (stdoutstdout, "warning: option -%c ignored\n", argv[arg][1]); |
1444 | } |
1445 | } |
1446 | |
1447 | sc = rtems_capture_flush (prime); |
1448 | |
1449 | if (sc != RTEMS_SUCCESSFUL) |
1450 | { |
1451 | fprintf (stdoutstdout, "error: flush failed: %s\n", rtems_status_text (sc)); |
1452 | return; |
1453 | } |
1454 | |
1455 | fprintf (stdoutstdout, "trace buffer flushed and %s.\n", |
1456 | prime ? "primed" : "not primed"); |
1457 | } |
1458 | |
1459 | static rtems_monitor_command_entry_t rtems_capture_cli_cmds[] = |
1460 | { |
1461 | { |
1462 | "copen", |
1463 | "usage: copen [-i] size\n", |
1464 | 0, |
1465 | rtems_capture_cli_open, |
1466 | { 0 }, |
1467 | 0 |
1468 | }, |
1469 | { |
1470 | "cclose", |
1471 | "usage: cclose\n", |
1472 | 0, |
1473 | rtems_capture_cli_close, |
1474 | { 0 }, |
1475 | 0 |
1476 | }, |
1477 | { |
1478 | "cenable", |
1479 | "usage: cenable\n", |
1480 | 0, |
1481 | rtems_capture_cli_enable, |
1482 | { 0 }, |
1483 | 0 |
1484 | }, |
1485 | { |
1486 | "cdisable", |
1487 | "usage: cdisable\n", |
1488 | 0, |
1489 | rtems_capture_cli_disable, |
1490 | { 0 }, |
1491 | 0 |
1492 | }, |
1493 | { |
1494 | "ctlist", |
1495 | "usage: ctlist \n", |
1496 | 0, |
1497 | rtems_capture_cli_task_list, |
1498 | { 0 }, |
1499 | 0 |
1500 | }, |
1501 | { |
1502 | "ctload", |
1503 | "usage: ctload \n", |
1504 | 0, |
1505 | rtems_capture_cli_task_load, |
1506 | { 0 }, |
1507 | 0 |
1508 | }, |
1509 | { |
1510 | "cwlist", |
1511 | "usage: cwlist\n", |
1512 | 0, |
1513 | rtems_capture_cli_watch_list, |
1514 | { 0 }, |
1515 | 0 |
1516 | }, |
1517 | { |
1518 | "cwadd", |
1519 | "usage: cwadd [task name] [id]\n", |
1520 | 0, |
1521 | rtems_capture_cli_watch_add, |
1522 | { 0 }, |
1523 | 0 |
1524 | }, |
1525 | { |
1526 | "cwdel", |
1527 | "usage: cwdel [task name] [id]\n", |
1528 | 0, |
1529 | rtems_capture_cli_watch_del, |
1530 | { 0 }, |
1531 | 0 |
1532 | }, |
1533 | { |
1534 | "cwctl", |
1535 | "usage: cwctl [task name] [id] on/off\n", |
1536 | 0, |
1537 | rtems_capture_cli_watch_control, |
1538 | { 0 }, |
1539 | 0 |
1540 | }, |
1541 | { |
1542 | "cwglob", |
1543 | "usage: cwglob on/off\n", |
1544 | 0, |
1545 | rtems_capture_cli_watch_global, |
1546 | { 0 }, |
1547 | 0 |
1548 | }, |
1549 | { |
1550 | "cwceil", |
1551 | "usage: cwceil priority\n", |
1552 | 0, |
1553 | rtems_capture_cli_watch_ceiling, |
1554 | { 0 }, |
1555 | 0 |
1556 | }, |
1557 | { |
1558 | "cwfloor", |
1559 | "usage: cwfloor priority\n", |
1560 | 0, |
1561 | rtems_capture_cli_watch_floor, |
1562 | { 0 }, |
1563 | 0 |
1564 | }, |
1565 | { |
1566 | "ctrace", |
1567 | "usage: ctrace [-c] [-r records]\n", |
1568 | 0, |
1569 | rtems_capture_cli_trace_records, |
1570 | { 0 }, |
1571 | 0 |
1572 | }, |
1573 | { |
1574 | "ctset", |
1575 | "usage: ctset -h\n", |
1576 | 0, |
1577 | rtems_capture_cli_trigger_set, |
1578 | { 0 }, |
1579 | 0 |
1580 | }, |
1581 | { |
1582 | "ctclear", |
1583 | "usage: ctclear -?\n", |
1584 | 0, |
1585 | rtems_capture_cli_trigger_clear, |
1586 | { 0 }, |
1587 | 0 |
1588 | }, |
1589 | { |
1590 | "cflush", |
1591 | "usage: cflush [-n]\n", |
1592 | 0, |
1593 | rtems_capture_cli_flush, |
1594 | { 0 }, |
1595 | 0 |
1596 | } |
1597 | }; |
1598 | |
1599 | /* |
1600 | * rtems_capture_cli_init |
1601 | * |
1602 | * DESCRIPTION: |
1603 | * |
1604 | * This function initialises the command line interface to the capture |
1605 | * engine. |
1606 | * |
1607 | */ |
1608 | |
1609 | rtems_status_code |
1610 | rtems_capture_cli_init (rtems_capture_timestamp timestamp) |
1611 | { |
1612 | size_t cmd; |
1613 | |
1614 | capture_timestamp = timestamp; |
1615 | |
1616 | for (cmd = 0; |
1617 | cmd < sizeof (rtems_capture_cli_cmds) / sizeof (rtems_monitor_command_entry_t); |
1618 | cmd++) |
1619 | rtems_monitor_insert_cmd (&rtems_capture_cli_cmds[cmd]); |
1620 | |
1621 | return RTEMS_SUCCESSFUL; |
1622 | } |