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

4.104.115
Last change on this file since 0893220 was 0893220, checked in by Ralf Corsepius <ralf.corsepius@…>, on 11/29/09 at 12:12:39

Whitespace removal.

  • Property mode set to 100644
File size: 40.7 KB
Line 
1/*
2  ------------------------------------------------------------------------
3  $Id$
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_H
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)
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
66rtems_capture_cli_open (int                          argc,
67                        char**                       argv,
68                        const rtems_monitor_command_arg_t* command_arg __attribute__((unused)),
69                        bool                         verbose __attribute__((unused)))
70{
71  uint32_t          size = 0;
72  bool              enable = false;
73  rtems_status_code sc;
74  int               arg;
75
76  if (argc <= 1)
77  {
78    fprintf (stdout, 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 = true;
88      else
89        fprintf (stdout, "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 (stdout, "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 (stdout, "error: open failed: %s\n", rtems_status_text (sc));
108    return;
109  }
110
111  fprintf (stdout, "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 (stdout, "error: open enable failed: %s\n", rtems_status_text (sc));
121    return;
122  }
123
124  fprintf (stdout, "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
136static void
137rtems_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                         verbose __attribute__((unused)))
141{
142  rtems_status_code sc;
143
144  sc = rtems_capture_close ();
145
146  if (sc != RTEMS_SUCCESSFUL)
147  {
148    fprintf (stdout, "error: close failed: %s\n", rtems_status_text (sc));
149    return;
150  }
151
152  fprintf (stdout, "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
164static void
165rtems_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                         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 (stdout, "error: enable failed: %s\n", rtems_status_text (sc));
177    return;
178  }
179
180  fprintf (stdout, "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
192static void
193rtems_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                         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 (stdout, "error: disable failed: %s\n", rtems_status_text (sc));
205    return;
206  }
207
208  fprintf (stdout, "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
220static void
221rtems_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                         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 (stdout, "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 (stdout, " ");
267    rtems_monitor_dump_id (rtems_capture_task_id (task));
268    fprintf (stdout, " ");
269    rtems_monitor_dump_name (rtems_capture_task_name (task));
270    fprintf (stdout, " ");
271    rtems_monitor_dump_priority (rtems_capture_task_start_priority (task));
272    fprintf (stdout, " ");
273    rtems_monitor_dump_priority (rtems_capture_task_real_priority (task));
274    fprintf (stdout, " ");
275    rtems_monitor_dump_priority (rtems_capture_task_curr_priority (task));
276    fprintf (stdout, " ");
277    rtems_monitor_dump_state (rtems_capture_task_state (task));
278    fprintf (stdout, " %c%c",
279             rtems_capture_task_valid (task) ? 'a' : 'd',
280             rtems_capture_task_flags (task) & RTEMS_CAPTURE_TRACED ? 't' : '-');
281
282    if ((floor > ceiling) && (ceiling > priority))
283      fprintf (stdout, "--");
284    else
285    {
286      uint32_t flags = rtems_capture_task_control_flags (task);
287      fprintf (stdout, "%c%c",
288               rtems_capture_task_control (task) ?
289               (flags & RTEMS_CAPTURE_WATCH ? 'w' : '+') : '-',
290               rtems_capture_watch_global_on () ? 'g' : '-');
291    }
292    fprintf (stdout, " %3" PRId32 "%% %3" PRId32 "%% (%" PRIu32 ")\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
308static void
309rtems_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 + 1];
318    unsigned long long    load[RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS + 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; 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 - 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 (stdout, "\x1b[H\x1b[J Press ENTER to exit.\n\n");
373    fprintf (stdout,
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; 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 (stdout, "\x1b[K");
405      rtems_monitor_dump_id (rtems_capture_task_id (tasks[i]));
406      fprintf (stdout, " ");
407      rtems_monitor_dump_name (rtems_capture_task_name (tasks[i]));
408      fprintf (stdout, "  ");
409      rtems_monitor_dump_priority (priority);
410      fprintf (stdout, "  ");
411      rtems_monitor_dump_priority (rtems_capture_task_curr_priority (tasks[i]));
412      fprintf (stdout, " ");
413      k = rtems_monitor_dump_state (rtems_capture_task_state (tasks[i]));
414      fprintf (stdout, "%*c %3i.%03i%% ", 6 - k, ' ',
415               task_load / 1000, task_load % 1000);
416      fprintf (stdout, "%3i%% %c%c", stack_used,
417              rtems_capture_task_valid (tasks[i]) ? 'a' : 'd',
418              rtems_capture_task_flags (tasks[i]) & RTEMS_CAPTURE_TRACED ? 't' : '-');
419
420      if ((floor > ceiling) && (ceiling > priority))
421        fprintf (stdout, "--");
422      else
423        fprintf (stdout, "%c%c",
424                rtems_capture_task_control (tasks[i]) ?
425                (rtems_capture_task_control_flags (tasks[i]) &
426                 RTEMS_CAPTURE_WATCH ? 'w' : '+') : '-',
427                rtems_capture_watch_global_on () ? 'g' : '-');
428
429      fprintf (stdout, "   %qi\n", rtems_capture_task_time (tasks[i]));
430    }
431
432    if (count < RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS)
433    {
434      j = RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS - count;
435      while (j > 0)
436      {
437        fprintf (stdout, "\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));
447  }
448}
449
450/*
451 * rtems_capture_cli_task_load
452 *
453 *  DESCRIPTION:
454 *
455 * This function is a monitor command.
456 *
457 */
458
459static void
460rtems_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                         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, RTEMS_CURRENT_PRIORITY, &priority);
471
472  if (sc != RTEMS_SUCCESSFUL)
473  {
474    fprintf (stdout, "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');
480
481  sc = rtems_task_create (name, priority, 4 * 1024,
482                          RTEMS_NO_FLOATING_POINT | RTEMS_LOCAL,
483                          RTEMS_PREEMPT | RTEMS_TIMESLICE | RTEMS_NO_ASR,
484                          &id);
485
486  if (sc != RTEMS_SUCCESSFUL)
487  {
488    fprintf (stdout, "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 (stdout, "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));
513
514      rtems_task_delete (id);
515
516      fprintf (stdout, "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
532static void
533rtems_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                         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 (stdout, "watch priority ceiling is %" PRId32 "\n", ceiling);
543  fprintf (stdout, "watch priority floor is %" PRId32 "\n", floor);
544  fprintf (stdout, "global watch is %s\n",
545          rtems_capture_watch_global_on () ? "enabled" : "disabled");
546  fprintf (stdout, "total %" PRId32 "\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 (stdout, " ");
556    rtems_monitor_dump_id (rtems_capture_control_id (control));
557    fprintf (stdout, " ");
558    rtems_monitor_dump_name (rtems_capture_control_name (control));
559    flags = rtems_capture_control_flags (control);
560    fprintf (stdout, " %c%c ",
561             rtems_capture_watch_global_on () ? 'g' : '-',
562             flags & RTEMS_CAPTURE_WATCH ? 'w' : '-');
563    flags = rtems_capture_control_to_triggers (control);
564    fprintf (stdout, " T:%c%c%c%c%c%c%c",
565             flags & RTEMS_CAPTURE_SWITCH    ? 'S' : '-',
566             flags & RTEMS_CAPTURE_CREATE ? 'C' : '-',
567             flags & RTEMS_CAPTURE_START ? 'S' : '-',
568             flags & RTEMS_CAPTURE_RESTART ? 'R' : '-',
569             flags & RTEMS_CAPTURE_DELETE ? 'D' : '-',
570             flags & RTEMS_CAPTURE_BEGIN ? 'B' : '-',
571             flags & RTEMS_CAPTURE_EXITTED ? 'E' : '-');
572    flags = rtems_capture_control_from_triggers (control);
573    fprintf (stdout, " F:%c%c%c%c%c",
574             flags & RTEMS_CAPTURE_SWITCH  ? 'S' : '-',
575             flags & RTEMS_CAPTURE_CREATE  ? 'C' : '-',
576             flags & RTEMS_CAPTURE_START   ? 'S' : '-',
577             flags & RTEMS_CAPTURE_RESTART ? 'R' : '-',
578             flags & RTEMS_CAPTURE_DELETE  ? 'D' : '-');
579
580    for (f = 0, fshowed = 0, lf = 1; f < RTEMS_CAPTURE_TRIGGER_TASKS; f++)
581    {
582      if (rtems_capture_control_by_valid (control, f))
583      {
584        if (lf && ((fshowed % 3) == 0))
585        {
586          fprintf (stdout, "\n");
587          lf = 0;
588        }
589
590        fprintf (stdout, "  %2i:", f);
591        rtems_monitor_dump_name (rtems_capture_control_by_name (control, f));
592        fprintf (stdout, "/");
593        rtems_monitor_dump_id (rtems_capture_control_by_id (control, f));
594        flags = rtems_capture_control_by_triggers (control, f);
595        fprintf (stdout, ":%c%c%c%c%c",
596                 flags & RTEMS_CAPTURE_SWITCH  ? 'S' : '-',
597                 flags & RTEMS_CAPTURE_CREATE  ? 'C' : '-',
598                 flags & RTEMS_CAPTURE_START   ? 'S' : '-',
599                 flags & RTEMS_CAPTURE_RESTART ? 'R' : '-',
600                 flags & RTEMS_CAPTURE_DELETE  ? 'D' : '-');
601        fshowed++;
602        lf = 1;
603      }
604    }
605
606    if (lf)
607      fprintf (stdout, "\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
622static bool
623rtems_capture_cli_get_name_id (char*          arg,
624                               bool*          valid_name,
625                               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 (stdout, "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 (arg[i]))
646      break;
647
648  if (i == l)
649  {
650    *id = strtoul (arg, 0, 16);
651    *valid_id = true;
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]);
665    *name = rname;
666    *valid_name = true;
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
682static char const * watch_add_usage = "usage: cwadd [task name] [id]\n";
683
684static void
685rtems_capture_cli_watch_add (int                          argc,
686                             char**                       argv,
687                             const rtems_monitor_command_arg_t* command_arg __attribute__((unused)),
688                             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              valid_name = false;
695  bool              valid_id = false;
696
697  if (argc <= 1)
698  {
699    fprintf (stdout, watch_add_usage);
700    return;
701  }
702
703  for (arg = 1; arg < argc; arg++)
704  {
705    if (argv[arg][0] == '-')
706    {
707      fprintf (stdout, "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 (stdout, "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 (stdout,
728             "error: watch add failed: %s\n", rtems_status_text (sc));
729    return;
730  }
731
732  fprintf (stdout, "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
745static char const * watch_del_usage = "usage: cwdel [task name] [id]\n";
746
747static void
748rtems_capture_cli_watch_del (int                          argc,
749                             char**                       argv,
750                             const rtems_monitor_command_arg_t* command_arg __attribute__((unused)),
751                             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              valid_name = false;
758  bool              valid_id = false;
759
760  if (argc <= 1)
761  {
762    fprintf (stdout, watch_del_usage);
763    return;
764  }
765
766  for (arg = 1; arg < argc; arg++)
767  {
768    if (argv[arg][0] == '-')
769    {
770      fprintf (stdout, "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 (stdout, "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 (stdout, "error: watch delete failed: %s\n",
791             rtems_status_text (sc));
792    return;
793  }
794
795  fprintf (stdout, "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
807static char const * watch_control_usage = "usage: cwctl [task name] [id] on/off\n";
808
809static void
810rtems_capture_cli_watch_control (int                          argc,
811                                 char**                       argv,
812                                 const rtems_monitor_command_arg_t* command_arg __attribute__((unused)),
813                                 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              valid_name = false;
820  bool              valid_id = false;
821  bool              enable = false;
822
823  if (argc <= 2)
824  {
825    fprintf (stdout, watch_control_usage);
826    return;
827  }
828
829  for (arg = 1; arg < argc; arg++)
830  {
831    if (argv[arg][0] == '-')
832    {
833      fprintf (stdout, "warning: option -%c ignored\n", argv[arg][1]);
834    }
835    else
836    {
837      if (strcmp (argv[arg], "on") == 0)
838        enable = true;
839      else if (strcmp (argv[arg], "off") == 0)
840        enable = false;
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 (stdout, "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 (stdout, "error: watch control failed: %s\n",
858             rtems_status_text (sc));
859    return;
860  }
861
862  fprintf (stdout, "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
874static char const * watch_global_usage = "usage: cwglob on/off\n";
875
876static void
877rtems_capture_cli_watch_global (int                          argc,
878                                char**                       argv,
879                                const rtems_monitor_command_arg_t* command_arg __attribute__((unused)),
880                                bool                         verbose __attribute__((unused)))
881{
882  rtems_status_code sc;
883  int               arg;
884  bool              enable = false;
885
886  if (argc <= 1)
887  {
888    fprintf (stdout, watch_global_usage);
889    return;
890  }
891
892  for (arg = 1; arg < argc; arg++)
893  {
894    if (argv[arg][0] == '-')
895    {
896      fprintf (stdout, "warning: option -%c ignored\n", argv[arg][1]);
897    }
898    else
899    {
900      if (strcmp (argv[arg], "on") == 0)
901        enable = true;
902      else if (strcmp (argv[arg], "off") == 0)
903        enable = false;
904    }
905  }
906
907  sc = rtems_capture_watch_global (enable);
908
909  if (sc != RTEMS_SUCCESSFUL)
910  {
911    fprintf (stdout, "error: global watch failed: %s\n",
912             rtems_status_text (sc));
913    return;
914  }
915
916  fprintf (stdout, "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
928static char const * watch_ceiling_usage = "usage: cwceil priority\n";
929
930static void
931rtems_capture_cli_watch_ceiling (int                          argc,
932                                 char**                       argv,
933                                 const rtems_monitor_command_arg_t* command_arg __attribute__((unused)),
934                                 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 (stdout, watch_ceiling_usage);
943    return;
944  }
945
946  for (arg = 1; arg < argc; arg++)
947  {
948    if (argv[arg][0] == '-')
949    {
950      fprintf (stdout, "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 (stdout, "error: watch ceiling failed: %s\n",
963             rtems_status_text (sc));
964    return;
965  }
966
967  fprintf (stdout, "watch ceiling is %" PRId32 ".\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
979static char const * watch_floor_usage = "usage: cwfloor priority\n";
980
981static void
982rtems_capture_cli_watch_floor (int                          argc,
983                               char**                       argv,
984                               const rtems_monitor_command_arg_t* command_arg __attribute__((unused)),
985                               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 (stdout, watch_floor_usage);
994    return;
995  }
996
997  for (arg = 1; arg < argc; arg++)
998  {
999    if (argv[arg][0] == '-')
1000    {
1001      fprintf (stdout, "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 (stdout, "error: watch floor failed: %s\n",
1014             rtems_status_text (sc));
1015    return;
1016  }
1017
1018  fprintf (stdout, "watch floor is %" PRId32 ".\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
1030static char const *trigger_set_usage =
1031      "usage: %s [-?] type [to name/id] [from] [from name/id]\n";
1032
1033static 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 */
1049typedef 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
1056static 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
1067typedef 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 \
1076  (sizeof (rtems_capture_cli_triggers) / sizeof (rtems_capture_cli_triggers_t))
1077
1078static void
1079rtems_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                         trigger_set = false;
1086  bool                         is_from = false;
1087  rtems_name                   name = 0;
1088  rtems_id                     id = 0;
1089  bool                         valid_name = false;
1090  bool                         valid_id = false;
1091  rtems_name                   from_name = 0;
1092  rtems_id                     from_id = 0;
1093  bool                         from_valid_name = false;
1094  bool                         from_valid_id = false;
1095  rtems_name                   to_name = 0;
1096  rtems_id                     to_id = 0;
1097  bool                         to_valid_name = false;
1098  bool                         to_valid_id = false;
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 (stdout, trigger_set_usage, set ? "ctset" : "ctclear");
1108          fprintf (stdout, trigger_set_types);
1109          return;
1110        default:
1111          fprintf (stdout, "warning: option -%c ignored\n", argv[arg][1]);
1112          break;
1113      }
1114    }
1115    else
1116    {
1117      if (!trigger_set)
1118      {
1119        bool found = false;
1120        int  t;
1121
1122        for (t = 0; t < RTEMS_CAPTURE_CLI_TRIGGERS_NUM; t++)
1123          if (strcmp (argv[arg], rtems_capture_cli_triggers[t].name) == 0)
1124          {
1125            trigger = t;
1126            found = true;
1127            break;
1128          }
1129
1130        trigger_set = true;
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 (stdout, "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 = true;
1160            from_name       = name;
1161          }
1162          else
1163            fprintf (stdout, "warning: extra arguments ignored\n");
1164        }
1165        else if (!to_valid_name && !to_valid_id)
1166        {
1167          to_valid_name = true;
1168          to_name       = name;
1169        }
1170        else
1171          fprintf (stdout, "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 = true;
1181            from_id       = id;
1182          }
1183          else
1184            fprintf (stdout, "warning: extra arguments ignored\n");
1185        }
1186        else if (!to_valid_name && !to_valid_id)
1187        {
1188          to_valid_id = true;
1189          to_id       = id;
1190        }
1191        else
1192          fprintf (stdout, "warning: extra arguments ignored\n");
1193      }
1194    }
1195  }
1196
1197  if (is_from && rtems_capture_cli_triggers[trigger].to_only)
1198  {
1199    fprintf (stdout, "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 (stdout, trigger_set_usage);
1207    return;
1208  }
1209
1210  if (!is_from && !to_valid_name && !to_valid_id)
1211  {
1212    fprintf (stdout, "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 (stdout, "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 (stdout, "error: %sing the trigger failed: %s\n",
1243             set ? "sett" : "clear", rtems_status_text (sc));
1244    return;
1245  }
1246
1247  fprintf (stdout, "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
1259static void
1260rtems_capture_cli_trigger_set (int                          argc,
1261                               char**                       argv,
1262                               const rtems_monitor_command_arg_t* command_arg __attribute__((unused)),
1263                               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
1277static void
1278rtems_capture_cli_trigger_clear (int                          argc,
1279                                 char**                       argv,
1280                                 const rtems_monitor_command_arg_t* command_arg __attribute__((unused)),
1281                                 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
1295static void
1296rtems_capture_cli_trace_records (int                          argc,
1297                                 char**                       argv,
1298                                 const rtems_monitor_command_arg_t* command_arg __attribute__((unused)),
1299                                 bool                         verbose __attribute__((unused)))
1300{
1301  rtems_status_code       sc;
1302  bool                    csv = false;
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 = true;
1316      else
1317        fprintf (stdout, "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 (argv[arg][i]))
1328        {
1329          fprintf (stdout, "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 (stdout, "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 (stdout, "%08" PRIxPTR ",%03" PRIu32
1367                   ",%03" PRIu32 ",%04" PRIx32 ",%" PRId32 ",%" PRId32 "\n",
1368                (uintptr_t) rec->task,
1369                (rec->events >> RTEMS_CAPTURE_REAL_PRIORITY_EVENT) & 0xff,
1370                (rec->events >> RTEMS_CAPTURE_CURR_PRIORITY_EVENT) & 0xff,
1371                (rec->events >> RTEMS_CAPTURE_EVENT_START),
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;
1380
1381        t  = rec->ticks;
1382        t *= rtems_capture_tick_time ();
1383        t += rec->tick_offset;
1384
1385        for (e = RTEMS_CAPTURE_EVENT_START; e < RTEMS_CAPTURE_EVENT_END; e++)
1386        {
1387          if (event & 1)
1388          {
1389            fprintf (stdout, "%9li.%06li ", (unsigned long) (t / 1000000),
1390                    (unsigned long) (t % 1000000));
1391            rtems_monitor_dump_id (rtems_capture_task_id (rec->task));
1392            fprintf (stdout, " ");
1393            rtems_monitor_dump_name (rtems_capture_task_name (rec->task));
1394            fprintf (stdout, " %3" PRId32 " %3" PRId32 " %s\n",
1395                    (rec->events >> RTEMS_CAPTURE_REAL_PRIORITY_EVENT) & 0xff,
1396                    (rec->events >> RTEMS_CAPTURE_CURR_PRIORITY_EVENT) & 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
1426static void
1427rtems_capture_cli_flush (int                          argc,
1428                         char**                       argv,
1429                         const rtems_monitor_command_arg_t* command_arg __attribute__((unused)),
1430                         bool                         verbose __attribute__((unused)))
1431{
1432  rtems_status_code sc;
1433  bool              prime = true;
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 = false;
1442      else
1443        fprintf (stdout, "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 (stdout, "error: flush failed: %s\n", rtems_status_text (sc));
1452    return;
1453  }
1454
1455  fprintf (stdout, "trace buffer flushed and %s.\n",
1456           prime ? "primed" : "not primed");
1457}
1458
1459static 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
1609rtems_status_code
1610rtems_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}
Note: See TracBrowser for help on using the repository browser.