Messages in this thread Patch in this message | | | From | Namhyung Kim <> | Subject | [PATCH 1/5] perf tools: Introduce struct perf_log | Date | Mon, 13 Jan 2014 17:00:53 +0900 |
| |
Add new functions to save error messages in a temp file. It'll be used by some UI front-ends to see the messages.
Signed-off-by: Namhyung Kim <namhyung@kernel.org> --- tools/perf/Makefile.perf | 1 + tools/perf/perf.c | 5 +++ tools/perf/util/debug.h | 15 +++++++ tools/perf/util/log.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 136 insertions(+) create mode 100644 tools/perf/util/log.c
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index 87d7726cee2d..2b5252f09c04 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -372,6 +372,7 @@ LIB_OBJS += $(OUTPUT)util/stat.o LIB_OBJS += $(OUTPUT)util/record.o LIB_OBJS += $(OUTPUT)util/srcline.o LIB_OBJS += $(OUTPUT)util/data.o +LIB_OBJS += $(OUTPUT)util/log.o LIB_OBJS += $(OUTPUT)ui/setup.o LIB_OBJS += $(OUTPUT)ui/helpline.o diff --git a/tools/perf/perf.c b/tools/perf/perf.c index 431798a4110d..f7c806d264a2 100644 --- a/tools/perf/perf.c +++ b/tools/perf/perf.c @@ -10,6 +10,7 @@ #include "util/exec_cmd.h" #include "util/cache.h" +#include "util/debug.h" #include "util/quote.h" #include "util/run-command.h" #include "util/parse-events.h" @@ -524,6 +525,9 @@ int main(int argc, const char **argv) */ pthread__block_sigwinch(); + if (perf_log__init() < 0) + fprintf(stderr, "Failed to init temporary log file.. ignoring\n"); + while (1) { static int done_help; int was_alias = run_argv(&argc, &argv); @@ -547,5 +551,6 @@ int main(int argc, const char **argv) fprintf(stderr, "Failed to run command '%s': %s\n", cmd, strerror(errno)); out: + perf_log__exit(); return 1; } diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h index 443694c36b03..2d69e9fa6499 100644 --- a/tools/perf/util/debug.h +++ b/tools/perf/util/debug.h @@ -19,4 +19,19 @@ int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2))); void pr_stat(const char *fmt, ...); +struct perf_log { + FILE *fp; + off_t *linemap; + u32 lines; + u32 nr_alloc; + bool seen_newline; +}; + +extern struct perf_log perf_log; + +int perf_log__init(void); +int perf_log__exit(void); +void perf_log__add(const char *msg); +void perf_log__addv(const char *fmt, va_list ap); + #endif /* __PERF_DEBUG_H */ diff --git a/tools/perf/util/log.c b/tools/perf/util/log.c new file mode 100644 index 000000000000..cb94417da435 --- /dev/null +++ b/tools/perf/util/log.c @@ -0,0 +1,115 @@ +#include <stdio.h> +#include <stdlib.h> +#include "util/debug.h" + +#define LINEMAP_GROW 128 + +struct perf_log perf_log = { + .seen_newline = true, +}; + +int perf_log__init(void) +{ + FILE *fp = tmpfile(); + if (fp == NULL) + return -1; + + perf_log.fp = fp; + + return 0; +} + +int perf_log__exit(void) +{ + FILE *fp = perf_log.fp; + if (fp) + fclose(fp); + + free(perf_log.linemap); + + perf_log.fp = NULL; + perf_log.linemap = NULL; + return 0; +} + +static int grow_linemap(struct perf_log *log) +{ + off_t *newmap; + int newsize = log->nr_alloc + LINEMAP_GROW; + + newmap = realloc(log->linemap, newsize * sizeof(*log->linemap)); + if (newmap == NULL) + return -1; + + log->nr_alloc = newsize; + log->linemap = newmap; + return 0; +} + +static int __add_to_linemap(struct perf_log *log, off_t idx) +{ + if (log->lines == log->nr_alloc) + if (grow_linemap(log) < 0) + return -1; + + log->linemap[log->lines++] = idx; + return 0; +} + +static void add_to_linemap(struct perf_log *log, const char *msg, off_t base) +{ + const char *pos; + + if (strlen(msg) == 0) + return; + + if (log->seen_newline) { + if (__add_to_linemap(log, base) < 0) + return; + } + + if ((pos = strchr(msg, '\n')) != NULL) { + log->seen_newline = true; + pos++; + add_to_linemap(log, pos, base + (pos - msg)); + } else { + log->seen_newline = false; + } +} + +void perf_log__add(const char *msg) +{ + FILE *fp = perf_log.fp; + off_t offset; + u32 saved_lines; + size_t msglen; + + if (fp == NULL) + return; + + pthread_mutex_lock(&ui__lock); + + offset = ftello(fp); + saved_lines = perf_log.lines; + msglen = strlen(msg); + + add_to_linemap(&perf_log, msg, offset); + + if (fwrite(msg, 1, msglen, fp) != msglen) { + /* restore original offset */ + fseeko(fp, offset, SEEK_SET); + perf_log.lines = saved_lines; + } + pthread_mutex_unlock(&ui__lock); +} + +void perf_log__addv(const char *fmt, va_list ap) +{ + char buf[4096]; + + if (perf_log.fp == NULL) + return; + + vsnprintf(buf, sizeof(buf), fmt, ap); + perf_log__add(buf); +} -- 1.7.11.7
| |