diff mbox

[OpenWrt-Devel] kernel: generic 4.1 & 4.4 perf: musl compatibility

Message ID 1451384084-5093-1-git-send-email-kevin@darbyshire-bryant.me.uk
State Superseded
Headers show

Commit Message

Kevin Darbyshire-Bryant Dec. 29, 2015, 10:14 a.m. UTC
Enable linux perf tools to compile under musl.

Tested on MIPS Archer c7 v2 & ARM Linksys 1200ac.

With thanks to Dave Taht <dave.taht@bufferbloat.net> who
did the heavy lifting.

Signed-off-by: Kevin Darbyshire-Bryant <kevin@darbyshire-bryant.me.uk>
---
 package/devel/perf/Makefile                        |   2 +-
 .../patches-4.1/280-perf-fixes-for-musl.patch      | 148 +++++++++++++++++++++
 .../patches-4.4/280-perf-fixes-for-musl.patch      | 147 ++++++++++++++++++++
 3 files changed, 296 insertions(+), 1 deletion(-)
 create mode 100644 target/linux/generic/patches-4.1/280-perf-fixes-for-musl.patch
 create mode 100644 target/linux/generic/patches-4.4/280-perf-fixes-for-musl.patch

Comments

Hauke Mehrtens Dec. 29, 2015, 11:13 a.m. UTC | #1
On 12/29/2015 11:14 AM, Kevin Darbyshire-Bryant wrote:
> Enable linux perf tools to compile under musl.
> 
> Tested on MIPS Archer c7 v2 & ARM Linksys 1200ac.
> 
> With thanks to Dave Taht <dave.taht@bufferbloat.net> who
> did the heavy lifting.
> 
> Signed-off-by: Kevin Darbyshire-Bryant <kevin@darbyshire-bryant.me.uk>
> ---
>  package/devel/perf/Makefile                        |   2 +-
>  .../patches-4.1/280-perf-fixes-for-musl.patch      | 148 +++++++++++++++++++++
>  .../patches-4.4/280-perf-fixes-for-musl.patch      | 147 ++++++++++++++++++++
>  3 files changed, 296 insertions(+), 1 deletion(-)
>  create mode 100644 target/linux/generic/patches-4.1/280-perf-fixes-for-musl.patch
>  create mode 100644 target/linux/generic/patches-4.4/280-perf-fixes-for-musl.patch
> 
> diff --git a/package/devel/perf/Makefile b/package/devel/perf/Makefile
> index 5e3d63f..46ddb92 100644
> --- a/package/devel/perf/Makefile
> +++ b/package/devel/perf/Makefile
> @@ -19,7 +19,7 @@ include $(INCLUDE_DIR)/package.mk
>  define Package/perf
>    SECTION:=devel
>    CATEGORY:=Development
> -  DEPENDS:= @USE_GLIBC +libelf1 +libdw +libpthread +librt +binutils
> +  DEPENDS:= @USE_MUSL +libelf1 +libdw +libpthread +librt +binutils

Does it not work with GLIBC any more or why do you make it depend on
musl only now? Does this work with uclibc-ng?

I assume that this will not work on kernel 3.18 and kernel 4.3, which is
fine, as you haven't added patches for these kernel versions, but the
dependency is missing. Please add @!LINUX_3_18 @!LINUX_4_3

Will this be in kernel 4.5?

>    TITLE:=Linux performance monitoring tool
>    VERSION:=$(LINUX_VERSION)-$(PKG_RELEASE)
>    URL:=http://www.kernel.org
> diff --git a/target/linux/generic/patches-4.1/280-perf-fixes-for-musl.patch b/target/linux/generic/patches-4.1/280-perf-fixes-for-musl.patch
> new file mode 100644
> index 0000000..0e8b6d8
> --- /dev/null
> +++ b/target/linux/generic/patches-4.1/280-perf-fixes-for-musl.patch
> @@ -0,0 +1,148 @@
> +kernel: 4.1 perf: musl compatibility
> +
> +Allow linux perf tool to compile under musl.
> +
> +Backport to 4.1 by Kevin D-B with thanks to Dave
> +Taht <dave.taht@bufferbloat.net> for the heavy lifting.
> +
> +Signed-off-by: Kevin Darbyshire-Bryant <kevin@darbyshire-bryant.me.uk>
> +
> +---
> + tools/lib/api/fs/debugfs.c         |  4 ++++
> + tools/lib/traceevent/event-parse.c |  4 ++++
> + tools/perf/perf.c                  | 17 ++++++++++++++++-
> + tools/perf/util/cache.h            |  2 +-
> + tools/perf/util/cloexec.c          |  4 ----
> + tools/perf/util/cloexec.h          |  4 ----
> + tools/perf/util/util.h             |  4 ++++
> + 7 files changed, 29 insertions(+), 10 deletions(-)
> +
> +diff --git a/tools/lib/api/fs/debugfs.c b/tools/lib/api/fs/debugfs.c
> +index 8305b3e..5d1745c 100644
> +--- a/tools/lib/api/fs/debugfs.c
> ++++ b/tools/lib/api/fs/debugfs.c
> +@@ -17,6 +17,10 @@
> + #define DEBUGFS_DEFAULT_PATH		"/sys/kernel/debug"
> + #endif
> + 
> ++/* musl has a xpg compliant strerror_r by default */
> ++#define strerror_r(err, buf, buflen) \
> ++	(strerror_r(err, buf, buflen) ? NULL : buf)
> ++
> + char debugfs_mountpoint[PATH_MAX + 1] = DEBUGFS_DEFAULT_PATH;
> + 
> + static const char * const debugfs_known_mountpoints[] = {
> +diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
> +index ed5461f..f151369 100644
> +--- a/tools/lib/traceevent/event-parse.c
> ++++ b/tools/lib/traceevent/event-parse.c
> +@@ -36,6 +36,10 @@
> + #include "event-parse.h"
> + #include "event-utils.h"
> + 
> ++/* musl has a xpg compliant strerror_r by default */
> ++#define strerror_r(err, buf, buflen) \
> ++        (strerror_r(err, buf, buflen) ? NULL : buf)
> ++
> + static const char *input_buf;
> + static unsigned long long input_buf_ptr;
> + static unsigned long long input_buf_siz;
> +diff --git a/tools/perf/perf.c b/tools/perf/perf.c
> +index b857fcb..3e67fa2 100644
> +--- a/tools/perf/perf.c
> ++++ b/tools/perf/perf.c
> +@@ -505,6 +505,21 @@ void pthread__unblock_sigwinch(void)
> + 	pthread_sigmask(SIG_UNBLOCK, &set, NULL);
> + }
> + 
> ++unsigned cache_line_size(void);
> ++
> ++unsigned cache_line_size(void) {
> ++	FILE * p = 0;
> ++	unsigned int i = 0;
> ++	p = fopen("/sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size", "r");
> ++	if (p) {
> ++		if(fscanf(p, "%d", &i) != 1) {
> ++			perror("cannot determine cache line size");
> ++		}
> ++		fclose(p);
> ++	}
> ++	return i;
> ++}
> ++
> + int main(int argc, const char **argv)
> + {
> + 	const char *cmd;
> +@@ -512,7 +527,7 @@ int main(int argc, const char **argv)
> + 
> + 	/* The page_size is placed in util object. */
> + 	page_size = sysconf(_SC_PAGE_SIZE);
> +-	cacheline_size = sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
> ++	cacheline_size = cache_line_size();
> + 
> + 	cmd = perf_extract_argv0_path(argv[0]);
> + 	if (!cmd)
> +diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
> +index fbcca21..9b23c4a 100644
> +--- a/tools/perf/util/cache.h
> ++++ b/tools/perf/util/cache.h
> +@@ -72,7 +72,7 @@ extern char *perf_path(const char *fmt, ...) __attribute__((format (printf, 1, 2
> + extern char *perf_pathdup(const char *fmt, ...)
> + 	__attribute__((format (printf, 1, 2)));
> + 
> +-#ifndef __UCLIBC__
> ++#if !defined(__UCLIBC__) && defined(__GLIBC__) 
> + /* Matches the libc/libbsd function attribute so we declare this unconditionally: */
> + extern size_t strlcpy(char *dest, const char *src, size_t size);
> + #endif
> +diff --git a/tools/perf/util/cloexec.c b/tools/perf/util/cloexec.c
> +index 2babdda..85b5238 100644
> +--- a/tools/perf/util/cloexec.c
> ++++ b/tools/perf/util/cloexec.c
> +@@ -7,15 +7,11 @@
> + 
> + static unsigned long flag = PERF_FLAG_FD_CLOEXEC;
> + 
> +-#ifdef __GLIBC_PREREQ
> +-#if !__GLIBC_PREREQ(2, 6)
> + int __weak sched_getcpu(void)
> + {
> + 	errno = ENOSYS;
> + 	return -1;
> + }
> +-#endif
> +-#endif
> + 
> + static int perf_flag_probe(void)
> + {
> +diff --git a/tools/perf/util/cloexec.h b/tools/perf/util/cloexec.h
> +index 68888c2..06904bc 100644
> +--- a/tools/perf/util/cloexec.h
> ++++ b/tools/perf/util/cloexec.h
> +@@ -3,10 +3,6 @@
> + 
> + unsigned long perf_event_open_cloexec_flag(void);
> + 
> +-#ifdef __GLIBC_PREREQ
> +-#if !__GLIBC_PREREQ(2, 6)
> + extern int sched_getcpu(void) __THROW;
> +-#endif
> +-#endif
> + 
> + #endif /* __PERF_CLOEXEC_H */
> +diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
> +index 1ff23e0..a5f4770 100644
> +--- a/tools/perf/util/util.h
> ++++ b/tools/perf/util/util.h
> +@@ -333,4 +333,8 @@ int gzip_decompress_to_file(const char *input, int output_fd);
> + int lzma_decompress_to_file(const char *input, int output_fd);
> + #endif
> + 
> ++/* musl has a xpg compliant strerror_r by default */
> ++#define strerror_r(err, buf, buflen) \
> ++        (strerror_r(err, buf, buflen) ? NULL : buf)
> ++
> + #endif /* GIT_COMPAT_UTIL_H */
> +-- 
> +1.9.1
> +
> diff --git a/target/linux/generic/patches-4.4/280-perf-fixes-for-musl.patch b/target/linux/generic/patches-4.4/280-perf-fixes-for-musl.patch
> new file mode 100644
> index 0000000..42d0d48
> --- /dev/null
> +++ b/target/linux/generic/patches-4.4/280-perf-fixes-for-musl.patch
> @@ -0,0 +1,147 @@
> +kernel: 4.4 perf: musl compatibility
> +
> +Allow linux perf tool to compile under musl.
> +
> +Thanks to Dave Taht <dave.taht@bufferbloat.net> for the
> +heavy lifting.
> +
> +Signed-off-by: Kevin Darbyshire-Bryant <kevin@darbyshire-bryant.me.uk>
> +
> +---
> + tools/lib/api/fs/tracing_path.c    |  3 +++
> + tools/lib/traceevent/event-parse.c |  4 ++++
> + tools/perf/perf.c                  | 17 ++++++++++++++++-
> + tools/perf/util/cache.h            |  2 +-
> + tools/perf/util/cloexec.c          |  4 ----
> + tools/perf/util/cloexec.h          |  4 ----
> + tools/perf/util/util.h             |  4 ++++
> + 7 files changed, 28 insertions(+), 10 deletions(-)
> +
> +diff --git a/tools/lib/api/fs/tracing_path.c b/tools/lib/api/fs/tracing_path.c
> +index a26bb5e..a04df38 100644
> +--- a/tools/lib/api/fs/tracing_path.c
> ++++ b/tools/lib/api/fs/tracing_path.c
> +@@ -10,6 +10,9 @@
> + #include "fs.h"
> + 
> + #include "tracing_path.h"
> ++/* musl has a xpg compliant strerror_r by default */
> ++#define strerror_r(err, buf, buflen) \
> ++        (strerror_r(err, buf, buflen) ? NULL : buf)
> + 
> + 
> + char tracing_mnt[PATH_MAX]         = "/sys/kernel/debug";
> +diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
> +index 2a912df..0644b42 100644
> +--- a/tools/lib/traceevent/event-parse.c
> ++++ b/tools/lib/traceevent/event-parse.c
> +@@ -36,6 +36,10 @@
> + #include "event-parse.h"
> + #include "event-utils.h"
> + 
> ++/* musl has a xpg compliant strerror_r by default */
> ++#define strerror_r(err, buf, buflen) \
> ++        (strerror_r(err, buf, buflen) ? NULL : buf)
> ++
> + static const char *input_buf;
> + static unsigned long long input_buf_ptr;
> + static unsigned long long input_buf_siz;
> +diff --git a/tools/perf/perf.c b/tools/perf/perf.c
> +index 3d4c7c0..91f57b0 100644
> +--- a/tools/perf/perf.c
> ++++ b/tools/perf/perf.c
> +@@ -523,6 +523,21 @@ void pthread__unblock_sigwinch(void)
> + 	pthread_sigmask(SIG_UNBLOCK, &set, NULL);
> + }
> + 
> ++unsigned cache_line_size(void);
> ++
> ++unsigned cache_line_size(void) {
> ++	FILE * p = 0;
> ++	unsigned int i = 0;
> ++	p = fopen("/sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size", "r");
> ++	if (p) {
> ++		if(fscanf(p, "%d", &i) != 1) {
> ++			perror("cannot determine cache line size");
> ++		}
> ++		fclose(p);
> ++	}
> ++	return i;
> ++}
> ++
> + int main(int argc, const char **argv)
> + {
> + 	const char *cmd;
> +@@ -530,7 +545,7 @@ int main(int argc, const char **argv)
> + 
> + 	/* The page_size is placed in util object. */
> + 	page_size = sysconf(_SC_PAGE_SIZE);
> +-	cacheline_size = sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
> ++	cacheline_size = cache_line_size();
> + 
> + 	cmd = perf_extract_argv0_path(argv[0]);
> + 	if (!cmd)
> +diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
> +index c861373..599aa97 100644
> +--- a/tools/perf/util/cache.h
> ++++ b/tools/perf/util/cache.h
> +@@ -71,7 +71,7 @@ extern char *perf_path(const char *fmt, ...) __attribute__((format (printf, 1, 2
> + extern char *perf_pathdup(const char *fmt, ...)
> + 	__attribute__((format (printf, 1, 2)));
> + 
> +-#ifndef __UCLIBC__
> ++#if !defined(__UCLIBC__) && defined(__GLIBC__) 
> + /* Matches the libc/libbsd function attribute so we declare this unconditionally: */
> + extern size_t strlcpy(char *dest, const char *src, size_t size);
> + #endif
> +diff --git a/tools/perf/util/cloexec.c b/tools/perf/util/cloexec.c
> +index 2babdda..85b5238 100644
> +--- a/tools/perf/util/cloexec.c
> ++++ b/tools/perf/util/cloexec.c
> +@@ -7,15 +7,11 @@
> + 
> + static unsigned long flag = PERF_FLAG_FD_CLOEXEC;
> + 
> +-#ifdef __GLIBC_PREREQ
> +-#if !__GLIBC_PREREQ(2, 6)
> + int __weak sched_getcpu(void)
> + {
> + 	errno = ENOSYS;
> + 	return -1;
> + }
> +-#endif
> +-#endif
> + 
> + static int perf_flag_probe(void)
> + {
> +diff --git a/tools/perf/util/cloexec.h b/tools/perf/util/cloexec.h
> +index 3bee677..06904bc 100644
> +--- a/tools/perf/util/cloexec.h
> ++++ b/tools/perf/util/cloexec.h
> +@@ -3,10 +3,6 @@
> + 
> + unsigned long perf_event_open_cloexec_flag(void);
> + 
> +-#ifdef __GLIBC_PREREQ
> +-#if !__GLIBC_PREREQ(2, 6) && !defined(__UCLIBC__)
> + extern int sched_getcpu(void) __THROW;
> +-#endif
> +-#endif
> + 
> + #endif /* __PERF_CLOEXEC_H */
> +diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
> +index dcc6590..16d398b 100644
> +--- a/tools/perf/util/util.h
> ++++ b/tools/perf/util/util.h
> +@@ -358,4 +358,8 @@ int fetch_kernel_version(unsigned int *puint,
> + #define KVER_FMT	"%d.%d.%d"
> + #define KVER_PARAM(x)	KVER_VERSION(x), KVER_PATCHLEVEL(x), KVER_SUBLEVEL(x)
> + 
> ++/* musl has a xpg compliant strerror_r by default */
> ++#define strerror_r(err, buf, buflen) \
> ++        (strerror_r(err, buf, buflen) ? NULL : buf)
> ++
> + #endif /* GIT_COMPAT_UTIL_H */
> +-- 
> +2.5.0
> +
>
Kevin Darbyshire-Bryant Dec. 29, 2015, 11:28 a.m. UTC | #2
On 29/12/15 11:13, Hauke Mehrtens wrote:
>
> On 12/29/2015 11:14 AM, Kevin Darbyshire-Bryant wrote:
>> Enable linux perf tools to compile under musl.
>>
>> Tested on MIPS Archer c7 v2 & ARM Linksys 1200ac.
>>
>> With thanks to Dave Taht <dave.taht@bufferbloat.net> who
>> did the heavy lifting.
>>
>> Signed-off-by: Kevin Darbyshire-Bryant <kevin@darbyshire-bryant.me.uk>
>> ---
>>  package/devel/perf/Makefile                        |   2 +-
>>  .../patches-4.1/280-perf-fixes-for-musl.patch      | 148 +++++++++++++++++++++
>>  .../patches-4.4/280-perf-fixes-for-musl.patch      | 147 ++++++++++++++++++++
>>  3 files changed, 296 insertions(+), 1 deletion(-)
>>  create mode 100644 target/linux/generic/patches-4.1/280-perf-fixes-for-musl.patch
>>  create mode 100644 target/linux/generic/patches-4.4/280-perf-fixes-for-musl.patch
>>
>> diff --git a/package/devel/perf/Makefile b/package/devel/perf/Makefile
>> index 5e3d63f..46ddb92 100644
>> --- a/package/devel/perf/Makefile
>> +++ b/package/devel/perf/Makefile
>> @@ -19,7 +19,7 @@ include $(INCLUDE_DIR)/package.mk
>>  define Package/perf
>>    SECTION:=devel
>>    CATEGORY:=Development
>> -  DEPENDS:= @USE_GLIBC +libelf1 +libdw +libpthread +librt +binutils
>> +  DEPENDS:= @USE_MUSL +libelf1 +libdw +libpthread +librt +binutils
Hi Hauke,

Let me prefix this with "I don't know what I'm doing"
> Does it not work with GLIBC any more or why do you make it depend on
> musl only now? Does this work with uclibc-ng?
I suspect it'll break spectacularly with glibc.  I'm sure the patches
could be modified to have both glibc & musl compatibility but it's
beyond my wit to know how.  I was interested in getting perf to work
(without enabling broken packages) under Archer C7 v2 which uses musl
now by default.  I've no idea about uclibc-ng.
>
> I assume that this will not work on kernel 3.18 and kernel 4.3, which is
> fine, as you haven't added patches for these kernel versions, but the
> dependency is missing. Please add @!LINUX_3_18 @!LINUX_4_3
Now that's something I can do....if it's worth the bother bearing in
mind other comments?
>
> Will this be in kernel 4.5?
No idea.  My Archer (ar71xx) isn't on 4.4 yet let alone 4.5


A few people have put effort into getting perf running on the above
mentioned platforms, I thought it worth throwing at OpenWrt devel list
as a patch to pass the effort on and see what sticks :-)  If it doesn't
stick then fair enough.

Kevin
Roman Yeryomin Dec. 31, 2015, 12:22 p.m. UTC | #3
On 29 December 2015 at 12:14, Kevin Darbyshire-Bryant
<kevin@darbyshire-bryant.me.uk> wrote:
> Enable linux perf tools to compile under musl.
>
> Tested on MIPS Archer c7 v2 & ARM Linksys 1200ac.
>
> With thanks to Dave Taht <dave.taht@bufferbloat.net> who
> did the heavy lifting.
>
> Signed-off-by: Kevin Darbyshire-Bryant <kevin@darbyshire-bryant.me.uk>
> ---
>  package/devel/perf/Makefile                        |   2 +-
>  .../patches-4.1/280-perf-fixes-for-musl.patch      | 148 +++++++++++++++++++++
>  .../patches-4.4/280-perf-fixes-for-musl.patch      | 147 ++++++++++++++++++++
>  3 files changed, 296 insertions(+), 1 deletion(-)
>  create mode 100644 target/linux/generic/patches-4.1/280-perf-fixes-for-musl.patch
>  create mode 100644 target/linux/generic/patches-4.4/280-perf-fixes-for-musl.patch
>
> diff --git a/package/devel/perf/Makefile b/package/devel/perf/Makefile
> index 5e3d63f..46ddb92 100644
> --- a/package/devel/perf/Makefile
> +++ b/package/devel/perf/Makefile
> @@ -19,7 +19,7 @@ include $(INCLUDE_DIR)/package.mk
>  define Package/perf
>    SECTION:=devel
>    CATEGORY:=Development
> -  DEPENDS:= @USE_GLIBC +libelf1 +libdw +libpthread +librt +binutils
> +  DEPENDS:= @USE_MUSL +libelf1 +libdw +libpthread +librt +binutils
>    TITLE:=Linux performance monitoring tool
>    VERSION:=$(LINUX_VERSION)-$(PKG_RELEASE)
>    URL:=http://www.kernel.org
> diff --git a/target/linux/generic/patches-4.1/280-perf-fixes-for-musl.patch b/target/linux/generic/patches-4.1/280-perf-fixes-for-musl.patch
> new file mode 100644
> index 0000000..0e8b6d8
> --- /dev/null
> +++ b/target/linux/generic/patches-4.1/280-perf-fixes-for-musl.patch
> @@ -0,0 +1,148 @@
> +kernel: 4.1 perf: musl compatibility
> +
> +Allow linux perf tool to compile under musl.
> +
> +Backport to 4.1 by Kevin D-B with thanks to Dave
> +Taht <dave.taht@bufferbloat.net> for the heavy lifting.
> +
> +Signed-off-by: Kevin Darbyshire-Bryant <kevin@darbyshire-bryant.me.uk>
> +
> +---
> + tools/lib/api/fs/debugfs.c         |  4 ++++
> + tools/lib/traceevent/event-parse.c |  4 ++++
> + tools/perf/perf.c                  | 17 ++++++++++++++++-
> + tools/perf/util/cache.h            |  2 +-
> + tools/perf/util/cloexec.c          |  4 ----
> + tools/perf/util/cloexec.h          |  4 ----
> + tools/perf/util/util.h             |  4 ++++
> + 7 files changed, 29 insertions(+), 10 deletions(-)
> +
> +diff --git a/tools/lib/api/fs/debugfs.c b/tools/lib/api/fs/debugfs.c
> +index 8305b3e..5d1745c 100644
> +--- a/tools/lib/api/fs/debugfs.c
> ++++ b/tools/lib/api/fs/debugfs.c
> +@@ -17,6 +17,10 @@
> + #define DEBUGFS_DEFAULT_PATH          "/sys/kernel/debug"
> + #endif
> +
> ++/* musl has a xpg compliant strerror_r by default */
> ++#define strerror_r(err, buf, buflen) \
> ++      (strerror_r(err, buf, buflen) ? NULL : buf)
> ++
> + char debugfs_mountpoint[PATH_MAX + 1] = DEBUGFS_DEFAULT_PATH;
> +
> + static const char * const debugfs_known_mountpoints[] = {
> +diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
> +index ed5461f..f151369 100644
> +--- a/tools/lib/traceevent/event-parse.c
> ++++ b/tools/lib/traceevent/event-parse.c
> +@@ -36,6 +36,10 @@
> + #include "event-parse.h"
> + #include "event-utils.h"
> +
> ++/* musl has a xpg compliant strerror_r by default */
> ++#define strerror_r(err, buf, buflen) \
> ++        (strerror_r(err, buf, buflen) ? NULL : buf)
> ++
> + static const char *input_buf;
> + static unsigned long long input_buf_ptr;
> + static unsigned long long input_buf_siz;
> +diff --git a/tools/perf/perf.c b/tools/perf/perf.c
> +index b857fcb..3e67fa2 100644
> +--- a/tools/perf/perf.c
> ++++ b/tools/perf/perf.c
> +@@ -505,6 +505,21 @@ void pthread__unblock_sigwinch(void)
> +       pthread_sigmask(SIG_UNBLOCK, &set, NULL);
> + }
> +
> ++unsigned cache_line_size(void);
> ++
> ++unsigned cache_line_size(void) {
> ++      FILE * p = 0;
> ++      unsigned int i = 0;
> ++      p = fopen("/sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size", "r");
> ++      if (p) {
> ++              if(fscanf(p, "%d", &i) != 1) {
> ++                      perror("cannot determine cache line size");
> ++              }
> ++              fclose(p);
> ++      }
> ++      return i;
> ++}
> ++

Kevin, are you sure this works?
I don't have /sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size
on my Archer C7
I did a little bit more simple way adding a header from eglibc. If
anybody interested I can submit the patch for RFC.


Regards,
Roman
Kevin Darbyshire-Bryant Dec. 31, 2015, 5:03 p.m. UTC | #4
On 31/12/15 12:22, Roman Yeryomin wrote:
> On 29 December 2015 at 12:14, Kevin Darbyshire-Bryant
> <kevin@darbyshire-bryant.me.uk> wrote:
>
> Kevin, are you sure this works?
> I don't have /sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size
> on my Archer C7
Hi Roman,

Perf ran and didn't barf when I tried...however I'm new to perf so maybe
I didn't look in the right place.  I also wonder if that sys file entry
is only enabled when kernel perf config is enabled too.

> I did a little bit more simple way adding a header from eglibc. If
> anybody interested I can submit the patch for RFC.
Personally, I'd say anything that helps performance investigations on
'under powered' SoC devices is a good thing, helpful & useful.

Kevin
>
>
> Regards,
> Roman
Felix Fietkau Jan. 2, 2016, 12:46 p.m. UTC | #5
On 2015-12-31 13:22, Roman Yeryomin wrote:
> Kevin, are you sure this works?
> I don't have /sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size
> on my Archer C7
> I did a little bit more simple way adding a header from eglibc. If
> anybody interested I can submit the patch for RFC.
As far as I can see, glibc only supports reading the cache line size for
few architectures, probably fewer than those that provide the sysfs file.

I don't see a generic way to query this on mips and the return code
should be the same as sysconf on uclibc/glibc, so this function makes
sense. It should probably be made static though...

- Felix
Felix Fietkau Jan. 2, 2016, 2:49 p.m. UTC | #6
On 2015-12-29 11:14, Kevin Darbyshire-Bryant wrote:
> Enable linux perf tools to compile under musl.
> 
> Tested on MIPS Archer c7 v2 & ARM Linksys 1200ac.
> 
> With thanks to Dave Taht <dave.taht@bufferbloat.net> who
> did the heavy lifting.
> 
> Signed-off-by: Kevin Darbyshire-Bryant <kevin@darbyshire-bryant.me.uk>
FYI, I just did some cleanups and fixes on perf, and it now builds and
runs on musl without any extra kernel patches.

- Felix
Kevin Darbyshire-Bryant Jan. 2, 2016, 4:53 p.m. UTC | #7
On 02/01/16 14:49, Felix Fietkau wrote:
> On 2015-12-29 11:14, Kevin Darbyshire-Bryant wrote:
>> Enable linux perf tools to compile under musl.
>>
>> Tested on MIPS Archer c7 v2 & ARM Linksys 1200ac.
>>
>> With thanks to Dave Taht <dave.taht@bufferbloat.net> who
>> did the heavy lifting.
>>
>> Signed-off-by: Kevin Darbyshire-Bryant <kevin@darbyshire-bryant.me.uk>
> FYI, I just did some cleanups and fixes on perf, and it now builds and
> runs on musl without any extra kernel patches.
>
> - Felix
That's great Felix!  Thank you.

Kevin
diff mbox

Patch

diff --git a/package/devel/perf/Makefile b/package/devel/perf/Makefile
index 5e3d63f..46ddb92 100644
--- a/package/devel/perf/Makefile
+++ b/package/devel/perf/Makefile
@@ -19,7 +19,7 @@  include $(INCLUDE_DIR)/package.mk
 define Package/perf
   SECTION:=devel
   CATEGORY:=Development
-  DEPENDS:= @USE_GLIBC +libelf1 +libdw +libpthread +librt +binutils
+  DEPENDS:= @USE_MUSL +libelf1 +libdw +libpthread +librt +binutils
   TITLE:=Linux performance monitoring tool
   VERSION:=$(LINUX_VERSION)-$(PKG_RELEASE)
   URL:=http://www.kernel.org
diff --git a/target/linux/generic/patches-4.1/280-perf-fixes-for-musl.patch b/target/linux/generic/patches-4.1/280-perf-fixes-for-musl.patch
new file mode 100644
index 0000000..0e8b6d8
--- /dev/null
+++ b/target/linux/generic/patches-4.1/280-perf-fixes-for-musl.patch
@@ -0,0 +1,148 @@ 
+kernel: 4.1 perf: musl compatibility
+
+Allow linux perf tool to compile under musl.
+
+Backport to 4.1 by Kevin D-B with thanks to Dave
+Taht <dave.taht@bufferbloat.net> for the heavy lifting.
+
+Signed-off-by: Kevin Darbyshire-Bryant <kevin@darbyshire-bryant.me.uk>
+
+---
+ tools/lib/api/fs/debugfs.c         |  4 ++++
+ tools/lib/traceevent/event-parse.c |  4 ++++
+ tools/perf/perf.c                  | 17 ++++++++++++++++-
+ tools/perf/util/cache.h            |  2 +-
+ tools/perf/util/cloexec.c          |  4 ----
+ tools/perf/util/cloexec.h          |  4 ----
+ tools/perf/util/util.h             |  4 ++++
+ 7 files changed, 29 insertions(+), 10 deletions(-)
+
+diff --git a/tools/lib/api/fs/debugfs.c b/tools/lib/api/fs/debugfs.c
+index 8305b3e..5d1745c 100644
+--- a/tools/lib/api/fs/debugfs.c
++++ b/tools/lib/api/fs/debugfs.c
+@@ -17,6 +17,10 @@
+ #define DEBUGFS_DEFAULT_PATH		"/sys/kernel/debug"
+ #endif
+ 
++/* musl has a xpg compliant strerror_r by default */
++#define strerror_r(err, buf, buflen) \
++	(strerror_r(err, buf, buflen) ? NULL : buf)
++
+ char debugfs_mountpoint[PATH_MAX + 1] = DEBUGFS_DEFAULT_PATH;
+ 
+ static const char * const debugfs_known_mountpoints[] = {
+diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
+index ed5461f..f151369 100644
+--- a/tools/lib/traceevent/event-parse.c
++++ b/tools/lib/traceevent/event-parse.c
+@@ -36,6 +36,10 @@
+ #include "event-parse.h"
+ #include "event-utils.h"
+ 
++/* musl has a xpg compliant strerror_r by default */
++#define strerror_r(err, buf, buflen) \
++        (strerror_r(err, buf, buflen) ? NULL : buf)
++
+ static const char *input_buf;
+ static unsigned long long input_buf_ptr;
+ static unsigned long long input_buf_siz;
+diff --git a/tools/perf/perf.c b/tools/perf/perf.c
+index b857fcb..3e67fa2 100644
+--- a/tools/perf/perf.c
++++ b/tools/perf/perf.c
+@@ -505,6 +505,21 @@ void pthread__unblock_sigwinch(void)
+ 	pthread_sigmask(SIG_UNBLOCK, &set, NULL);
+ }
+ 
++unsigned cache_line_size(void);
++
++unsigned cache_line_size(void) {
++	FILE * p = 0;
++	unsigned int i = 0;
++	p = fopen("/sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size", "r");
++	if (p) {
++		if(fscanf(p, "%d", &i) != 1) {
++			perror("cannot determine cache line size");
++		}
++		fclose(p);
++	}
++	return i;
++}
++
+ int main(int argc, const char **argv)
+ {
+ 	const char *cmd;
+@@ -512,7 +527,7 @@ int main(int argc, const char **argv)
+ 
+ 	/* The page_size is placed in util object. */
+ 	page_size = sysconf(_SC_PAGE_SIZE);
+-	cacheline_size = sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
++	cacheline_size = cache_line_size();
+ 
+ 	cmd = perf_extract_argv0_path(argv[0]);
+ 	if (!cmd)
+diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
+index fbcca21..9b23c4a 100644
+--- a/tools/perf/util/cache.h
++++ b/tools/perf/util/cache.h
+@@ -72,7 +72,7 @@ extern char *perf_path(const char *fmt, ...) __attribute__((format (printf, 1, 2
+ extern char *perf_pathdup(const char *fmt, ...)
+ 	__attribute__((format (printf, 1, 2)));
+ 
+-#ifndef __UCLIBC__
++#if !defined(__UCLIBC__) && defined(__GLIBC__) 
+ /* Matches the libc/libbsd function attribute so we declare this unconditionally: */
+ extern size_t strlcpy(char *dest, const char *src, size_t size);
+ #endif
+diff --git a/tools/perf/util/cloexec.c b/tools/perf/util/cloexec.c
+index 2babdda..85b5238 100644
+--- a/tools/perf/util/cloexec.c
++++ b/tools/perf/util/cloexec.c
+@@ -7,15 +7,11 @@
+ 
+ static unsigned long flag = PERF_FLAG_FD_CLOEXEC;
+ 
+-#ifdef __GLIBC_PREREQ
+-#if !__GLIBC_PREREQ(2, 6)
+ int __weak sched_getcpu(void)
+ {
+ 	errno = ENOSYS;
+ 	return -1;
+ }
+-#endif
+-#endif
+ 
+ static int perf_flag_probe(void)
+ {
+diff --git a/tools/perf/util/cloexec.h b/tools/perf/util/cloexec.h
+index 68888c2..06904bc 100644
+--- a/tools/perf/util/cloexec.h
++++ b/tools/perf/util/cloexec.h
+@@ -3,10 +3,6 @@
+ 
+ unsigned long perf_event_open_cloexec_flag(void);
+ 
+-#ifdef __GLIBC_PREREQ
+-#if !__GLIBC_PREREQ(2, 6)
+ extern int sched_getcpu(void) __THROW;
+-#endif
+-#endif
+ 
+ #endif /* __PERF_CLOEXEC_H */
+diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
+index 1ff23e0..a5f4770 100644
+--- a/tools/perf/util/util.h
++++ b/tools/perf/util/util.h
+@@ -333,4 +333,8 @@ int gzip_decompress_to_file(const char *input, int output_fd);
+ int lzma_decompress_to_file(const char *input, int output_fd);
+ #endif
+ 
++/* musl has a xpg compliant strerror_r by default */
++#define strerror_r(err, buf, buflen) \
++        (strerror_r(err, buf, buflen) ? NULL : buf)
++
+ #endif /* GIT_COMPAT_UTIL_H */
+-- 
+1.9.1
+
diff --git a/target/linux/generic/patches-4.4/280-perf-fixes-for-musl.patch b/target/linux/generic/patches-4.4/280-perf-fixes-for-musl.patch
new file mode 100644
index 0000000..42d0d48
--- /dev/null
+++ b/target/linux/generic/patches-4.4/280-perf-fixes-for-musl.patch
@@ -0,0 +1,147 @@ 
+kernel: 4.4 perf: musl compatibility
+
+Allow linux perf tool to compile under musl.
+
+Thanks to Dave Taht <dave.taht@bufferbloat.net> for the
+heavy lifting.
+
+Signed-off-by: Kevin Darbyshire-Bryant <kevin@darbyshire-bryant.me.uk>
+
+---
+ tools/lib/api/fs/tracing_path.c    |  3 +++
+ tools/lib/traceevent/event-parse.c |  4 ++++
+ tools/perf/perf.c                  | 17 ++++++++++++++++-
+ tools/perf/util/cache.h            |  2 +-
+ tools/perf/util/cloexec.c          |  4 ----
+ tools/perf/util/cloexec.h          |  4 ----
+ tools/perf/util/util.h             |  4 ++++
+ 7 files changed, 28 insertions(+), 10 deletions(-)
+
+diff --git a/tools/lib/api/fs/tracing_path.c b/tools/lib/api/fs/tracing_path.c
+index a26bb5e..a04df38 100644
+--- a/tools/lib/api/fs/tracing_path.c
++++ b/tools/lib/api/fs/tracing_path.c
+@@ -10,6 +10,9 @@
+ #include "fs.h"
+ 
+ #include "tracing_path.h"
++/* musl has a xpg compliant strerror_r by default */
++#define strerror_r(err, buf, buflen) \
++        (strerror_r(err, buf, buflen) ? NULL : buf)
+ 
+ 
+ char tracing_mnt[PATH_MAX]         = "/sys/kernel/debug";
+diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
+index 2a912df..0644b42 100644
+--- a/tools/lib/traceevent/event-parse.c
++++ b/tools/lib/traceevent/event-parse.c
+@@ -36,6 +36,10 @@
+ #include "event-parse.h"
+ #include "event-utils.h"
+ 
++/* musl has a xpg compliant strerror_r by default */
++#define strerror_r(err, buf, buflen) \
++        (strerror_r(err, buf, buflen) ? NULL : buf)
++
+ static const char *input_buf;
+ static unsigned long long input_buf_ptr;
+ static unsigned long long input_buf_siz;
+diff --git a/tools/perf/perf.c b/tools/perf/perf.c
+index 3d4c7c0..91f57b0 100644
+--- a/tools/perf/perf.c
++++ b/tools/perf/perf.c
+@@ -523,6 +523,21 @@ void pthread__unblock_sigwinch(void)
+ 	pthread_sigmask(SIG_UNBLOCK, &set, NULL);
+ }
+ 
++unsigned cache_line_size(void);
++
++unsigned cache_line_size(void) {
++	FILE * p = 0;
++	unsigned int i = 0;
++	p = fopen("/sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size", "r");
++	if (p) {
++		if(fscanf(p, "%d", &i) != 1) {
++			perror("cannot determine cache line size");
++		}
++		fclose(p);
++	}
++	return i;
++}
++
+ int main(int argc, const char **argv)
+ {
+ 	const char *cmd;
+@@ -530,7 +545,7 @@ int main(int argc, const char **argv)
+ 
+ 	/* The page_size is placed in util object. */
+ 	page_size = sysconf(_SC_PAGE_SIZE);
+-	cacheline_size = sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
++	cacheline_size = cache_line_size();
+ 
+ 	cmd = perf_extract_argv0_path(argv[0]);
+ 	if (!cmd)
+diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
+index c861373..599aa97 100644
+--- a/tools/perf/util/cache.h
++++ b/tools/perf/util/cache.h
+@@ -71,7 +71,7 @@ extern char *perf_path(const char *fmt, ...) __attribute__((format (printf, 1, 2
+ extern char *perf_pathdup(const char *fmt, ...)
+ 	__attribute__((format (printf, 1, 2)));
+ 
+-#ifndef __UCLIBC__
++#if !defined(__UCLIBC__) && defined(__GLIBC__) 
+ /* Matches the libc/libbsd function attribute so we declare this unconditionally: */
+ extern size_t strlcpy(char *dest, const char *src, size_t size);
+ #endif
+diff --git a/tools/perf/util/cloexec.c b/tools/perf/util/cloexec.c
+index 2babdda..85b5238 100644
+--- a/tools/perf/util/cloexec.c
++++ b/tools/perf/util/cloexec.c
+@@ -7,15 +7,11 @@
+ 
+ static unsigned long flag = PERF_FLAG_FD_CLOEXEC;
+ 
+-#ifdef __GLIBC_PREREQ
+-#if !__GLIBC_PREREQ(2, 6)
+ int __weak sched_getcpu(void)
+ {
+ 	errno = ENOSYS;
+ 	return -1;
+ }
+-#endif
+-#endif
+ 
+ static int perf_flag_probe(void)
+ {
+diff --git a/tools/perf/util/cloexec.h b/tools/perf/util/cloexec.h
+index 3bee677..06904bc 100644
+--- a/tools/perf/util/cloexec.h
++++ b/tools/perf/util/cloexec.h
+@@ -3,10 +3,6 @@
+ 
+ unsigned long perf_event_open_cloexec_flag(void);
+ 
+-#ifdef __GLIBC_PREREQ
+-#if !__GLIBC_PREREQ(2, 6) && !defined(__UCLIBC__)
+ extern int sched_getcpu(void) __THROW;
+-#endif
+-#endif
+ 
+ #endif /* __PERF_CLOEXEC_H */
+diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
+index dcc6590..16d398b 100644
+--- a/tools/perf/util/util.h
++++ b/tools/perf/util/util.h
+@@ -358,4 +358,8 @@ int fetch_kernel_version(unsigned int *puint,
+ #define KVER_FMT	"%d.%d.%d"
+ #define KVER_PARAM(x)	KVER_VERSION(x), KVER_PATCHLEVEL(x), KVER_SUBLEVEL(x)
+ 
++/* musl has a xpg compliant strerror_r by default */
++#define strerror_r(err, buf, buflen) \
++        (strerror_r(err, buf, buflen) ? NULL : buf)
++
+ #endif /* GIT_COMPAT_UTIL_H */
+-- 
+2.5.0
+