History

[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

Andi Kleen committed 20 years ago

Commit 3cfc3481 parent c08c8205 files · +37 −1Browse files

Unified · Split

5 files
  1. arch/i386/kernel/syscall_table.S +1 −0
  2. arch/x86_64/ia32/ia32entry.S +1 −0
  3. include/asm-i386/unistd.h +2 −1
  4. include/linux/syscalls.h +2 −0
  5. kernel/sys.c +31 −0
arch/i386/kernel/syscall_table.S+1−0
@@ -317,3 +317,4 @@ ENTRY(sys_call_table) · 316 unmodified lines
317317 .long sys_tee /* 315 */
318318 .long sys_vmsplice
319319 .long sys_move_pages
320+ .long sys_getcpu
arch/x86_64/ia32/ia32entry.S+1−0
@@ -713,4 +713,5 @@ ia32_sys_call_table: · 712 unmodified lines
713713 .quad sys_tee
714714 .quad compat_sys_vmsplice
715715 .quad compat_sys_move_pages
716+ .quad sys_getcpu
716717 ia32_syscall_end:
include/asm-i386/unistd.h+2−1
@@ -323,10 +323,11 @@ · 322 unmodified lines
323323 #define __NR_tee 315
324324 #define __NR_vmsplice 316
325325 #define __NR_move_pages 317
326+#define __NR_getcpu 318
326327
327328 #ifdef __KERNEL__
328329
329−#define NR_syscalls 318
330+#define NR_syscalls 319
330331
331332 /*
332333 * user-visible error numbers are in the range -1 - -128: see
include/linux/syscalls.h+2−0
@@ -53,6 +53,7 @@ struct mq_attr; · 52 unmodified lines
5353 struct compat_stat;
5454 struct compat_timeval;
5555 struct robust_list_head;
56+struct getcpu_cache;
5657
5758 #include <linux/types.h>
5859 #include <linux/aio_abi.h>
@@ -596,5 +597,6 @@ asmlinkage long sys_get_robust_list(int pid, · 537 unmodified lines
596597 size_t __user *len_ptr);
597598 asmlinkage long sys_set_robust_list(struct robust_list_head __user *head,
598599 size_t len);
600+asmlinkage long sys_getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *cache);
599601
600602 #endif
kernel/sys.c+31−0
@@ -28,6 +28,7 @@ · 27 unmodified lines
2828 #include <linux/tty.h>
2929 #include <linux/signal.h>
3030 #include <linux/cn_proc.h>
31+#include <linux/getcpu.h>
3132
3233 #include <linux/compat.h>
3334 #include <linux/syscalls.h>
@@ -2062,3 +2063,33 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3, · 2028 unmodified lines
20622063 }
20632064 return error;
20642065 }
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;
2095+}