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

Last change on this file was 4b7fbc7, checked in by Joel Sherrill <joel@…>, on 03/18/22 at 15:18:07

cpukit/libmisc/capture: Manually change license to BSD-2

These files did not follow the standard format and needed to be
changed manually.

Updates #3053.

  • Property mode set to 100644
File size: 30.0 KB
Line 
1/* SPDX-License-Identifier: BSD-2-Clause */
2
3/**
4 * @file
5 *
6 * @brief RTEMS Performance Monitoring and Measurement Framework.
7 *
8 * This is the Target Interface Command Line Interface. You need
9 * start the RTEMS monitor.
10 */
11
12/*
13 * Copyright 2002, 2015 Chris Johns <chrisj@rtems.org>.
14 * All rights reserved.
15 *
16 * COPYRIGHT (c) 2014.
17 * On-Line Applications Research Corporation (OAR).
18 *
19 * Redistribution and use in source and binary forms, with or without
20 * modification, are permitted provided that the following conditions
21 * are met:
22 * 1. Redistributions of source code must retain the above copyright
23 *    notice, this list of conditions and the following disclaimer.
24 * 2. Redistributions in binary form must reproduce the above copyright
25 *    notice, this list of conditions and the following disclaimer in the
26 *    documentation and/or other materials provided with the distribution.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
32 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 */
40
41#ifdef HAVE_CONFIG_H
42#include "config.h"
43#endif
44
45#include <ctype.h>
46#include <stdlib.h>
47#include <stdio.h>
48#include <string.h>
49#include <inttypes.h>
50
51#include <rtems.h>
52#include <rtems/capture-cli.h>
53#include <rtems/captureimpl.h>
54#include <rtems/monitor.h>
55#include <rtems/cpuuse.h>
56#
57#define RC_UNUSED RTEMS_UNUSED
58
59#define RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS (20)
60
61/*
62 * The user capture timestamper.
63 */
64static rtems_capture_timestamp capture_timestamp;
65
66/*
67 * rtems_capture_cli_open
68 *
69 * This function opens the capture engine. We need the size of the
70 * capture buffer.
71 */
72
73static const char* open_usage = "usage: copen [-i] size\n";
74
75static void
76rtems_capture_cli_open (int                                argc,
77                        char**                             argv,
78                        const rtems_monitor_command_arg_t* command_arg RC_UNUSED,
79                        bool                               verbose RC_UNUSED)
80{
81  uint32_t          size = 0;
82  bool              enable = false;
83  rtems_status_code sc;
84  int               arg;
85
86  if (argc <= 1)
87  {
88    fprintf (stdout, open_usage);
89    return;
90  }
91
92  for (arg = 1; arg < argc; arg++)
93  {
94    if (argv[arg][0] == '-')
95    {
96      if (argv[arg][1] == 'i')
97        enable = true;
98      else
99        fprintf (stdout, "warning: option -%c ignored\n", argv[arg][1]);
100    }
101    else
102    {
103      size = strtoul (argv[arg], 0, 0);
104
105      if (size < 100)
106      {
107        fprintf (stdout, "error: size must be greater than or equal to 100\n");
108        return;
109      }
110    }
111  }
112
113  sc = rtems_capture_open (size, capture_timestamp);
114
115  if (sc != RTEMS_SUCCESSFUL)
116  {
117    fprintf (stdout, "error: open failed: %s\n", rtems_status_text (sc));
118    return;
119  }
120
121  fprintf (stdout, "capture engine opened.\n");
122
123  if (!enable)
124    return;
125
126  sc = rtems_capture_set_control (enable);
127
128  if (sc != RTEMS_SUCCESSFUL)
129  {
130    fprintf (stdout, "error: open enable failed: %s\n", rtems_status_text (sc));
131    return;
132  }
133
134  fprintf (stdout, "capture engine enabled.\n");
135}
136
137/*
138 * rtems_capture_cli_close
139 *
140 * This function closes the capture engine.
141 */
142
143static void
144rtems_capture_cli_close (int                                argc RC_UNUSED,
145                         char**                             argv RC_UNUSED,
146                         const rtems_monitor_command_arg_t* command_arg RC_UNUSED,
147                         bool                               verbose RC_UNUSED)
148{
149  rtems_status_code sc;
150
151  sc = rtems_capture_close ();
152
153  if (sc != RTEMS_SUCCESSFUL)
154  {
155    fprintf (stdout, "error: close failed: %s\n", rtems_status_text (sc));
156    return;
157  }
158
159  fprintf (stdout, "capture engine closed.\n");
160}
161
162/*
163 * rtems_capture_cli_enable
164 *
165 * This function enables the capture engine.
166 */
167
168static void
169rtems_capture_cli_enable (int                                argc RC_UNUSED,
170                          char**                             argv RC_UNUSED,
171                          const rtems_monitor_command_arg_t* command_arg RC_UNUSED,
172                          bool                               verbose RC_UNUSED)
173{
174  rtems_status_code sc;
175
176  sc = rtems_capture_set_control (true);
177
178  if (sc != RTEMS_SUCCESSFUL)
179  {
180    fprintf (stdout, "error: enable failed: %s\n", rtems_status_text (sc));
181    return;
182  }
183
184  fprintf (stdout, "capture engine enabled.\n");
185}
186
187/*
188 * rtems_capture_cli_disable
189 *
190 * This function disables the capture engine.
191 */
192
193static void
194rtems_capture_cli_disable (int                                argc RC_UNUSED,
195                           char**                             argv RC_UNUSED,
196                           const rtems_monitor_command_arg_t* command_arg RC_UNUSED,
197                           bool                               verbose RC_UNUSED)
198{
199  rtems_status_code sc;
200
201  sc = rtems_capture_set_control (false);
202
203  if (sc != RTEMS_SUCCESSFUL)
204  {
205    fprintf (stdout, "error: disable failed: %s\n", rtems_status_text (sc));
206    return;
207  }
208
209  fprintf (stdout, "capture engine disabled.\n");
210}
211
212static bool
213rtems_capture_cli_print_task (rtems_tcb *tcb, void *arg)
214{
215  rtems_task_priority   ceiling = rtems_capture_watch_get_ceiling ();
216  rtems_task_priority   floor = rtems_capture_watch_get_floor ();
217  rtems_task_priority   priority;
218  int                   length;
219  uint32_t              flags = rtems_capture_task_control_flags (tcb);
220
221  priority = rtems_capture_task_real_priority (tcb);
222
223  fprintf (stdout, " ");
224  rtems_monitor_dump_id (rtems_capture_task_id (tcb));
225  fprintf (stdout, " ");
226  if (rtems_capture_task_api (rtems_capture_task_id (tcb)) != OBJECTS_POSIX_API)
227  {
228    rtems_monitor_dump_name (rtems_capture_task_id (tcb));
229    fprintf (stdout, " ");
230  }
231  else
232  {
233    fprintf (stdout, "     ");
234  }
235  rtems_monitor_dump_priority (rtems_capture_task_start_priority (tcb));
236  fprintf (stdout, " ");
237  rtems_monitor_dump_priority (rtems_capture_task_real_priority (tcb));
238  fprintf (stdout, " ");
239  rtems_monitor_dump_priority (rtems_capture_task_curr_priority (tcb));
240  fprintf (stdout, " ");
241  length = rtems_monitor_dump_state (rtems_capture_task_state (tcb));
242  fprintf (stdout, "%*c", 14 - length, ' ');
243  fprintf (stdout, " %c%c",
244           'a',
245           flags & RTEMS_CAPTURE_TRACED ? 't' : '-');
246
247  if ((floor > ceiling) && (ceiling > priority))
248    fprintf (stdout, "--");
249  else
250  {
251    fprintf (stdout, "%c%c",
252             rtems_capture_task_control (tcb) ?
253             (flags & RTEMS_CAPTURE_WATCH ? 'w' : '+') : '-',
254             rtems_capture_watch_global_on () ? 'g' : '-');
255  }
256  fprintf (stdout, "\n");
257  return false;
258}
259
260/*
261 * rtems_capture_cli_count_tasks
262 *
263 * This function is called for each tcb and counts the
264 * number of tasks.
265 */
266
267static bool
268rtems_capture_cli_count_tasks (rtems_tcb *tcb, void *arg)
269{
270  uint32_t *task_count = arg;
271  ++(*task_count);
272  return false;
273}
274
275
276/*
277 * rtems_capture_cli_task_list
278 *
279 * This function lists the tasks the capture engine knows about.
280 */
281
282static void
283rtems_capture_cli_task_list (int                                argc RC_UNUSED,
284                             char**                             argv RC_UNUSED,
285                             const rtems_monitor_command_arg_t* command_arg RC_UNUSED,
286                             bool                               verbose RC_UNUSED)
287{
288  rtems_capture_time uptime;
289  uint32_t           task_count;
290
291  rtems_capture_get_time (&uptime);
292
293  task_count = 0;
294  rtems_task_iterate (rtems_capture_cli_count_tasks, &task_count);
295
296  fprintf (stdout, "uptime: ");
297  rtems_capture_print_timestamp (uptime);
298  fprintf (stdout, "\ntotal %" PRIu32 "\n", task_count);
299  rtems_task_iterate (rtems_capture_cli_print_task, NULL);
300}
301
302/*
303 * rtems_capture_cli_watch_list
304 *
305 * This function lists the controls in the capture engine.
306 */
307
308static void
309rtems_capture_cli_watch_list (int                                argc RC_UNUSED,
310                              char**                             argv RC_UNUSED,
311                              const rtems_monitor_command_arg_t* command_arg RC_UNUSED,
312                              bool                               verbose RC_UNUSED)
313{
314  rtems_capture_print_watch_list();
315}
316
317/*
318 * rtems_capture_cli_get_name_id
319 *
320 * This function checks arguments for a name or an id.
321 */
322
323static bool
324rtems_capture_cli_get_name_id (char*       arg,
325                               bool*       valid_name,
326                               bool*       valid_id,
327                               rtems_name* name,
328                               rtems_id*   id)
329{
330  size_t l;
331  size_t i;
332
333  if (*valid_name && *valid_id)
334  {
335    fprintf (stdout, "error: too many arguments\n");
336    return 0;
337  }
338
339  /*
340   * See if the arg is all hex digits.
341   */
342
343  l = strlen (arg);
344
345  for (i = 0; i < l; i++)
346    if (!isxdigit ((unsigned char)arg[i]))
347      break;
348
349  if (i == l)
350  {
351    *id = strtoul (arg, 0, 16);
352    *valid_id = true;
353  }
354  else
355  {
356    /*
357     * This is a bit of hack but it should work on all platforms
358     * as it is what the score does with names.
359     *
360     * @warning The extra assigns play with the byte order so do not
361     *          remove unless the score has been updated.
362     */
363    rtems_name   rname;
364
365    rname = rtems_build_name(arg[0], arg[1], arg[2], arg[3]);
366    *name = rname;
367    *valid_name = true;
368  }
369
370  return 1;
371}
372
373/*
374 * rtems_capture_cli_watch_add
375 *
376 * This function is a monitor command that add a watch to the capture
377 * engine.
378 */
379
380static char const * watch_add_usage = "usage: cwadd [task name] [id]\n";
381
382static void
383rtems_capture_cli_watch_add (int                                argc,
384                             char**                             argv,
385                             const rtems_monitor_command_arg_t* command_arg RC_UNUSED,
386                             bool                               verbose RC_UNUSED)
387{
388  rtems_status_code sc;
389  int               arg;
390  rtems_name        name = 0;
391  rtems_id          id = 0;
392  bool              valid_name = false;
393  bool              valid_id = false;
394
395  if (argc <= 1)
396  {
397    fprintf (stdout, watch_add_usage);
398    return;
399  }
400
401  for (arg = 1; arg < argc; arg++)
402  {
403    if (argv[arg][0] == '-')
404    {
405      fprintf (stdout, "warning: option -%c ignored\n", argv[arg][1]);
406    }
407    else
408    {
409      if (!rtems_capture_cli_get_name_id (argv[arg], &valid_name, &valid_id,
410                                          &name, &id))
411        return;
412    }
413  }
414
415  if (!valid_name && !valid_id)
416  {
417    fprintf (stdout, "error: no valid name or task id located\n");
418    return;
419  }
420
421  sc = rtems_capture_watch_add (name, id);
422
423  if (sc != RTEMS_SUCCESSFUL)
424  {
425    fprintf (stdout,
426             "error: watch add failed: %s\n", rtems_status_text (sc));
427    return;
428  }
429
430  fprintf (stdout, "watch added.\n");
431}
432
433/*
434 * rtems_capture_cli_watch_del
435 *
436 * This function is a monitor command that deletes a watch from the capture
437 * engine.
438 */
439
440static char const * watch_del_usage = "usage: cwdel [task name] [id]\n";
441
442static void
443rtems_capture_cli_watch_del (int                                argc,
444                             char**                             argv,
445                             const rtems_monitor_command_arg_t* command_arg RC_UNUSED,
446                             bool                               verbose RC_UNUSED)
447{
448  rtems_status_code sc;
449  int               arg;
450  rtems_name        name = 0;
451  rtems_id          id = 0;
452  bool              valid_name = false;
453  bool              valid_id = false;
454
455  if (argc <= 1)
456  {
457    fprintf (stdout, watch_del_usage);
458    return;
459  }
460
461  for (arg = 1; arg < argc; arg++)
462  {
463    if (argv[arg][0] == '-')
464    {
465      fprintf (stdout, "warning: option -%c ignored\n", argv[arg][1]);
466    }
467    else
468    {
469      if (!rtems_capture_cli_get_name_id (argv[arg], &valid_name, &valid_id,
470                                          &name, &id))
471        return;
472    }
473  }
474
475  if (!valid_name && !valid_id)
476  {
477    fprintf (stdout, "error: no valid name or task id located\n");
478    return;
479  }
480
481  sc = rtems_capture_watch_del (name, id);
482
483  if (sc != RTEMS_SUCCESSFUL)
484  {
485    fprintf (stdout, "error: watch delete failed: %s\n",
486             rtems_status_text (sc));
487    return;
488  }
489
490  fprintf (stdout, "watch delete.\n");
491}
492
493/*
494 * rtems_capture_cli_watch_control
495 *
496 * This function is a monitor command that controls a watch.
497 */
498
499static char const * watch_control_usage = "usage: cwctl [task name] [id] on/off\n";
500
501static void
502rtems_capture_cli_watch_control (int                                argc,
503                                 char**                             argv,
504                                 const rtems_monitor_command_arg_t* command_arg RC_UNUSED,
505                                 bool                               verbose RC_UNUSED)
506{
507  rtems_status_code sc;
508  int               arg;
509  rtems_name        name = 0;
510  rtems_id          id = 0;
511  bool              valid_name = false;
512  bool              valid_id = false;
513  bool              enable = false;
514
515  if (argc <= 2)
516  {
517    fprintf (stdout, watch_control_usage);
518    return;
519  }
520
521  for (arg = 1; arg < argc; arg++)
522  {
523    if (argv[arg][0] == '-')
524    {
525      fprintf (stdout, "warning: option -%c ignored\n", argv[arg][1]);
526    }
527    else
528    {
529      if (strcmp (argv[arg], "on") == 0)
530        enable = true;
531      else if (strcmp (argv[arg], "off") == 0)
532        enable = false;
533      else if (!rtems_capture_cli_get_name_id (argv[arg], &valid_name,
534                                               &valid_id, &name, &id))
535        return;
536    }
537  }
538
539  if (!valid_name && !valid_id)
540  {
541    fprintf (stdout, "error: no valid name or task id located\n");
542    return;
543  }
544
545  sc = rtems_capture_watch_ctrl (name, id, enable);
546
547  if (sc != RTEMS_SUCCESSFUL)
548  {
549    fprintf (stdout, "error: watch control failed: %s\n",
550             rtems_status_text (sc));
551    return;
552  }
553
554  fprintf (stdout, "watch %s.\n", enable ? "enabled" : "disabled");
555}
556
557/*
558 * rtems_capture_cli_watch_global
559 *
560 * This function is a monitor command that sets a global watch.
561 */
562
563static char const * watch_global_usage = "usage: cwglob on/off\n";
564
565static void
566rtems_capture_cli_watch_global (int                                argc,
567                                char**                             argv,
568                                const rtems_monitor_command_arg_t* command_arg RC_UNUSED,
569                                bool                               verbose RC_UNUSED)
570{
571  rtems_status_code sc;
572  int               arg;
573  bool              enable = false;
574
575  if (argc <= 1)
576  {
577    fprintf (stdout, watch_global_usage);
578    return;
579  }
580
581  for (arg = 1; arg < argc; arg++)
582  {
583    if (argv[arg][0] == '-')
584    {
585      fprintf (stdout, "warning: option -%c ignored\n", argv[arg][1]);
586    }
587    else
588    {
589      if (strcmp (argv[arg], "on") == 0)
590        enable = true;
591      else if (strcmp (argv[arg], "off") == 0)
592        enable = false;
593    }
594  }
595
596  sc = rtems_capture_watch_global (enable);
597
598  if (sc != RTEMS_SUCCESSFUL)
599  {
600    fprintf (stdout, "error: global watch failed: %s\n",
601             rtems_status_text (sc));
602    return;
603  }
604
605  fprintf (stdout, "global watch %s.\n", enable ? "enabled" : "disabled");
606}
607
608/*
609 * rtems_capture_cli_watch_ceiling
610 *
611 * This function is a monitor command that sets watch ceiling.
612 */
613
614static char const * watch_ceiling_usage = "usage: cwceil priority\n";
615
616static void
617rtems_capture_cli_watch_ceiling (int                                argc,
618                                 char**                             argv,
619                                 const rtems_monitor_command_arg_t* command_arg RC_UNUSED,
620                                 bool                               verbose RC_UNUSED)
621{
622  rtems_status_code   sc;
623  int                 arg;
624  rtems_task_priority priority = 0;
625
626  if (argc <= 1)
627  {
628    fprintf (stdout, watch_ceiling_usage);
629    return;
630  }
631
632  for (arg = 1; arg < argc; arg++)
633  {
634    if (argv[arg][0] == '-')
635    {
636      fprintf (stdout, "warning: option -%c ignored\n", argv[arg][1]);
637    }
638    else
639    {
640      priority = strtoul (argv[arg], 0, 0);
641    }
642  }
643
644  sc = rtems_capture_watch_ceiling (priority);
645
646  if (sc != RTEMS_SUCCESSFUL)
647  {
648    fprintf (stdout, "error: watch ceiling failed: %s\n",
649             rtems_status_text (sc));
650    return;
651  }
652
653  fprintf (stdout, "watch ceiling is %" PRId32 ".\n", priority);
654}
655
656/*
657 * rtems_capture_cli_watch_floor
658 *
659 * This function is a monitor command that sets watch floor.
660 */
661
662static char const * watch_floor_usage = "usage: cwfloor priority\n";
663
664static void
665rtems_capture_cli_watch_floor (int                                argc,
666                               char**                             argv,
667                               const rtems_monitor_command_arg_t* command_arg RC_UNUSED,
668                               bool                               verbose RC_UNUSED)
669{
670  rtems_status_code   sc;
671  int                 arg;
672  rtems_task_priority priority = 0;
673
674  if (argc <= 1)
675  {
676    fprintf (stdout, watch_floor_usage);
677    return;
678  }
679
680  for (arg = 1; arg < argc; arg++)
681  {
682    if (argv[arg][0] == '-')
683    {
684      fprintf (stdout, "warning: option -%c ignored\n", argv[arg][1]);
685    }
686    else
687    {
688      priority = strtoul (argv[arg], 0, 0);
689    }
690  }
691
692  sc = rtems_capture_watch_floor (priority);
693
694  if (sc != RTEMS_SUCCESSFUL)
695  {
696    fprintf (stdout, "error: watch floor failed: %s\n",
697             rtems_status_text (sc));
698    return;
699  }
700
701  fprintf (stdout, "watch floor is %" PRId32 ".\n", priority);
702}
703
704/*
705 * rtems_capture_cli_trigger_worker
706 *
707 * This function is a monitor command that sets or clears a trigger.
708 */
709
710static char const *trigger_set_usage =
711      "usage: %s [-?] type [to name/id] [from] [from name/id]\n";
712
713static char const *trigger_set_types =
714      "  You can say 'type TASK' or 'type TO from FROM'\n" \
715      "  where TASK is the task the event is happening to\n" \
716      "  or you can say the event TO this task FROM this task.\n" \
717      "  No type defaults to 'switch'.\n" \
718      "   switch  : context switch TASK or FROM or FROM->TO\n" \
719      "   create  : create TASK, or create TO from FROM\n" \
720      "   start   : start TASK, or start TO from FROM\n" \
721      "   restart : restart TASK, or restart TO from FROM\n" \
722      "   delete  : delete TASK or delete TO from FROM\n" \
723      "   begin   : begin TASK\n" \
724      "   exitted : exitted TASK\n";
725
726/*
727 * Structure to handle the parsing of the trigger command line.
728 */
729typedef struct rtems_capture_cli_triggers
730{
731  char const *          name;
732  rtems_capture_trigger type;
733  int                   to_only;
734} rtems_capture_cli_triggers;
735
736static const rtems_capture_cli_triggers rtems_capture_cli_trigger[] =
737{
738  { "switch",  rtems_capture_switch,  0 }, /* must be first */
739  { "create",  rtems_capture_create,  0 },
740  { "start",   rtems_capture_start,   0 },
741  { "restart", rtems_capture_restart, 0 },
742  { "delete",  rtems_capture_delete,  0 },
743  { "begin",   rtems_capture_begin,   1 },
744  { "exitted", rtems_capture_exitted, 1 }
745};
746
747typedef enum rtems_capture_cli_trig_state
748{
749  trig_type,
750  trig_to,
751  trig_from_from,
752  trig_from
753} rtems_capture_cli_trig_state;
754
755#define RTEMS_CAPTURE_CLI_TRIGGERS_NUM \
756  (sizeof (rtems_capture_cli_trigger) / sizeof (rtems_capture_cli_triggers))
757
758static void
759rtems_capture_cli_trigger_worker (int set, int argc, char** argv)
760{
761  rtems_status_code          sc;
762  int                        arg;
763  int                        trigger = 0; /* switch */
764  rtems_capture_trigger_mode trigger_mode = rtems_capture_from_any;
765  bool                       trigger_set = false;
766  bool                       is_from = false;
767  bool                       is_to = false;
768  rtems_name                 name = 0;
769  rtems_id                   id = 0;
770  bool                       valid_name = false;
771  bool                       valid_id = false;
772  rtems_name                 from_name = 0;
773  rtems_id                   from_id = 0;
774  bool                       from_valid_name = false;
775  bool                       from_valid_id = false;
776  rtems_name                 to_name = 0;
777  rtems_id                   to_id = 0;
778  bool                       to_valid_name = false;
779  bool                       to_valid_id = false;
780
781  for (arg = 1; arg < argc; arg++)
782  {
783    if (argv[arg][0] == '-')
784    {
785      switch (argv[arg][1])
786      {
787        case '?':
788          fprintf (stdout, trigger_set_usage, set ? "ctset" : "ctclear");
789          fprintf (stdout, trigger_set_types);
790          return;
791        default:
792          fprintf (stdout, "warning: option -%c ignored\n", argv[arg][1]);
793          break;
794      }
795    }
796    else
797    {
798      if (!trigger_set)
799      {
800        bool found = false;
801        int  t;
802
803        for (t = 0; t < RTEMS_CAPTURE_CLI_TRIGGERS_NUM; t++)
804          if (strcmp (argv[arg], rtems_capture_cli_trigger[t].name) == 0)
805          {
806            trigger = t;
807            found = true;
808            break;
809          }
810
811        trigger_set = true;
812
813        /*
814         * If a trigger was not found assume the default and
815         * assume the parameter is a task name or id.
816         */
817        if (found)
818          continue;
819      }
820
821      if (strcmp (argv[arg], "from") == 0)
822      {
823        if (from_valid_name || from_valid_id)
824          fprintf (stdout, "warning: extra 'from' ignored\n");
825
826        is_from = true;
827        continue;
828      }
829
830      if (strcmp (argv[arg], "to") == 0)
831      {
832        if (to_valid_name || from_valid_id)
833          fprintf (stdout, "warning: extra 'to' ignored\n");
834
835        is_to = true;
836        continue;
837      }
838
839      if (!rtems_capture_cli_get_name_id (argv[arg], &valid_name, &valid_id,
840                                          &name, &id))
841        return;
842
843      if (valid_name)
844      {
845        if (!is_from && !is_to)
846          is_to = true;
847
848        if (is_from)
849        {
850          if (!from_valid_name && !from_valid_id)
851          {
852            from_valid_name = true;
853            from_name       = name;
854          }
855          else
856            fprintf (stdout, "warning: extra name arguments ignored\n");
857        }
858        else if (!to_valid_name && !to_valid_id)
859        {
860          to_valid_name = true;
861          to_name       = name;
862        }
863        else
864          fprintf (stdout, "warning: extra name arguments ignored\n");
865      }
866
867      if (valid_id)
868      {
869        if (!is_from && !is_to)
870          is_to = true;
871
872        if (is_from)
873        {
874          if (!from_valid_name && !from_valid_id)
875          {
876            from_valid_id = true;
877            from_id       = id;
878          }
879          else
880            fprintf (stdout, "warning: extra id arguments ignored\n");
881        }
882        else if (!to_valid_name && !to_valid_id)
883        {
884          to_valid_id = true;
885          to_id       = id;
886        }
887        else
888          fprintf (stdout, "warning: extra id arguments ignored\n");
889      }
890    }
891  }
892
893  if (is_from && rtems_capture_cli_trigger[trigger].to_only)
894  {
895    fprintf (stdout, "error: a %s trigger can be a TO trigger\n",
896             rtems_capture_cli_trigger[trigger].name);
897    return;
898  }
899
900  if (!to_valid_name && !to_valid_id && !from_valid_name && !from_valid_id)
901  {
902    fprintf (stdout, trigger_set_usage, set ? "ctset" : "ctclear");
903    return;
904  }
905
906  if (!is_from && !to_valid_name && !to_valid_id)
907  {
908    fprintf (stdout, "error: a %s trigger needs a TO name or id\n",
909             rtems_capture_cli_trigger[trigger].name);
910    return;
911  }
912
913  if (is_from && !from_valid_name && !from_valid_id)
914  {
915    fprintf (stdout, "error: a %s trigger needs a FROM name or id\n",
916             rtems_capture_cli_trigger[trigger].name);
917    return;
918  }
919
920  if ((from_valid_name || from_valid_id) && (to_valid_name || to_valid_id))
921    trigger_mode = rtems_capture_from_to;
922  else if (from_valid_name || from_valid_id)
923    trigger_mode = rtems_capture_to_any;
924  else if (to_valid_name || to_valid_id)
925    trigger_mode = rtems_capture_from_any;
926
927  if (set)
928    sc = rtems_capture_set_trigger (from_name, from_id, to_name, to_id,
929                                    trigger_mode,
930                                    rtems_capture_cli_trigger[trigger].type);
931  else
932    sc = rtems_capture_clear_trigger (from_name, from_id, to_name, to_id,
933                                      trigger_mode,
934                                      rtems_capture_cli_trigger[trigger].type);
935
936  if (sc != RTEMS_SUCCESSFUL)
937  {
938    fprintf (stdout, "error: %sing the trigger failed: %s\n",
939             set ? "sett" : "clear", rtems_status_text (sc));
940    return;
941  }
942
943  fprintf (stdout, "trigger %s.\n", set ? "set" : "cleared");
944}
945
946/*
947 * rtems_capture_cli_trigger_set
948 *
949 * This function is a monitor command that sets a trigger.
950 */
951
952static void
953rtems_capture_cli_trigger_set (int                                argc,
954                               char**                             argv,
955                               const rtems_monitor_command_arg_t* command_arg RC_UNUSED,
956                               bool                               verbose RC_UNUSED)
957{
958  rtems_capture_cli_trigger_worker (1, argc, argv);
959}
960
961/*
962 * rtems_capture_cli_trigger_clear
963 *
964 * This function is a monitor command that clears a trigger.
965 */
966
967static void
968rtems_capture_cli_trigger_clear (int                                argc,
969                                 char**                             argv,
970                                 const rtems_monitor_command_arg_t* command_arg RC_UNUSED,
971                                 bool                               verbose RC_UNUSED)
972{
973  rtems_capture_cli_trigger_worker (0, argc, argv);
974}
975
976/*
977 * rtems_capture_cli_trace_records
978 *
979 * This function is a monitor command that dumps trace records.
980 */
981
982static void
983rtems_capture_cli_trace_records (int                                argc,
984                                 char**                             argv,
985                                 const rtems_monitor_command_arg_t* command_arg RC_UNUSED,
986                                 bool                               verbose RC_UNUSED)
987{
988  bool                    csv = false;
989  static int              dump_total = 22;
990  int                     arg;
991
992  for (arg = 1; arg < argc; arg++)
993  {
994    if (argv[arg][0] == '-')
995    {
996      if (argv[arg][1] == 'c')
997        csv = true;
998      else
999        fprintf (stdout, "warning: option -%c ignored\n", argv[arg][1]);
1000    }
1001    else
1002    {
1003      size_t i;
1004      size_t l;
1005
1006      l = strlen (argv[arg]);
1007
1008      for (i = 0; i < l; i++)
1009        if (!isdigit ((unsigned char)argv[arg][i]))
1010        {
1011          fprintf (stdout, "error: not a number\n");
1012          return;
1013        }
1014
1015      dump_total = strtoul (argv[arg], 0, 0);
1016    }
1017  }
1018
1019  rtems_capture_print_trace_records( dump_total, csv );
1020}
1021
1022/*
1023 * rtems_capture_cli_flush
1024 *
1025 * This function is a monitor command that flushes and primes the capture
1026 * engine.
1027 */
1028
1029static void
1030rtems_capture_cli_flush (int                                argc,
1031                         char**                             argv,
1032                         const rtems_monitor_command_arg_t* command_arg RC_UNUSED,
1033                         bool                               verbose RC_UNUSED)
1034{
1035  rtems_status_code sc;
1036  bool              prime = true;
1037  int               arg;
1038
1039  for (arg = 1; arg < argc; arg++)
1040  {
1041    if (argv[arg][0] == '-')
1042    {
1043      if (argv[arg][1] == 'n')
1044        prime = false;
1045      else
1046        fprintf (stdout, "warning: option -%c ignored\n", argv[arg][1]);
1047    }
1048  }
1049
1050  sc = rtems_capture_flush (prime);
1051
1052  if (sc != RTEMS_SUCCESSFUL)
1053  {
1054    fprintf (stdout, "error: flush failed: %s\n", rtems_status_text (sc));
1055    return;
1056  }
1057
1058  fprintf (stdout, "trace buffer flushed and %s.\n",
1059           prime ? "primed" : "not primed");
1060}
1061
1062static rtems_monitor_command_entry_t rtems_capture_cli_cmds[] =
1063{
1064  {
1065    "copen",
1066    "usage: copen [-i] size",
1067    0,
1068    rtems_capture_cli_open,
1069    { 0 },
1070    0
1071  },
1072  {
1073    "cclose",
1074    "usage: cclose",
1075    0,
1076    rtems_capture_cli_close,
1077    { 0 },
1078    0
1079  },
1080  {
1081    "cenable",
1082    "usage: cenable",
1083    0,
1084    rtems_capture_cli_enable,
1085    { 0 },
1086    0
1087  },
1088  {
1089    "cdisable",
1090    "usage: cdisable",
1091    0,
1092    rtems_capture_cli_disable,
1093    { 0 },
1094    0
1095  },
1096  {
1097    "ctlist",
1098    "usage: ctlist",
1099    0,
1100     rtems_capture_cli_task_list,
1101    { 0 },
1102    0
1103  },
1104  {
1105    "cwlist",
1106    "usage: cwlist",
1107    0,
1108    rtems_capture_cli_watch_list,
1109    { 0 },
1110    0
1111  },
1112  {
1113    "cwadd",
1114    "usage: cwadd [task name] [id]",
1115    0,
1116    rtems_capture_cli_watch_add,
1117    { 0 },
1118    0
1119  },
1120  {
1121    "cwdel",
1122    "usage: cwdel [task name] [id]",
1123    0,
1124    rtems_capture_cli_watch_del,
1125    { 0 },
1126    0
1127  },
1128  {
1129    "cwctl",
1130    "usage: cwctl [task name] [id] on/off",
1131    0,
1132    rtems_capture_cli_watch_control,
1133    { 0 },
1134    0
1135  },
1136  {
1137    "cwglob",
1138    "usage: cwglob on/off",
1139    0,
1140    rtems_capture_cli_watch_global,
1141    { 0 },
1142    0
1143  },
1144  {
1145    "cwceil",
1146    "usage: cwceil priority",
1147    0,
1148    rtems_capture_cli_watch_ceiling,
1149    { 0 },
1150    0
1151  },
1152  {
1153    "cwfloor",
1154    "usage: cwfloor priority",
1155    0,
1156    rtems_capture_cli_watch_floor,
1157    { 0 },
1158    0
1159  },
1160  {
1161    "ctrace",
1162    "usage: ctrace [-c] [-r records]",
1163    0,
1164    rtems_capture_cli_trace_records,
1165    { 0 },
1166    0
1167  },
1168  {
1169    "ctset",
1170    "usage: ctset -h",
1171    0,
1172    rtems_capture_cli_trigger_set,
1173    { 0 },
1174    0
1175  },
1176  {
1177    "ctclear",
1178    "usage: ctclear -?",
1179    0,
1180    rtems_capture_cli_trigger_clear,
1181    { 0 },
1182    0
1183  },
1184  {
1185    "cflush",
1186    "usage: cflush [-n]",
1187    0,
1188    rtems_capture_cli_flush,
1189    { 0 },
1190    0
1191  }
1192};
1193
1194/*
1195 * rtems_capture_cli_init
1196 *
1197 * This function initialises the command line interface to the capture
1198 * engine.
1199 */
1200
1201rtems_status_code
1202rtems_capture_cli_init (rtems_capture_timestamp timestamp)
1203{
1204  size_t cmd;
1205
1206  capture_timestamp = timestamp;
1207
1208  for (cmd = 0;
1209       cmd < sizeof (rtems_capture_cli_cmds) / sizeof (rtems_monitor_command_entry_t);
1210       cmd++)
1211    rtems_monitor_insert_cmd (&rtems_capture_cli_cmds[cmd]);
1212
1213  return RTEMS_SUCCESSFUL;
1214}
Note: See TracBrowser for help on using the repository browser.