musl: fix mips vdso handling
authorhauke <hauke@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Mon, 25 Jan 2016 23:26:19 +0000 (23:26 +0000)
committerhauke <hauke@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Mon, 25 Jan 2016 23:26:19 +0000 (23:26 +0000)
mips returns -ENOSYS in case it can not handle the vdso call and wants
the libc to call the original syscall in such a case. This fixes the
patch to add such handling. I hope this fixes the random reboots I got.

Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@48501 3c298f89-4303-0410-b956-a3cf2f4a3e73

toolchain/musl/patches/030-mips-add-vdso-support.patch

index e4a15e3..537a1ca 100644 (file)
@@ -1,4 +1,4 @@
-From c29a29c3334344e0f3cfdec6130a6261514507a0 Mon Sep 17 00:00:00 2001
+From 93332ebdcd54b0e0c0e86bced537cc96247bc1f1 Mon Sep 17 00:00:00 2001
 From: Hauke Mehrtens <hauke@hauke-m.de>
 Date: Sat, 23 Jan 2016 16:23:09 +0100
 Subject: [PATCH 2/2] mips: add vdso support
@@ -7,10 +7,32 @@ vdso support is available on mips starting with kernel 4.4, see kernel
 commit a7f4df4e21 "MIPS: VDSO: Add implementations of gettimeofday()
 and clock_gettime()" for details.
 
+In Linux kernel 4.4.0 the mips code returns -ENOSYS in case it can not
+handle the vdso call and assumes the libc will call the original
+syscall in this case. Handle this case in musl. Currently Linux kernel
+4.4.0 handles the following types: CLOCK_REALTIME_COARSE,
+CLOCK_MONOTONIC_COARSE, CLOCK_REALTIME and CLOCK_MONOTONIC.
+
+These are some measurements of calling clock_gettime(CLOCK_MONOTONIC,
+&tp); 1.000.000 times.
+
+without vdso:
+root@OpenWrt:/# time ./vdso-test
+real 0m 0.95s
+user 0m 0.24s
+sys 0m 0.70s
+
+with vdso:
+root@OpenWrt:/# time /usr/bin/vdso-test
+real 0m 0.35s
+user 0m 0.34s
+sys 0m 0.00s
+
 Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
 ---
- arch/mips/syscall_arch.h | 4 ++++
- 1 file changed, 4 insertions(+)
+ arch/mips/syscall_arch.h |  4 ++++
+ src/time/clock_gettime.c | 12 +++++++++++-
+ 2 files changed, 15 insertions(+), 1 deletion(-)
 
 diff --git a/arch/mips/syscall_arch.h b/arch/mips/syscall_arch.h
 index e74e0ad..39c0ea3 100644
@@ -24,6 +46,35 @@ index e74e0ad..39c0ea3 100644
 +#define VDSO_USEFUL
 +#define VDSO_CGT_SYM "__vdso_clock_gettime"
 +#define VDSO_CGT_VER "LINUX_2.6"
+diff --git a/src/time/clock_gettime.c b/src/time/clock_gettime.c
+index 1572de0..dba99ff 100644
+--- a/src/time/clock_gettime.c
++++ b/src/time/clock_gettime.c
+@@ -26,13 +26,23 @@ void *__vdsosym(const char *, const char *);
+ int __clock_gettime(clockid_t clk, struct timespec *ts)
+ {
+ #ifdef VDSO_CGT_SYM
++      int ret;
+       static int (*volatile cgt)(clockid_t, struct timespec *);
+       if (!cgt) {
+               void *f = __vdsosym(VDSO_CGT_VER, VDSO_CGT_SYM);
+               if (!f) f = (void *)sc_clock_gettime;
+               a_cas_p(&cgt, 0, f);
+       }
+-      return cgt(clk, ts);
++      ret = cgt(clk, ts);
++
++      /*
++       * mips in linux kernel 4.4.0 returns -ENOSYS if it can not
++       * handle the syscall in vdso, the original syscall should be
++       * called by the libc in such a case.
++       */
++      if (ret == -ENOSYS)
++              return sc_clock_gettime(clk, ts);
++      return ret;
+ #else
+       return sc_clock_gettime(clk, ts);
+ #endif
 -- 
 2.7.0.rc3