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

4.115
Last change on this file since da30417b was da30417b, checked in by Chris Johns <chrisj@…>, on 03/19/15 at 07:23:12

libmisc/capture: Clean up formatting on ARM.

The printing of 64bit diff's for the timestamp did not work on ARM
so I have changed this to 32bit. A 32bit nano-second diff between
events should be more than enough time.

Print '' for POSIX thread output.

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