add sched_getcpu vDSO support
authorNathan Zadoks <nathan@nathan7.eu>
Wed, 2 Mar 2016 16:26:27 +0000 (17:26 +0100)
committerRich Felker <dalias@aerifal.cx>
Thu, 3 Mar 2016 02:35:40 +0000 (21:35 -0500)
This brings the call to an actually usable speed.
Quick unscientific benchmark: 14ns : 102ns :: vDSO : syscall

arch/x86_64/syscall_arch.h
src/sched/sched_getcpu.c

index a7a7b5a..54e05ff 100644 (file)
@@ -64,3 +64,5 @@ static __inline long __syscall6(long n, long a1, long a2, long a3, long a4, long
 #define VDSO_USEFUL
 #define VDSO_CGT_SYM "__vdso_clock_gettime"
 #define VDSO_CGT_VER "LINUX_2.6"
+#define VDSO_GETCPU_SYM "__vdso_getcpu"
+#define VDSO_GETCPU_VER "LINUX_2.6"
index 760e4d5..e08cfdf 100644 (file)
@@ -1,12 +1,43 @@
 #define _GNU_SOURCE
+#include <errno.h>
 #include <sched.h>
 #include "syscall.h"
+#include "atomic.h"
+
+#ifdef VDSO_GETCPU_SYM
+
+void *__vdsosym(const char *, const char *);
+
+static void *volatile vdso_func;
+
+typedef long (*getcpu_f)(unsigned *, unsigned *, void *);
+
+static long getcpu_init(unsigned *cpu, unsigned *node, void *unused)
+{
+       void *p = __vdsosym(VDSO_GETCPU_VER, VDSO_GETCPU_SYM);
+       getcpu_f f = (getcpu_f)p;
+       a_cas_p(&vdso_func, (void *)getcpu_init, p);
+       return f ? f(cpu, node, unused) : -ENOSYS;
+}
+
+static void *volatile vdso_func = (void *)getcpu_init;
+
+#endif
 
 int sched_getcpu(void)
 {
        int r;
        unsigned cpu;
 
+#ifdef VDSO_GETCPU_SYM
+       getcpu_f f = (getcpu_f)vdso_func;
+       if (f) {
+               r = f(&cpu, 0, 0);
+               if (!r) return cpu;
+               if (r != -ENOSYS) return __syscall_ret(r);
+       }
+#endif
+
        r = __syscall(SYS_getcpu, &cpu, 0, 0);
        if (!r) return cpu;
        return __syscall_ret(r);