aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/evlist.c
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2011-11-09 05:47:15 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2011-11-28 07:26:14 -0500
commit35b9d88ecd8c5fb720ba0dd325262f356d0b03e7 (patch)
tree536902f734862d5b04a6122c81386fddb19f4bcd /tools/perf/util/evlist.c
parent0f82ebc452f921590e216b28eee0b41f5e434a48 (diff)
perf evlist: Introduce {prepare,start}_workload refactored from 'perf record'
So that we can easily start a workload in other tools. Cc: David Ahern <dsahern@gmail.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Link: http://lkml.kernel.org/n/tip-zdsksd4aphu0nltg2lpwsw3x@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util/evlist.c')
-rw-r--r--tools/perf/util/evlist.c96
1 files changed, 96 insertions, 0 deletions
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index b774341e797f..a472247af191 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -13,6 +13,7 @@
13#include "thread_map.h" 13#include "thread_map.h"
14#include "evlist.h" 14#include "evlist.h"
15#include "evsel.h" 15#include "evsel.h"
16#include <unistd.h>
16 17
17#include "parse-events.h" 18#include "parse-events.h"
18 19
@@ -33,6 +34,7 @@ void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus,
33 INIT_HLIST_HEAD(&evlist->heads[i]); 34 INIT_HLIST_HEAD(&evlist->heads[i]);
34 INIT_LIST_HEAD(&evlist->entries); 35 INIT_LIST_HEAD(&evlist->entries);
35 perf_evlist__set_maps(evlist, cpus, threads); 36 perf_evlist__set_maps(evlist, cpus, threads);
37 evlist->workload.pid = -1;
36} 38}
37 39
38struct perf_evlist *perf_evlist__new(struct cpu_map *cpus, 40struct perf_evlist *perf_evlist__new(struct cpu_map *cpus,
@@ -674,3 +676,97 @@ out_err:
674 676
675 return err; 677 return err;
676} 678}
679
680int perf_evlist__prepare_workload(struct perf_evlist *evlist,
681 struct perf_record_opts *opts,
682 const char *argv[])
683{
684 int child_ready_pipe[2], go_pipe[2];
685 char bf;
686
687 if (pipe(child_ready_pipe) < 0) {
688 perror("failed to create 'ready' pipe");
689 return -1;
690 }
691
692 if (pipe(go_pipe) < 0) {
693 perror("failed to create 'go' pipe");
694 goto out_close_ready_pipe;
695 }
696
697 evlist->workload.pid = fork();
698 if (evlist->workload.pid < 0) {
699 perror("failed to fork");
700 goto out_close_pipes;
701 }
702
703 if (!evlist->workload.pid) {
704 if (opts->pipe_output)
705 dup2(2, 1);
706
707 close(child_ready_pipe[0]);
708 close(go_pipe[1]);
709 fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC);
710
711 /*
712 * Do a dummy execvp to get the PLT entry resolved,
713 * so we avoid the resolver overhead on the real
714 * execvp call.
715 */
716 execvp("", (char **)argv);
717
718 /*
719 * Tell the parent we're ready to go
720 */
721 close(child_ready_pipe[1]);
722
723 /*
724 * Wait until the parent tells us to go.
725 */
726 if (read(go_pipe[0], &bf, 1) == -1)
727 perror("unable to read pipe");
728
729 execvp(argv[0], (char **)argv);
730
731 perror(argv[0]);
732 kill(getppid(), SIGUSR1);
733 exit(-1);
734 }
735
736 if (!opts->system_wide && opts->target_tid == -1 && opts->target_pid == -1)
737 evlist->threads->map[0] = evlist->workload.pid;
738
739 close(child_ready_pipe[1]);
740 close(go_pipe[0]);
741 /*
742 * wait for child to settle
743 */
744 if (read(child_ready_pipe[0], &bf, 1) == -1) {
745 perror("unable to read pipe");
746 goto out_close_pipes;
747 }
748
749 evlist->workload.cork_fd = go_pipe[1];
750 close(child_ready_pipe[0]);
751 return 0;
752
753out_close_pipes:
754 close(go_pipe[0]);
755 close(go_pipe[1]);
756out_close_ready_pipe:
757 close(child_ready_pipe[0]);
758 close(child_ready_pipe[1]);
759 return -1;
760}
761
762int perf_evlist__start_workload(struct perf_evlist *evlist)
763{
764 if (evlist->workload.cork_fd > 0) {
765 /*
766 * Remove the cork, let it rip!
767 */
768 return close(evlist->workload.cork_fd);
769 }
770
771 return 0;
772}