Commit 3cfc348bf90ffaa777c188652aa297f04eb94de8

Authored by Andi Kleen
Committed by Andi Kleen
1 parent c08c820508

[PATCH] x86: Add portable getcpu call

For NUMA optimization and some other algorithms it is useful to have a fast
to get the current CPU and node numbers in user space.

x86-64 added a fast way to do this in a vsyscall. This adds a generic
syscall for other architectures to make it a generic portable facility.

I expect some of them will also implement it as a faster vsyscall.

The cache is an optimization for the x86-64 vsyscall optimization. Since
what the syscall returns is an approximation anyways and user space
often wants very fast results it can be cached for some time.  The norma
methods to get this information in user space are relatively slow

The vsyscall is in a better position to manage the cache because it has direct
access to a fast time stamp (jiffies). For the generic syscall optimization
it doesn't help much, but enforce a valid argument to keep programs
portable

I only added an i386 syscall entry for now. Other architectures can follow
as needed.

AK: Also added some cleanups from Andrew Morton

Signed-off-by: Andi Kleen <ak@suse.de>

Showing 5 changed files with 37 additions and 1 deletions Side-by-side Diff

arch/i386/kernel/syscall_table.S
... ... @@ -317,4 +317,5 @@
317 317 .long sys_tee /* 315 */
318 318 .long sys_vmsplice
319 319 .long sys_move_pages
  320 + .long sys_getcpu
arch/x86_64/ia32/ia32entry.S
... ... @@ -713,5 +713,6 @@
713 713 .quad sys_tee
714 714 .quad compat_sys_vmsplice
715 715 .quad compat_sys_move_pages
  716 + .quad sys_getcpu
716 717 ia32_syscall_end:
include/asm-i386/unistd.h
... ... @@ -323,10 +323,11 @@
323 323 #define __NR_tee 315
324 324 #define __NR_vmsplice 316
325 325 #define __NR_move_pages 317
  326 +#define __NR_getcpu 318
326 327  
327 328 #ifdef __KERNEL__
328 329  
329   -#define NR_syscalls 318
  330 +#define NR_syscalls 319
330 331  
331 332 /*
332 333 * user-visible error numbers are in the range -1 - -128: see
include/linux/syscalls.h
... ... @@ -53,6 +53,7 @@
53 53 struct compat_stat;
54 54 struct compat_timeval;
55 55 struct robust_list_head;
  56 +struct getcpu_cache;
56 57  
57 58 #include <linux/types.h>
58 59 #include <linux/aio_abi.h>
... ... @@ -596,6 +597,7 @@
596 597 size_t __user *len_ptr);
597 598 asmlinkage long sys_set_robust_list(struct robust_list_head __user *head,
598 599 size_t len);
  600 +asmlinkage long sys_getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *cache);
599 601  
600 602 #endif
... ... @@ -28,6 +28,7 @@
28 28 #include <linux/tty.h>
29 29 #include <linux/signal.h>
30 30 #include <linux/cn_proc.h>
  31 +#include <linux/getcpu.h>
31 32  
32 33 #include <linux/compat.h>
33 34 #include <linux/syscalls.h>
... ... @@ -2061,5 +2062,35 @@
2061 2062 break;
2062 2063 }
2063 2064 return error;
  2065 +}
  2066 +
  2067 +asmlinkage long sys_getcpu(unsigned __user *cpup, unsigned __user *nodep,
  2068 + struct getcpu_cache __user *cache)
  2069 +{
  2070 + int err = 0;
  2071 + int cpu = raw_smp_processor_id();
  2072 + if (cpup)
  2073 + err |= put_user(cpu, cpup);
  2074 + if (nodep)
  2075 + err |= put_user(cpu_to_node(cpu), nodep);
  2076 + if (cache) {
  2077 + /*
  2078 + * The cache is not needed for this implementation,
  2079 + * but make sure user programs pass something
  2080 + * valid. vsyscall implementations can instead make
  2081 + * good use of the cache. Only use t0 and t1 because
  2082 + * these are available in both 32bit and 64bit ABI (no
  2083 + * need for a compat_getcpu). 32bit has enough
  2084 + * padding
  2085 + */
  2086 + unsigned long t0, t1;
  2087 + get_user(t0, &cache->t0);
  2088 + get_user(t1, &cache->t1);
  2089 + t0++;
  2090 + t1++;
  2091 + put_user(t0, &cache->t0);
  2092 + put_user(t1, &cache->t1);
  2093 + }
  2094 + return err ? -EFAULT : 0;
2064 2095 }