<sched.h>: Add sched_getcpu() and cpu_set_t

This adds the cpu_set_t type definition and related functions
and macros used to handle CPU thread affinity.

  sched_getcpu()
  sched_setaffinity()
  sched_getaffinity()

Change-Id: If382ecafde8926341a88478062b275553645065b
diff --git a/libc/Android.mk b/libc/Android.mk
index 59e8e32..8a22918 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -273,6 +273,10 @@
 	bionic/md5.c \
 	bionic/pututline.c \
 	bionic/realpath.c \
+	bionic/sched_getaffinity.c \
+	bionic/sched_getcpu.c \
+	bionic/sched_cpualloc.c \
+	bionic/sched_cpucount.c \
 	bionic/semaphore.c \
 	bionic/sha1.c \
 	bionic/ssp.c \
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index 0a08e12..2bb8a42 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -229,6 +229,9 @@
 int sched_get_priority_max(int policy)  159
 int sched_get_priority_min(int policy)  160
 int sched_rr_get_interval(pid_t pid, struct timespec *interval)  161
+int sched_setaffinity(pid_t pid, size_t setsize, const cpu_set_t* set) 241
+int __sched_getaffinity:sched_getaffinity(pid_t pid, size_t setsize, cpu_set_t* set)  242
+int __getcpu:getcpu(unsigned *cpu, unsigned *node, void *unused) 345,318,318
 
 # io priorities
 int ioprio_set(int which, int who, int ioprio) 314,289,288
diff --git a/libc/arch-arm/syscalls.mk b/libc/arch-arm/syscalls.mk
index ba78c18..e25bb31 100644
--- a/libc/arch-arm/syscalls.mk
+++ b/libc/arch-arm/syscalls.mk
@@ -153,6 +153,9 @@
 syscall_src += arch-arm/syscalls/sched_get_priority_max.S
 syscall_src += arch-arm/syscalls/sched_get_priority_min.S
 syscall_src += arch-arm/syscalls/sched_rr_get_interval.S
+syscall_src += arch-arm/syscalls/sched_setaffinity.S
+syscall_src += arch-arm/syscalls/__sched_getaffinity.S
+syscall_src += arch-arm/syscalls/__getcpu.S
 syscall_src += arch-arm/syscalls/ioprio_set.S
 syscall_src += arch-arm/syscalls/ioprio_get.S
 syscall_src += arch-arm/syscalls/uname.S
diff --git a/libc/arch-arm/syscalls/__getcpu.S b/libc/arch-arm/syscalls/__getcpu.S
new file mode 100644
index 0000000..ed6927a
--- /dev/null
+++ b/libc/arch-arm/syscalls/__getcpu.S
@@ -0,0 +1,19 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+
+    .text
+    .type __getcpu, #function
+    .globl __getcpu
+    .align 4
+    .fnstart
+
+__getcpu:
+    .save   {r4, r7}
+    stmfd   sp!, {r4, r7}
+    ldr     r7, =__NR_getcpu
+    swi     #0
+    ldmfd   sp!, {r4, r7}
+    movs    r0, r0
+    bxpl    lr
+    b       __set_syscall_errno
+    .fnend
diff --git a/libc/arch-arm/syscalls/__sched_getaffinity.S b/libc/arch-arm/syscalls/__sched_getaffinity.S
new file mode 100644
index 0000000..71f2b1d
--- /dev/null
+++ b/libc/arch-arm/syscalls/__sched_getaffinity.S
@@ -0,0 +1,19 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+
+    .text
+    .type __sched_getaffinity, #function
+    .globl __sched_getaffinity
+    .align 4
+    .fnstart
+
+__sched_getaffinity:
+    .save   {r4, r7}
+    stmfd   sp!, {r4, r7}
+    ldr     r7, =__NR_sched_getaffinity
+    swi     #0
+    ldmfd   sp!, {r4, r7}
+    movs    r0, r0
+    bxpl    lr
+    b       __set_syscall_errno
+    .fnend
diff --git a/libc/arch-arm/syscalls/sched_setaffinity.S b/libc/arch-arm/syscalls/sched_setaffinity.S
new file mode 100644
index 0000000..aedf8f3
--- /dev/null
+++ b/libc/arch-arm/syscalls/sched_setaffinity.S
@@ -0,0 +1,19 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+
+    .text
+    .type sched_setaffinity, #function
+    .globl sched_setaffinity
+    .align 4
+    .fnstart
+
+sched_setaffinity:
+    .save   {r4, r7}
+    stmfd   sp!, {r4, r7}
+    ldr     r7, =__NR_sched_setaffinity
+    swi     #0
+    ldmfd   sp!, {r4, r7}
+    movs    r0, r0
+    bxpl    lr
+    b       __set_syscall_errno
+    .fnend
diff --git a/libc/arch-sh/syscalls.mk b/libc/arch-sh/syscalls.mk
index a87419d..493f437 100644
--- a/libc/arch-sh/syscalls.mk
+++ b/libc/arch-sh/syscalls.mk
@@ -142,6 +142,9 @@
 syscall_src += arch-sh/syscalls/sched_get_priority_max.S
 syscall_src += arch-sh/syscalls/sched_get_priority_min.S
 syscall_src += arch-sh/syscalls/sched_rr_get_interval.S
+syscall_src += arch-sh/syscalls/sched_setaffinity.S
+syscall_src += arch-sh/syscalls/__sched_getaffinity.S
+syscall_src += arch-sh/syscalls/__getcpu.S
 syscall_src += arch-sh/syscalls/ioprio_set.S
 syscall_src += arch-sh/syscalls/ioprio_get.S
 syscall_src += arch-sh/syscalls/uname.S
diff --git a/libc/arch-sh/syscalls/__getcpu.S b/libc/arch-sh/syscalls/__getcpu.S
new file mode 100644
index 0000000..125387b
--- /dev/null
+++ b/libc/arch-sh/syscalls/__getcpu.S
@@ -0,0 +1,32 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+
+    .text
+    .type __getcpu, @function
+    .globl __getcpu
+    .align 4
+
+__getcpu:
+
+    /* invoke trap */
+    mov.l   0f, r3  /* trap num */
+    trapa   #(3 + 0x10)
+
+    /* check return value */
+    cmp/pz  r0
+    bt      __NR_getcpu_end
+
+    /* keep error number */
+    sts.l   pr, @-r15
+    mov.l   1f, r1
+    jsr     @r1
+    mov     r0, r4
+    lds.l   @r15+, pr
+
+__NR_getcpu_end:
+    rts
+    nop
+
+    .align  2
+0:  .long   __NR_getcpu
+1:  .long   __set_syscall_errno
diff --git a/libc/arch-sh/syscalls/__sched_getaffinity.S b/libc/arch-sh/syscalls/__sched_getaffinity.S
new file mode 100644
index 0000000..7e8be6a
--- /dev/null
+++ b/libc/arch-sh/syscalls/__sched_getaffinity.S
@@ -0,0 +1,32 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+
+    .text
+    .type __sched_getaffinity, @function
+    .globl __sched_getaffinity
+    .align 4
+
+__sched_getaffinity:
+
+    /* invoke trap */
+    mov.l   0f, r3  /* trap num */
+    trapa   #(3 + 0x10)
+
+    /* check return value */
+    cmp/pz  r0
+    bt      __NR_sched_getaffinity_end
+
+    /* keep error number */
+    sts.l   pr, @-r15
+    mov.l   1f, r1
+    jsr     @r1
+    mov     r0, r4
+    lds.l   @r15+, pr
+
+__NR_sched_getaffinity_end:
+    rts
+    nop
+
+    .align  2
+0:  .long   __NR_sched_getaffinity
+1:  .long   __set_syscall_errno
diff --git a/libc/arch-sh/syscalls/sched_setaffinity.S b/libc/arch-sh/syscalls/sched_setaffinity.S
new file mode 100644
index 0000000..9dda3b4
--- /dev/null
+++ b/libc/arch-sh/syscalls/sched_setaffinity.S
@@ -0,0 +1,32 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+
+    .text
+    .type sched_setaffinity, @function
+    .globl sched_setaffinity
+    .align 4
+
+sched_setaffinity:
+
+    /* invoke trap */
+    mov.l   0f, r3  /* trap num */
+    trapa   #(3 + 0x10)
+
+    /* check return value */
+    cmp/pz  r0
+    bt      __NR_sched_setaffinity_end
+
+    /* keep error number */
+    sts.l   pr, @-r15
+    mov.l   1f, r1
+    jsr     @r1
+    mov     r0, r4
+    lds.l   @r15+, pr
+
+__NR_sched_setaffinity_end:
+    rts
+    nop
+
+    .align  2
+0:  .long   __NR_sched_setaffinity
+1:  .long   __set_syscall_errno
diff --git a/libc/arch-x86/syscalls.mk b/libc/arch-x86/syscalls.mk
index 420a91e..c210b21 100644
--- a/libc/arch-x86/syscalls.mk
+++ b/libc/arch-x86/syscalls.mk
@@ -156,6 +156,9 @@
 syscall_src += arch-x86/syscalls/sched_get_priority_max.S
 syscall_src += arch-x86/syscalls/sched_get_priority_min.S
 syscall_src += arch-x86/syscalls/sched_rr_get_interval.S
+syscall_src += arch-x86/syscalls/sched_setaffinity.S
+syscall_src += arch-x86/syscalls/__sched_getaffinity.S
+syscall_src += arch-x86/syscalls/__getcpu.S
 syscall_src += arch-x86/syscalls/ioprio_set.S
 syscall_src += arch-x86/syscalls/ioprio_get.S
 syscall_src += arch-x86/syscalls/uname.S
diff --git a/libc/arch-x86/syscalls/__getcpu.S b/libc/arch-x86/syscalls/__getcpu.S
new file mode 100644
index 0000000..0381799
--- /dev/null
+++ b/libc/arch-x86/syscalls/__getcpu.S
@@ -0,0 +1,29 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+
+    .text
+    .type __getcpu, @function
+    .globl __getcpu
+    .align 4
+
+__getcpu:
+    pushl   %ebx
+    pushl   %ecx
+    pushl   %edx
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
+    mov     24(%esp), %edx
+    movl    $__NR_getcpu, %eax
+    int     $0x80
+    cmpl    $-129, %eax
+    jb      1f
+    negl    %eax
+    pushl   %eax
+    call    __set_errno
+    addl    $4, %esp
+    orl     $-1, %eax
+1:
+    popl    %edx
+    popl    %ecx
+    popl    %ebx
+    ret
diff --git a/libc/arch-x86/syscalls/__sched_getaffinity.S b/libc/arch-x86/syscalls/__sched_getaffinity.S
new file mode 100644
index 0000000..43bfa50
--- /dev/null
+++ b/libc/arch-x86/syscalls/__sched_getaffinity.S
@@ -0,0 +1,29 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+
+    .text
+    .type __sched_getaffinity, @function
+    .globl __sched_getaffinity
+    .align 4
+
+__sched_getaffinity:
+    pushl   %ebx
+    pushl   %ecx
+    pushl   %edx
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
+    mov     24(%esp), %edx
+    movl    $__NR_sched_getaffinity, %eax
+    int     $0x80
+    cmpl    $-129, %eax
+    jb      1f
+    negl    %eax
+    pushl   %eax
+    call    __set_errno
+    addl    $4, %esp
+    orl     $-1, %eax
+1:
+    popl    %edx
+    popl    %ecx
+    popl    %ebx
+    ret
diff --git a/libc/arch-x86/syscalls/sched_setaffinity.S b/libc/arch-x86/syscalls/sched_setaffinity.S
new file mode 100644
index 0000000..5fa51ef
--- /dev/null
+++ b/libc/arch-x86/syscalls/sched_setaffinity.S
@@ -0,0 +1,29 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+
+    .text
+    .type sched_setaffinity, @function
+    .globl sched_setaffinity
+    .align 4
+
+sched_setaffinity:
+    pushl   %ebx
+    pushl   %ecx
+    pushl   %edx
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
+    mov     24(%esp), %edx
+    movl    $__NR_sched_setaffinity, %eax
+    int     $0x80
+    cmpl    $-129, %eax
+    jb      1f
+    negl    %eax
+    pushl   %eax
+    call    __set_errno
+    addl    $4, %esp
+    orl     $-1, %eax
+1:
+    popl    %edx
+    popl    %ecx
+    popl    %ebx
+    ret
diff --git a/libc/bionic/sched_cpualloc.c b/libc/bionic/sched_cpualloc.c
new file mode 100644
index 0000000..30964bc
--- /dev/null
+++ b/libc/bionic/sched_cpualloc.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#define _GNU_SOURCE 1
+#include <sched.h>
+#include <stdlib.h>
+
+cpu_set_t* __sched_cpualloc(size_t count)
+{
+    return (cpu_set_t*) malloc(CPU_ALLOC_SIZE(count));
+}
+
+void __sched_cpufree(cpu_set_t* set)
+{
+    free(set);
+}
diff --git a/libc/bionic/sched_cpucount.c b/libc/bionic/sched_cpucount.c
new file mode 100644
index 0000000..9458dc8
--- /dev/null
+++ b/libc/bionic/sched_cpucount.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#define _GNU_SOURCE 1
+#include <sched.h>
+
+int __sched_cpucount(size_t setsize, cpu_set_t* set)
+{
+    int nn = 0, nn_max = setsize / sizeof(__CPU_BITTYPE);
+    int count = 0;
+
+    for ( ; nn < nn_max; nn++ )
+        count += __builtin_popcount(set->__bits[nn]);
+
+    return count;
+}
diff --git a/libc/bionic/sched_getaffinity.c b/libc/bionic/sched_getaffinity.c
new file mode 100644
index 0000000..7313822
--- /dev/null
+++ b/libc/bionic/sched_getaffinity.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#define _GNU_SOURCE 1
+#include <sched.h>
+
+int  sched_getaffinity(pid_t pid, size_t setsize, cpu_set_t* set)
+{
+    int ret = __sched_getaffinity(pid, setsize, set);
+    if (ret >= 0) {
+        if ((size_t)ret < setsize) {
+            memset((char*)set + ret, '\0', setsize - (size_t)ret);
+        }
+        ret = 0;
+    }
+    return ret;
+}
diff --git a/libc/bionic/sched_getcpu.c b/libc/bionic/sched_getcpu.c
new file mode 100644
index 0000000..954df37
--- /dev/null
+++ b/libc/bionic/sched_getcpu.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#define _GNU_SOURCE 1
+#include <sched.h>
+
+extern int  __getcpu(unsigned *cpu, unsigned *node, void* unused);
+
+int  sched_getcpu(void)
+{
+    unsigned cpu;
+    if (__getcpu(&cpu, NULL, NULL) < 0)
+        return 0;
+
+    return (int)cpu;
+}
diff --git a/libc/docs/CHANGES.TXT b/libc/docs/CHANGES.TXT
index 67b9e76..8e23c0e 100644
--- a/libc/docs/CHANGES.TXT
+++ b/libc/docs/CHANGES.TXT
@@ -11,6 +11,9 @@
 
 - <time.h>: Add timegm(), timelocal(), time2posix() and posix2time()
 
+- <sched.h>: Add sched_getcpu(), sched_getaffinity(), sched_setaffinity(),
+  cpu_set_t and related macros (e.g. CPU_SETSIZE, CPU_ZERO, CPU_SET, ...)
+
 -------------------------------------------------------------------------------
 Differences between Android 2.3 and Android 2.2:
 
diff --git a/libc/include/sched.h b/libc/include/sched.h
index e702470..ca72da7 100644
--- a/libc/include/sched.h
+++ b/libc/include/sched.h
@@ -73,6 +73,162 @@
 extern int clone(int (*fn)(void *), void *child_stack, int flags, void*  arg, ...);
 #endif
 
+/* Support for cpu thread affinity */
+#ifdef _GNU_SOURCE
+
+extern int sched_getcpu(void);
+
+
+/* Our implementation supports up to 32 independent CPUs, which is also
+ * the maximum supported by the kernel at the moment. GLibc uses 1024 by
+ * default.
+ *
+ * If you want to use more than that, you should use CPU_ALLOC() / CPU_FREE()
+ * and the CPU_XXX_S() macro variants.
+ */
+#define CPU_SETSIZE   32
+
+#define __CPU_BITTYPE    unsigned long int  /* mandated by the kernel  */
+#define __CPU_BITSHIFT   5                  /* should be log2(BITTYPE) */
+#define __CPU_BITS       (1 << __CPU_BITSHIFT)
+#define __CPU_ELT(x)     ((x) >> __CPU_BITSHIFT)
+#define __CPU_MASK(x)    ((__CPU_BITTYPE)1 << ((x) & (__CPU_BITS-1)))
+
+typedef struct {
+    __CPU_BITTYPE  __bits[ CPU_SETSIZE / __CPU_BITS ];
+} cpu_set_t;
+
+extern int sched_setaffinity(pid_t pid, size_t setsize, const cpu_set_t* set);
+
+extern int sched_getaffinity(pid_t pid, size_t setsize, cpu_set_t* set);
+
+/* Provide optimized implementation for 32-bit cpu_set_t */
+#if CPU_SETSIZE == __CPU_BITS
+
+#  define CPU_ZERO(set_)   \
+    do{ \
+        (set_)->__bits[0] = 0; \
+    }while(0)
+
+#  define CPU_SET(cpu_,set_) \
+    do {\
+        size_t __cpu = (cpu_); \
+        if (__cpu < CPU_SETSIZE) \
+            (set_)->__bits[0] |= __CPU_MASK(__cpu); \
+    }while (0)
+
+#  define CPU_CLR(cpu_,set_) \
+    do {\
+        size_t __cpu = (cpu_); \
+        if (__cpu < CPU_SETSIZE) \
+            (set_)->__bits[0] &= ~__CPU_MASK(__cpu); \
+    }while (0)
+
+#  define CPU_ISSET(cpu_, set_) \
+    (__extension__({\
+        size_t  __cpu = (cpu_); \
+        (cpu_ < CPU_SETSIZE) \
+            ? ((set_)->__bits[0] & __CPU_MASK(__cpu)) != 0 \
+            : 0; \
+    }))
+
+#  define CPU_EQUAL(set1_, set2_) \
+    ((set1_)->__bits[0] == (set2_)->__bits[0])
+
+#  define __CPU_OP(dst_, set1_, set2_, op_) \
+    do { \
+        (dst_)->__bits[0] = (set1_)->__bits[0] op_ (set2_)->__bits[0]; \
+    } while (0)
+
+#  define CPU_COUNT(set_)  __builtin_popcountl((set_)->__bits[0])
+
+#else /* CPU_SETSIZE != __CPU_BITS */
+
+#  define CPU_ZERO(set_)          CPU_ZERO_S(sizeof(cpu_set_t), set_)
+#  define CPU_SET(cpu_,set_)      CPU_SET_S(cpu_,sizeof(cpu_set_t),set_)
+#  define CPU_CLR(cpu_,set_)      CPU_CLR_S(cpu_,sizeof(cpu_set_t),set_)
+#  define CPU_ISSET(cpu_,set_)    CPU_ISSET_S(cpu_,sizeof(cpu_set_t),set_)
+#  define CPU_COUNT(set_)         CPU_COUNT_S(sizeof(cpu_set_t),set_)
+#  define CPU_EQUAL(set1_,set2_)  CPU_EQUAL_S(sizeof(cpu_set_t),set1_,set2_)
+
+#  define __CPU_OP(dst_,set1_,set2_,op_)  __CPU_OP_S(sizeof(cpu_set_t),dst_,set1_,set2_,op_)
+
+#endif /* CPU_SETSIZE != __CPU_BITS */
+
+#define CPU_AND(set1_,set2_)   __CPU_OP(set1_,set2_,&)
+#define CPU_OR(set1_,set2_)    __CPU_OP(set1_,set2_,|)
+#define CPU_XOR(set1_,set2_)   __CPU_OP(set1_,set2_,^)
+
+/* Support for dynamically-allocated cpu_set_t */
+
+#define CPU_ALLOC_SIZE(count) \
+    __CPU_ELT((count) + (__CPU_BITS-1))*sizeof(__CPU_BITTYPE)
+
+#define CPU_ALLOC(count)   __sched_cpualloc((count));
+#define CPU_FREE(set)      __sched_cpufree((set))
+
+extern cpu_set_t* __sched_cpualloc(size_t count);
+extern void       __sched_cpufree(cpu_set_t* set);
+
+#define CPU_ZERO_S(setsize_,set_)  \
+    do { \
+        size_t __nn = 0; \
+        size_t __nn_max = (setsize_)/sizeof(__CPU_BITTYPE); \
+        for (; __nn < __nn_max; __nn++) \
+            (set_)->__bits[__nn] = 0; \
+    } while (0)
+
+#define CPU_SET_S(cpu_,setsize_,set_) \
+    do { \
+        size_t __cpu = (cpu_); \
+        if (__cpu < 8*(setsize_)) \
+            (set_)->__bits[__CPU_ELT(__cpu)] |= __CPU_MASK(__cpu); \
+    } while (0)
+
+#define CPU_CLR_S(cpu_,setsize_,set_) \
+    do { \
+        size_t __cpu = (cpu_); \
+        if (__cpu < 8*(setsize_)) \
+            (set_)->__bits[__CPU_ELT(__cpu)] &= ~__CPU_MASK(__cpu); \
+    } while (0)
+
+#define CPU_ISSET_S(cpu_, setsize_, set_) \
+    (__extension__ ({ \
+        size_t __cpu = (cpu_); \
+        (__cpu < 8*(setsize_)) \
+          ? ((set_)->__bits[__CPU_ELT(__cpu)] & __CPU_MASK(__cpu)) != 0 \
+          : 0; \
+    }))
+
+#define CPU_EQUAL_S(setsize_, set1_, set2_) \
+    (__extension__ ({ \
+        __const __CPU_BITTYPE* __src1 = (set1_)->__bits; \
+        __const __CPU_BITTYPE* __src2 = (set2_)->__bits; \
+        size_t __nn = 0, __nn_max = (setsize_)/sizeof(__CPU_BITTYPE); \
+        for (; __nn < __nn_max; __nn++) { \
+            if (__src1[__nn] != __src2[__nn]) \
+                break; \
+        } \
+        __nn == __nn_max; \
+    }))
+
+#define __CPU_OP_S(setsize_, dstset_, srcset1_, srcset2_, op) \
+    do { \
+        cpu_set_t* __dst = (dstset); \
+        const __CPU_BITTYPE* __src1 = (srcset1)->__bits; \
+        const __CPU_BITTYPE* __src2 = (srcset2)->__bits; \
+        size_t __nn = 0, __nn_max = (setsize_)/sizeof(__CPU_BITTYPE); \
+        for (; __nn < __nn_max; __nn++) \
+            (__dst)->__bits[__nn] = __src1[__nn] op __src2[__nn]; \
+    } while (0)
+
+#define CPU_COUNT_S(setsize_, set_) \
+    __sched_cpucount((setsize_), (set_))
+
+extern int __sched_cpucount(size_t setsize, cpu_set_t* set);
+
+#endif /* _GNU_SOURCE */
+
 __END_DECLS
 
 #endif /* _SCHED_H_ */
diff --git a/libc/include/sys/linux-syscalls.h b/libc/include/sys/linux-syscalls.h
index 9702a7a..35729ae 100644
--- a/libc/include/sys/linux-syscalls.h
+++ b/libc/include/sys/linux-syscalls.h
@@ -120,6 +120,8 @@
 #define __NR_sched_get_priority_max       (__NR_SYSCALL_BASE + 159)
 #define __NR_sched_get_priority_min       (__NR_SYSCALL_BASE + 160)
 #define __NR_sched_rr_get_interval        (__NR_SYSCALL_BASE + 161)
+#define __NR_sched_setaffinity            (__NR_SYSCALL_BASE + 241)
+#define __NR_sched_getaffinity            (__NR_SYSCALL_BASE + 242)
 #define __NR_uname                        (__NR_SYSCALL_BASE + 122)
 #define __NR_wait4                        (__NR_SYSCALL_BASE + 114)
 #define __NR_umask                        (__NR_SYSCALL_BASE + 60)
@@ -174,6 +176,7 @@
 #define __NR_getsockopt                   (__NR_SYSCALL_BASE + 295)
 #define __NR_sendmsg                      (__NR_SYSCALL_BASE + 296)
 #define __NR_recvmsg                      (__NR_SYSCALL_BASE + 297)
+#define __NR_getcpu                       (__NR_SYSCALL_BASE + 345)
 #define __NR_ioprio_set                   (__NR_SYSCALL_BASE + 314)
 #define __NR_ioprio_get                   (__NR_SYSCALL_BASE + 315)
 #define __NR_epoll_create                 (__NR_SYSCALL_BASE + 250)
@@ -218,6 +221,7 @@
 #define __NR_timer_delete                 (__NR_SYSCALL_BASE + 263)
 #define __NR_utimes                       (__NR_SYSCALL_BASE + 271)
 #define __NR_socketcall                   (__NR_SYSCALL_BASE + 102)
+#define __NR_getcpu                       (__NR_SYSCALL_BASE + 318)
 #define __NR_ioprio_set                   (__NR_SYSCALL_BASE + 289)
 #define __NR_ioprio_get                   (__NR_SYSCALL_BASE + 290)
 #define __NR_epoll_create                 (__NR_SYSCALL_BASE + 254)
@@ -276,6 +280,7 @@
 #define __NR_socketcall                   (__NR_SYSCALL_BASE + 102)
 #define __NR_socketcall                   (__NR_SYSCALL_BASE + 102)
 #define __NR___socketcall                 (__NR_SYSCALL_BASE + 102)
+#define __NR_getcpu                       (__NR_SYSCALL_BASE + 318)
 #define __NR_ioprio_set                   (__NR_SYSCALL_BASE + 288)
 #define __NR_ioprio_get                   (__NR_SYSCALL_BASE + 289)
 #define __NR_epoll_create                 (__NR_SYSCALL_BASE + 254)
diff --git a/libc/include/sys/linux-unistd.h b/libc/include/sys/linux-unistd.h
index 48c5c77..4a61724 100644
--- a/libc/include/sys/linux-unistd.h
+++ b/libc/include/sys/linux-unistd.h
@@ -53,7 +53,7 @@
 ssize_t          read (int, void*, size_t);
 ssize_t          write (int, const void*, size_t);
 ssize_t          __pread64 (int, void *, size_t, off_t, off_t);
-ssize_t          __pwrite64 (int, const void *, size_t, off_t, off_t);
+ssize_t          __pwrite64 (int, void *, size_t, off_t, off_t);
 int              __open (const char*, int, mode_t);
 int              __openat (int, const char*, int, mode_t);
 int              close (int);
@@ -183,6 +183,9 @@
 int              sched_get_priority_max (int policy);
 int              sched_get_priority_min (int policy);
 int              sched_rr_get_interval (pid_t pid, struct timespec *interval);
+int              sched_setaffinity (pid_t pid, size_t setsize, const cpu_set_t* set);
+int              __sched_getaffinity (pid_t pid, size_t setsize, cpu_set_t* set);
+int              __getcpu (unsigned *cpu, unsigned *node, void *unused);
 int              ioprio_set (int which, int who, int ioprio);
 int              ioprio_get (int which, int who);
 int              uname (struct utsname *);
@@ -205,7 +208,6 @@
 int              eventfd (unsigned int, int);
 int              __set_tls (void*);
 int              cacheflush (long start, long end, long flags);
-int              eventfd (int count, int flags);
 #ifdef __cplusplus
 }
 #endif