source: rtems/cpukit/libmisc/capture/capture-cli.c @ 6a26e9b

4.115
Last change on this file since 6a26e9b was 6a26e9b, checked in by Chris Johns <chrisj@…>, on 12/24/13 at 07:08:29

cpukit/capture: Print the uptime and diff in ctrace.

Print the uptime and difference in nanoseconds to the previous
record in the ctrace output. For example:

0:00:59.474927121 14760 0a01000c TNTD 235 235 CREATED_BY
0:00:59.474927418 297 0a010012 /dev 235 235 CREATED
0:00:59.474930799 3381 0a01000c TNTD 235 235 STARTED_BY
0:00:59.474931105 306 0a010012 /dev 235 235 STARTED
0:00:59.475072297 141192 0a01000c TNTD 235 235 SWITCHED_OUT

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