-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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>
- Loading branch information
Ingo Molnar
committed
May 27, 2009
1 parent
23ac9cb
commit a930d2c
Showing
6 changed files
with
177 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
/* | ||
* We put all the perf config variables in this same object | ||
* file, so that programs can link against the config parser | ||
* without having to link against all the rest of perf. | ||
*/ | ||
#include "cache.h" | ||
|
||
const char *pager_program; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
#include "cache.h" | ||
#include "run-command.h" | ||
#include "sigchain.h" | ||
|
||
/* | ||
* This is split up from the rest of git so that we can do | ||
* something different on Windows. | ||
*/ | ||
|
||
static int spawned_pager; | ||
|
||
#ifndef __MINGW32__ | ||
static void pager_preexec(void) | ||
{ | ||
/* | ||
* Work around bug in "less" by not starting it until we | ||
* have real input | ||
*/ | ||
fd_set in; | ||
|
||
FD_ZERO(&in); | ||
FD_SET(0, &in); | ||
select(1, &in, NULL, &in, NULL); | ||
|
||
setenv("LESS", "FRSX", 0); | ||
} | ||
#endif | ||
|
||
static const char *pager_argv[] = { "sh", "-c", NULL, NULL }; | ||
static struct child_process pager_process; | ||
|
||
static void wait_for_pager(void) | ||
{ | ||
fflush(stdout); | ||
fflush(stderr); | ||
/* signal EOF to pager */ | ||
close(1); | ||
close(2); | ||
finish_command(&pager_process); | ||
} | ||
|
||
static void wait_for_pager_signal(int signo) | ||
{ | ||
wait_for_pager(); | ||
sigchain_pop(signo); | ||
raise(signo); | ||
} | ||
|
||
void setup_pager(void) | ||
{ | ||
const char *pager = getenv("PERF_PAGER"); | ||
|
||
if (!isatty(1)) | ||
return; | ||
if (!pager) { | ||
if (!pager_program) | ||
perf_config(perf_default_config, NULL); | ||
pager = pager_program; | ||
} | ||
if (!pager) | ||
pager = getenv("PAGER"); | ||
if (!pager) | ||
pager = "less"; | ||
else if (!*pager || !strcmp(pager, "cat")) | ||
return; | ||
|
||
spawned_pager = 1; /* means we are emitting to terminal */ | ||
|
||
/* spawn the pager */ | ||
pager_argv[2] = pager; | ||
pager_process.argv = pager_argv; | ||
pager_process.in = -1; | ||
#ifndef __MINGW32__ | ||
pager_process.preexec_cb = pager_preexec; | ||
#endif | ||
if (start_command(&pager_process)) | ||
return; | ||
|
||
/* original process continues, but writes to the pipe */ | ||
dup2(pager_process.in, 1); | ||
if (isatty(2)) | ||
dup2(pager_process.in, 2); | ||
close(pager_process.in); | ||
|
||
/* this makes sure that the parent terminates after the pager */ | ||
sigchain_push_common(wait_for_pager_signal); | ||
atexit(wait_for_pager); | ||
} | ||
|
||
int pager_in_use(void) | ||
{ | ||
const char *env; | ||
|
||
if (spawned_pager) | ||
return 1; | ||
|
||
env = getenv("PERF_PAGER_IN_USE"); | ||
return env ? perf_config_bool("PERF_PAGER_IN_USE", env) : 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
#include "sigchain.h" | ||
#include "cache.h" | ||
|
||
#define SIGCHAIN_MAX_SIGNALS 32 | ||
|
||
struct sigchain_signal { | ||
sigchain_fun *old; | ||
int n; | ||
int alloc; | ||
}; | ||
static struct sigchain_signal signals[SIGCHAIN_MAX_SIGNALS]; | ||
|
||
static void check_signum(int sig) | ||
{ | ||
if (sig < 1 || sig >= SIGCHAIN_MAX_SIGNALS) | ||
die("BUG: signal out of range: %d", sig); | ||
} | ||
|
||
int sigchain_push(int sig, sigchain_fun f) | ||
{ | ||
struct sigchain_signal *s = signals + sig; | ||
check_signum(sig); | ||
|
||
ALLOC_GROW(s->old, s->n + 1, s->alloc); | ||
s->old[s->n] = signal(sig, f); | ||
if (s->old[s->n] == SIG_ERR) | ||
return -1; | ||
s->n++; | ||
return 0; | ||
} | ||
|
||
int sigchain_pop(int sig) | ||
{ | ||
struct sigchain_signal *s = signals + sig; | ||
check_signum(sig); | ||
if (s->n < 1) | ||
return 0; | ||
|
||
if (signal(sig, s->old[s->n - 1]) == SIG_ERR) | ||
return -1; | ||
s->n--; | ||
return 0; | ||
} | ||
|
||
void sigchain_push_common(sigchain_fun f) | ||
{ | ||
sigchain_push(SIGINT, f); | ||
sigchain_push(SIGHUP, f); | ||
sigchain_push(SIGTERM, f); | ||
sigchain_push(SIGQUIT, f); | ||
sigchain_push(SIGPIPE, f); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
#ifndef SIGCHAIN_H | ||
#define SIGCHAIN_H | ||
|
||
typedef void (*sigchain_fun)(int); | ||
|
||
int sigchain_push(int sig, sigchain_fun f); | ||
int sigchain_pop(int sig); | ||
|
||
void sigchain_push_common(sigchain_fun f); | ||
|
||
#endif /* SIGCHAIN_H */ |