aboutsummaryrefslogtreecommitdiffstats
path: root/Documentation/perf_counter
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2009-05-27 03:50:13 -0400
committerIngo Molnar <mingo@elte.hu>2009-05-27 03:59:00 -0400
commita930d2c0d0a685ab955472b08baad041cc5edb4a (patch)
tree988e0da70e64ef72437058828974d946328280af /Documentation/perf_counter
parent23ac9cbed82b00ca3520bb81dbe9ea3b7a936a1b (diff)
perf_counter tools: Add built-in pager support
Add Git's pager.c (and sigchain) code. A command only has to call setup_pager() to get paged interactive output. Non-interactive (redirected, command-piped, etc.) uses are not affected. Update perf-report to make use of this. [ Impact: new feature ] Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com> Cc: Marcelo Tosatti <mtosatti@redhat.com> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: John Kacur <jkacur@redhat.com> LKML-Reference: <new-submission> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'Documentation/perf_counter')
-rw-r--r--Documentation/perf_counter/Makefile4
-rw-r--r--Documentation/perf_counter/builtin-report.c3
-rw-r--r--Documentation/perf_counter/util/environment.c8
-rw-r--r--Documentation/perf_counter/util/pager.c99
-rw-r--r--Documentation/perf_counter/util/sigchain.c52
-rw-r--r--Documentation/perf_counter/util/sigchain.h11
6 files changed, 177 insertions, 0 deletions
diff --git a/Documentation/perf_counter/Makefile b/Documentation/perf_counter/Makefile
index efb05892db69..51b13f989833 100644
--- a/Documentation/perf_counter/Makefile
+++ b/Documentation/perf_counter/Makefile
@@ -297,11 +297,13 @@ LIB_H += util/util.h
297LIB_H += util/help.h 297LIB_H += util/help.h
298LIB_H += util/strbuf.h 298LIB_H += util/strbuf.h
299LIB_H += util/run-command.h 299LIB_H += util/run-command.h
300LIB_H += util/sigchain.h
300 301
301LIB_OBJS += util/abspath.o 302LIB_OBJS += util/abspath.o
302LIB_OBJS += util/alias.o 303LIB_OBJS += util/alias.o
303LIB_OBJS += util/config.o 304LIB_OBJS += util/config.o
304LIB_OBJS += util/ctype.o 305LIB_OBJS += util/ctype.o
306LIB_OBJS += util/environment.o
305LIB_OBJS += util/exec_cmd.o 307LIB_OBJS += util/exec_cmd.o
306LIB_OBJS += util/help.o 308LIB_OBJS += util/help.o
307LIB_OBJS += util/levenshtein.o 309LIB_OBJS += util/levenshtein.o
@@ -314,6 +316,8 @@ LIB_OBJS += util/quote.o
314LIB_OBJS += util/strbuf.o 316LIB_OBJS += util/strbuf.o
315LIB_OBJS += util/usage.o 317LIB_OBJS += util/usage.o
316LIB_OBJS += util/wrapper.o 318LIB_OBJS += util/wrapper.o
319LIB_OBJS += util/sigchain.o
320LIB_OBJS += util/pager.o
317 321
318BUILTIN_OBJS += builtin-help.o 322BUILTIN_OBJS += builtin-help.o
319BUILTIN_OBJS += builtin-record.o 323BUILTIN_OBJS += builtin-record.o
diff --git a/Documentation/perf_counter/builtin-report.c b/Documentation/perf_counter/builtin-report.c
index e2712cd06310..9aef7c54483e 100644
--- a/Documentation/perf_counter/builtin-report.c
+++ b/Documentation/perf_counter/builtin-report.c
@@ -7,6 +7,7 @@
7#include <ctype.h> 7#include <ctype.h>
8 8
9#include "util/list.h" 9#include "util/list.h"
10#include "util/cache.h"
10#include "util/rbtree.h" 11#include "util/rbtree.h"
11 12
12#include "perf.h" 13#include "perf.h"
@@ -992,5 +993,7 @@ int cmd_report(int argc, const char **argv, const char *prefix)
992 993
993 parse_options(argc, argv, options, report_usage, 0); 994 parse_options(argc, argv, options, report_usage, 0);
994 995
996 setup_pager();
997
995 return __cmd_report(); 998 return __cmd_report();
996} 999}
diff --git a/Documentation/perf_counter/util/environment.c b/Documentation/perf_counter/util/environment.c
new file mode 100644
index 000000000000..9b1c8199e729
--- /dev/null
+++ b/Documentation/perf_counter/util/environment.c
@@ -0,0 +1,8 @@
1/*
2 * We put all the perf config variables in this same object
3 * file, so that programs can link against the config parser
4 * without having to link against all the rest of perf.
5 */
6#include "cache.h"
7
8const char *pager_program;
diff --git a/Documentation/perf_counter/util/pager.c b/Documentation/perf_counter/util/pager.c
new file mode 100644
index 000000000000..a28bccae5458
--- /dev/null
+++ b/Documentation/perf_counter/util/pager.c
@@ -0,0 +1,99 @@
1#include "cache.h"
2#include "run-command.h"
3#include "sigchain.h"
4
5/*
6 * This is split up from the rest of git so that we can do
7 * something different on Windows.
8 */
9
10static int spawned_pager;
11
12#ifndef __MINGW32__
13static void pager_preexec(void)
14{
15 /*
16 * Work around bug in "less" by not starting it until we
17 * have real input
18 */
19 fd_set in;
20
21 FD_ZERO(&in);
22 FD_SET(0, &in);
23 select(1, &in, NULL, &in, NULL);
24
25 setenv("LESS", "FRSX", 0);
26}
27#endif
28
29static const char *pager_argv[] = { "sh", "-c", NULL, NULL };
30static struct child_process pager_process;
31
32static void wait_for_pager(void)
33{
34 fflush(stdout);
35 fflush(stderr);
36 /* signal EOF to pager */
37 close(1);
38 close(2);
39 finish_command(&pager_process);
40}
41
42static void wait_for_pager_signal(int signo)
43{
44 wait_for_pager();
45 sigchain_pop(signo);
46 raise(signo);
47}
48
49void setup_pager(void)
50{
51 const char *pager = getenv("PERF_PAGER");
52
53 if (!isatty(1))
54 return;
55 if (!pager) {
56 if (!pager_program)
57 perf_config(perf_default_config, NULL);
58 pager = pager_program;
59 }
60 if (!pager)
61 pager = getenv("PAGER");
62 if (!pager)
63 pager = "less";
64 else if (!*pager || !strcmp(pager, "cat"))
65 return;
66
67 spawned_pager = 1; /* means we are emitting to terminal */
68
69 /* spawn the pager */
70 pager_argv[2] = pager;
71 pager_process.argv = pager_argv;
72 pager_process.in = -1;
73#ifndef __MINGW32__
74 pager_process.preexec_cb = pager_preexec;
75#endif
76 if (start_command(&pager_process))
77 return;
78
79 /* original process continues, but writes to the pipe */
80 dup2(pager_process.in, 1);
81 if (isatty(2))
82 dup2(pager_process.in, 2);
83 close(pager_process.in);
84
85 /* this makes sure that the parent terminates after the pager */
86 sigchain_push_common(wait_for_pager_signal);
87 atexit(wait_for_pager);
88}
89
90int pager_in_use(void)
91{
92 const char *env;
93
94 if (spawned_pager)
95 return 1;
96
97 env = getenv("PERF_PAGER_IN_USE");
98 return env ? perf_config_bool("PERF_PAGER_IN_USE", env) : 0;
99}
diff --git a/Documentation/perf_counter/util/sigchain.c b/Documentation/perf_counter/util/sigchain.c
new file mode 100644
index 000000000000..1118b99e57d3
--- /dev/null
+++ b/Documentation/perf_counter/util/sigchain.c
@@ -0,0 +1,52 @@
1#include "sigchain.h"
2#include "cache.h"
3
4#define SIGCHAIN_MAX_SIGNALS 32
5
6struct sigchain_signal {
7 sigchain_fun *old;
8 int n;
9 int alloc;
10};
11static struct sigchain_signal signals[SIGCHAIN_MAX_SIGNALS];
12
13static void check_signum(int sig)
14{
15 if (sig < 1 || sig >= SIGCHAIN_MAX_SIGNALS)
16 die("BUG: signal out of range: %d", sig);
17}
18
19int sigchain_push(int sig, sigchain_fun f)
20{
21 struct sigchain_signal *s = signals + sig;
22 check_signum(sig);
23
24 ALLOC_GROW(s->old, s->n + 1, s->alloc);
25 s->old[s->n] = signal(sig, f);
26 if (s->old[s->n] == SIG_ERR)
27 return -1;
28 s->n++;
29 return 0;
30}
31
32int sigchain_pop(int sig)
33{
34 struct sigchain_signal *s = signals + sig;
35 check_signum(sig);
36 if (s->n < 1)
37 return 0;
38
39 if (signal(sig, s->old[s->n - 1]) == SIG_ERR)
40 return -1;
41 s->n--;
42 return 0;
43}
44
45void sigchain_push_common(sigchain_fun f)
46{
47 sigchain_push(SIGINT, f);
48 sigchain_push(SIGHUP, f);
49 sigchain_push(SIGTERM, f);
50 sigchain_push(SIGQUIT, f);
51 sigchain_push(SIGPIPE, f);
52}
diff --git a/Documentation/perf_counter/util/sigchain.h b/Documentation/perf_counter/util/sigchain.h
new file mode 100644
index 000000000000..618083bce0c6
--- /dev/null
+++ b/Documentation/perf_counter/util/sigchain.h
@@ -0,0 +1,11 @@
1#ifndef SIGCHAIN_H
2#define SIGCHAIN_H
3
4typedef void (*sigchain_fun)(int);
5
6int sigchain_push(int sig, sigchain_fun f);
7int sigchain_pop(int sig);
8
9void sigchain_push_common(sigchain_fun f);
10
11#endif /* SIGCHAIN_H */