aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--trace-cmd.c138
1 files changed, 113 insertions, 25 deletions
diff --git a/trace-cmd.c b/trace-cmd.c
index ac14a61..b755ebe 100644
--- a/trace-cmd.c
+++ b/trace-cmd.c
@@ -145,6 +145,19 @@ static void stop_threads(void)
145 } 145 }
146} 146}
147 147
148static void flush_threads(void)
149{
150 int i;
151
152 if (!cpu_count)
153 return;
154
155 for (i = 0; i < cpu_count; i++) {
156 if (pids[i] > 0)
157 kill(pids[i], SIGUSR1);
158 }
159}
160
148void die(char *fmt, ...) 161void die(char *fmt, ...)
149{ 162{
150 va_list ap; 163 va_list ap;
@@ -569,6 +582,12 @@ static void finish(int sig)
569 finished = 1; 582 finished = 1;
570} 583}
571 584
585static void flush(int sig)
586{
587 if (recorder)
588 tracecmd_stop_recording(recorder);
589}
590
572static int create_recorder(int cpu) 591static int create_recorder(int cpu)
573{ 592{
574 char *file; 593 char *file;
@@ -582,6 +601,7 @@ static int create_recorder(int cpu)
582 return pid; 601 return pid;
583 602
584 signal(SIGINT, finish); 603 signal(SIGINT, finish);
604 signal(SIGUSR1, flush);
585 605
586 /* do not kill tasks on error */ 606 /* do not kill tasks on error */
587 cpu_count = 0; 607 cpu_count = 0;
@@ -593,7 +613,8 @@ static int create_recorder(int cpu)
593 613
594 if (!recorder) 614 if (!recorder)
595 die ("can't create recorder"); 615 die ("can't create recorder");
596 tracecmd_start_recording(recorder, sleep_time); 616 while (!finished)
617 tracecmd_start_recording(recorder, sleep_time);
597 tracecmd_free_recorder(recorder); 618 tracecmd_free_recorder(recorder);
598 619
599 exit(0); 620 exit(0);
@@ -644,6 +665,46 @@ static void record_data(void)
644 tracecmd_output_close(handle); 665 tracecmd_output_close(handle);
645} 666}
646 667
668static int trace_empty(void)
669{
670 char *path;
671 FILE *fp;
672 char *line = NULL;
673 size_t size;
674 ssize_t n;
675 int ret;
676
677 /*
678 * Test if the trace file is empty.
679 *
680 * Yes, this is a heck of a hack. What is done here
681 * is to read the trace file and ignore the
682 * lines starting with '#', and if we get a line
683 * that is without a '#' the trace is not empty.
684 * Otherwise it is.
685 */
686 path = get_tracing_file("trace");
687 fp = fopen(path, "r");
688 if (!fp)
689 die("reading '%s'", path);
690
691 do {
692 n = getline(&line, &size, fp);
693 if (!line)
694 ret = 1;
695 else if (line[0] != '#')
696 ret = 0;
697 if (n < 0)
698 ret = 1;
699 } while (line && n > 0);
700
701 put_tracing_file(path);
702
703 fclose(fp);
704
705 return ret;
706}
707
647void usage(char **argv) 708void usage(char **argv)
648{ 709{
649 char *arg = argv[0]; 710 char *arg = argv[0];
@@ -669,6 +730,9 @@ void usage(char **argv)
669 " Uses same options as record, but does not run a command.\n" 730 " Uses same options as record, but does not run a command.\n"
670 " It only enables the tracing and exits\n" 731 " It only enables the tracing and exits\n"
671 "\n" 732 "\n"
733 " %s extract [-p plugin][-O option][-o file]\n"
734 " Uses same options as record, but only reads an existing trace.\n"
735 "\n"
672 " %s stop\n" 736 " %s stop\n"
673 " Stops the tracer from recording more data.\n" 737 " Stops the tracer from recording more data.\n"
674 " Used in conjunction with start\n" 738 " Used in conjunction with start\n"
@@ -689,7 +753,7 @@ void usage(char **argv)
689 " -e list available events\n" 753 " -e list available events\n"
690 " -p list available plugins\n" 754 " -p list available plugins\n"
691 " -o list available options\n" 755 " -o list available options\n"
692 "\n", p, TRACECMD_VERSION, p, p, p, p, p, p); 756 "\n", p, TRACECMD_VERSION, p, p, p, p, p, p, p);
693 exit(-1); 757 exit(-1);
694} 758}
695 759
@@ -705,6 +769,7 @@ int main (int argc, char **argv)
705 int events = 0; 769 int events = 0;
706 int options = 0; 770 int options = 0;
707 int record = 0; 771 int record = 0;
772 int extract = 0;
708 int run_command = 0; 773 int run_command = 0;
709 int neg_event = 0; 774 int neg_event = 0;
710 int fset; 775 int fset;
@@ -721,7 +786,8 @@ int main (int argc, char **argv)
721 trace_report(argc, argv); 786 trace_report(argc, argv);
722 exit(0); 787 exit(0);
723 } else if ((record = (strcmp(argv[1], "record") == 0)) || 788 } else if ((record = (strcmp(argv[1], "record") == 0)) ||
724 (strcmp(argv[1], "start") == 0)) { 789 (strcmp(argv[1], "start") == 0) ||
790 ((extract = strcmp(argv[1], "extract") == 0))) {
725 791
726 while ((c = getopt(argc-1, argv+1, "+he:p:do:O:s:v")) >= 0) { 792 while ((c = getopt(argc-1, argv+1, "+he:p:do:O:s:v")) >= 0) {
727 switch (c) { 793 switch (c) {
@@ -729,6 +795,8 @@ int main (int argc, char **argv)
729 usage(argv); 795 usage(argv);
730 break; 796 break;
731 case 'e': 797 case 'e':
798 if (extract)
799 usage(argv);
732 events = 1; 800 events = 1;
733 event = malloc_or_die(sizeof(*event)); 801 event = malloc_or_die(sizeof(*event));
734 event->event = optarg; 802 event->event = optarg;
@@ -737,6 +805,8 @@ int main (int argc, char **argv)
737 event_selection = event; 805 event_selection = event;
738 break; 806 break;
739 case 'v': 807 case 'v':
808 if (extract)
809 usage(argv);
740 neg_event = 1; 810 neg_event = 1;
741 break; 811 break;
742 case 'p': 812 case 'p':
@@ -746,10 +816,12 @@ int main (int argc, char **argv)
746 fprintf(stderr, " plugin %s\n", plugin); 816 fprintf(stderr, " plugin %s\n", plugin);
747 break; 817 break;
748 case 'd': 818 case 'd':
819 if (extract)
820 usage(argv);
749 disable = 1; 821 disable = 1;
750 break; 822 break;
751 case 'o': 823 case 'o':
752 if (!record) 824 if (!record && !extract)
753 die("start does not take output\n" 825 die("start does not take output\n"
754 "Did you mean 'record'?"); 826 "Did you mean 'record'?");
755 if (output) 827 if (output)
@@ -761,6 +833,8 @@ int main (int argc, char **argv)
761 set_option(option); 833 set_option(option);
762 break; 834 break;
763 case 's': 835 case 's':
836 if (extract)
837 usage(argv);
764 sleep_time = atoi(optarg); 838 sleep_time = atoi(optarg);
765 break; 839 break;
766 } 840 }
@@ -824,20 +898,26 @@ int main (int argc, char **argv)
824 if (!record) 898 if (!record)
825 die("Command start does not take any commands\n" 899 die("Command start does not take any commands\n"
826 "Did you mean 'record'?"); 900 "Did you mean 'record'?");
901 if (extract)
902 die("Command extract does not take any commands\n"
903 "Did you mean 'record'?");
827 run_command = 1; 904 run_command = 1;
828 } 905 }
829 906
830 if (!events && !plugin) 907 if (!events && !plugin && !extract)
831 die("no event or plugin was specified... aborting"); 908 die("no event or plugin was specified... aborting");
832 909
833 if (output) 910 if (output)
834 output_file = output; 911 output_file = output;
835 912
836 fset = set_ftrace(!disable); 913 if (!extract) {
837 disable_all(); 914 fset = set_ftrace(!disable);
915 disable_all();
916
917 if (events)
918 enable_events();
919 }
838 920
839 if (events)
840 enable_events();
841 if (plugin) { 921 if (plugin) {
842 /* 922 /*
843 * Latency tracers just save the trace and kill 923 * Latency tracers just save the trace and kill
@@ -853,33 +933,41 @@ int main (int argc, char **argv)
853 if (fset < 0 && (strcmp(plugin, "function") == 0 || 933 if (fset < 0 && (strcmp(plugin, "function") == 0 ||
854 strcmp(plugin, "function_graph") == 0)) 934 strcmp(plugin, "function_graph") == 0))
855 die("function tracing not configured on this kernel"); 935 die("function tracing not configured on this kernel");
856 set_plugin(plugin); 936 if (!extract)
937 set_plugin(plugin);
857 } 938 }
858 939
859 if (record) { 940 if (record || extract) {
860 if (!latency) 941 if (!latency)
861 start_threads(); 942 start_threads();
862 signal(SIGINT, finish); 943 signal(SIGINT, finish);
863 } 944 }
864 945
865 enable_tracing(); 946 if (extract) {
866 if (latency) 947 while (!finished && !trace_empty()) {
867 reset_max_latency(); 948 flush_threads();
949 sleep(1);
950 }
951 } else {
952 enable_tracing();
953 if (latency)
954 reset_max_latency();
868 955
869 if (!record) 956 if (!record)
870 exit(0); 957 exit(0);
958
959 if (run_command)
960 run_cmd((argc - optind) - 1, &argv[optind + 1]);
961 else {
962 /* sleep till we are woken with Ctrl^C */
963 printf("Hit Ctrl^C to stop recording\n");
964 while (!finished)
965 sleep(10);
966 }
871 967
872 if (run_command) 968 disable_tracing();
873 run_cmd((argc - optind) - 1, &argv[optind + 1]);
874 else {
875 /* sleep till we are woken with Ctrl^C */
876 printf("Hit Ctrl^C to stop recording\n");
877 while (!finished)
878 sleep(10);
879 } 969 }
880 970
881 disable_tracing();
882
883 stop_threads(); 971 stop_threads();
884 972
885 record_data(); 973 record_data();