[PATCH v3 06/30] perf llvm: Extract helpers in llvm-utils.c

2016-11-25 Thread Wang Nan
Following commits will use builtin clang to compile BPF script.
llvm__get_kbuild_opts() and llvm__get_nr_cpus() are extracted to help
building '-DKERNEL_VERSION_CODE' and '-D__NR_CPUS__' macros.

Doing object dumping in bpf loader, so futher builtin clang compiling
needn't consider it.

Signed-off-by: Wang Nan 
Cc: Arnaldo Carvalho de Melo 
Cc: Alexei Starovoitov 
Cc: He Kuang 
Cc: Jiri Olsa 
Cc: Zefan Li 
Cc: pi3or...@163.com
---
 tools/perf/util/bpf-loader.c |  4 +++
 tools/perf/util/llvm-utils.c | 76 +---
 tools/perf/util/llvm-utils.h |  6 
 3 files changed, 68 insertions(+), 18 deletions(-)

diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index a5fd275..cf16b941 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -90,6 +90,10 @@ struct bpf_object *bpf__prepare_load(const char *filename, 
bool source)
if (err)
return ERR_PTR(-BPF_LOADER_ERRNO__COMPILE);
obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, filename);
+
+   if (!IS_ERR(obj) && llvm_param.dump_obj)
+   llvm__dump_obj(filename, obj_buf, obj_buf_sz);
+
free(obj_buf);
} else
obj = bpf_object__open(filename);
diff --git a/tools/perf/util/llvm-utils.c b/tools/perf/util/llvm-utils.c
index 27b6f303..b23ff44 100644
--- a/tools/perf/util/llvm-utils.c
+++ b/tools/perf/util/llvm-utils.c
@@ -7,6 +7,7 @@
 #include 
 #include 
 #include 
+#include 
 #include "debug.h"
 #include "llvm-utils.h"
 #include "config.h"
@@ -282,9 +283,10 @@ static const char *kinc_fetch_script =
 "rm -rf $TMPDIR\n"
 "exit $RET\n";
 
-static inline void
-get_kbuild_opts(char **kbuild_dir, char **kbuild_include_opts)
+void llvm__get_kbuild_opts(char **kbuild_dir, char **kbuild_include_opts)
 {
+   static char *saved_kbuild_dir;
+   static char *saved_kbuild_include_opts;
int err;
 
if (!kbuild_dir || !kbuild_include_opts)
@@ -293,10 +295,28 @@ get_kbuild_opts(char **kbuild_dir, char 
**kbuild_include_opts)
*kbuild_dir = NULL;
*kbuild_include_opts = NULL;
 
+   if (saved_kbuild_dir && saved_kbuild_include_opts &&
+   !IS_ERR(saved_kbuild_dir) && !IS_ERR(saved_kbuild_include_opts)) {
+   *kbuild_dir = strdup(saved_kbuild_dir);
+   *kbuild_include_opts = strdup(saved_kbuild_include_opts);
+
+   if (*kbuild_dir && *kbuild_include_opts)
+   return;
+
+   zfree(kbuild_dir);
+   zfree(kbuild_include_opts);
+   /*
+* Don't fall through: it may breaks saved_kbuild_dir and
+* saved_kbuild_include_opts if detect them again when
+* memory is low.
+*/
+   return;
+   }
+
if (llvm_param.kbuild_dir && !llvm_param.kbuild_dir[0]) {
pr_debug("[llvm.kbuild-dir] is set to \"\" deliberately.\n");
pr_debug("Skip kbuild options detection.\n");
-   return;
+   goto errout;
}
 
err = detect_kbuild_dir(kbuild_dir);
@@ -306,7 +326,7 @@ get_kbuild_opts(char **kbuild_dir, char 
**kbuild_include_opts)
 "Hint:\tSet correct kbuild directory using 'kbuild-dir' option in [llvm]\n"
 " \tsection of ~/.perfconfig or set it to \"\" to suppress kbuild\n"
 " \tdetection.\n\n");
-   return;
+   goto errout;
}
 
pr_debug("Kernel build dir is set to %s\n", *kbuild_dir);
@@ -325,14 +345,43 @@ get_kbuild_opts(char **kbuild_dir, char 
**kbuild_include_opts)
 
free(*kbuild_dir);
*kbuild_dir = NULL;
-   return;
+   goto errout;
}
 
pr_debug("include option is set to %s\n", *kbuild_include_opts);
+
+   saved_kbuild_dir = strdup(*kbuild_dir);
+   saved_kbuild_include_opts = strdup(*kbuild_include_opts);
+
+   if (!saved_kbuild_dir || !saved_kbuild_include_opts) {
+   zfree(_kbuild_dir);
+   zfree(_kbuild_include_opts);
+   }
+   return;
+errout:
+   saved_kbuild_dir = ERR_PTR(-EINVAL);
+   saved_kbuild_include_opts = ERR_PTR(-EINVAL);
 }
 
-static void
-dump_obj(const char *path, void *obj_buf, size_t size)
+int llvm__get_nr_cpus(void)
+{
+   static int nr_cpus_avail = 0;
+   char serr[STRERR_BUFSIZE];
+
+   if (nr_cpus_avail > 0)
+   return nr_cpus_avail;
+
+   nr_cpus_avail = sysconf(_SC_NPROCESSORS_CONF);
+   if (nr_cpus_avail <= 0) {
+   pr_err(
+"WARNING:\tunable to get available CPUs in this system: %s\n"
+"\tUse 128 instead.\n", str_error_r(errno, serr, sizeof(serr)));
+   nr_cpus_avail = 128;
+   }
+   return nr_cpus_avail;
+}
+
+void llvm__dump_obj(const 

[PATCH v3 06/30] perf llvm: Extract helpers in llvm-utils.c

2016-11-25 Thread Wang Nan
Following commits will use builtin clang to compile BPF script.
llvm__get_kbuild_opts() and llvm__get_nr_cpus() are extracted to help
building '-DKERNEL_VERSION_CODE' and '-D__NR_CPUS__' macros.

Doing object dumping in bpf loader, so futher builtin clang compiling
needn't consider it.

Signed-off-by: Wang Nan 
Cc: Arnaldo Carvalho de Melo 
Cc: Alexei Starovoitov 
Cc: He Kuang 
Cc: Jiri Olsa 
Cc: Zefan Li 
Cc: pi3or...@163.com
---
 tools/perf/util/bpf-loader.c |  4 +++
 tools/perf/util/llvm-utils.c | 76 +---
 tools/perf/util/llvm-utils.h |  6 
 3 files changed, 68 insertions(+), 18 deletions(-)

diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index a5fd275..cf16b941 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -90,6 +90,10 @@ struct bpf_object *bpf__prepare_load(const char *filename, 
bool source)
if (err)
return ERR_PTR(-BPF_LOADER_ERRNO__COMPILE);
obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, filename);
+
+   if (!IS_ERR(obj) && llvm_param.dump_obj)
+   llvm__dump_obj(filename, obj_buf, obj_buf_sz);
+
free(obj_buf);
} else
obj = bpf_object__open(filename);
diff --git a/tools/perf/util/llvm-utils.c b/tools/perf/util/llvm-utils.c
index 27b6f303..b23ff44 100644
--- a/tools/perf/util/llvm-utils.c
+++ b/tools/perf/util/llvm-utils.c
@@ -7,6 +7,7 @@
 #include 
 #include 
 #include 
+#include 
 #include "debug.h"
 #include "llvm-utils.h"
 #include "config.h"
@@ -282,9 +283,10 @@ static const char *kinc_fetch_script =
 "rm -rf $TMPDIR\n"
 "exit $RET\n";
 
-static inline void
-get_kbuild_opts(char **kbuild_dir, char **kbuild_include_opts)
+void llvm__get_kbuild_opts(char **kbuild_dir, char **kbuild_include_opts)
 {
+   static char *saved_kbuild_dir;
+   static char *saved_kbuild_include_opts;
int err;
 
if (!kbuild_dir || !kbuild_include_opts)
@@ -293,10 +295,28 @@ get_kbuild_opts(char **kbuild_dir, char 
**kbuild_include_opts)
*kbuild_dir = NULL;
*kbuild_include_opts = NULL;
 
+   if (saved_kbuild_dir && saved_kbuild_include_opts &&
+   !IS_ERR(saved_kbuild_dir) && !IS_ERR(saved_kbuild_include_opts)) {
+   *kbuild_dir = strdup(saved_kbuild_dir);
+   *kbuild_include_opts = strdup(saved_kbuild_include_opts);
+
+   if (*kbuild_dir && *kbuild_include_opts)
+   return;
+
+   zfree(kbuild_dir);
+   zfree(kbuild_include_opts);
+   /*
+* Don't fall through: it may breaks saved_kbuild_dir and
+* saved_kbuild_include_opts if detect them again when
+* memory is low.
+*/
+   return;
+   }
+
if (llvm_param.kbuild_dir && !llvm_param.kbuild_dir[0]) {
pr_debug("[llvm.kbuild-dir] is set to \"\" deliberately.\n");
pr_debug("Skip kbuild options detection.\n");
-   return;
+   goto errout;
}
 
err = detect_kbuild_dir(kbuild_dir);
@@ -306,7 +326,7 @@ get_kbuild_opts(char **kbuild_dir, char 
**kbuild_include_opts)
 "Hint:\tSet correct kbuild directory using 'kbuild-dir' option in [llvm]\n"
 " \tsection of ~/.perfconfig or set it to \"\" to suppress kbuild\n"
 " \tdetection.\n\n");
-   return;
+   goto errout;
}
 
pr_debug("Kernel build dir is set to %s\n", *kbuild_dir);
@@ -325,14 +345,43 @@ get_kbuild_opts(char **kbuild_dir, char 
**kbuild_include_opts)
 
free(*kbuild_dir);
*kbuild_dir = NULL;
-   return;
+   goto errout;
}
 
pr_debug("include option is set to %s\n", *kbuild_include_opts);
+
+   saved_kbuild_dir = strdup(*kbuild_dir);
+   saved_kbuild_include_opts = strdup(*kbuild_include_opts);
+
+   if (!saved_kbuild_dir || !saved_kbuild_include_opts) {
+   zfree(_kbuild_dir);
+   zfree(_kbuild_include_opts);
+   }
+   return;
+errout:
+   saved_kbuild_dir = ERR_PTR(-EINVAL);
+   saved_kbuild_include_opts = ERR_PTR(-EINVAL);
 }
 
-static void
-dump_obj(const char *path, void *obj_buf, size_t size)
+int llvm__get_nr_cpus(void)
+{
+   static int nr_cpus_avail = 0;
+   char serr[STRERR_BUFSIZE];
+
+   if (nr_cpus_avail > 0)
+   return nr_cpus_avail;
+
+   nr_cpus_avail = sysconf(_SC_NPROCESSORS_CONF);
+   if (nr_cpus_avail <= 0) {
+   pr_err(
+"WARNING:\tunable to get available CPUs in this system: %s\n"
+"\tUse 128 instead.\n", str_error_r(errno, serr, sizeof(serr)));
+   nr_cpus_avail = 128;
+   }
+   return nr_cpus_avail;
+}
+
+void llvm__dump_obj(const char *path, void *obj_buf, size_t size)
 {
char *obj_path = strdup(path);
FILE *fp;
@@