Add sched_getaffinity(2) and sched_setaffinity(2)

"Indan Zupancic" <[email protected]> Mon, 6 Dec 2010 12:02:26 +0100 (CET)
Newsgroups gmane.linux.lib.dietlibc
Message-ID <[email protected]>
Hello,

This patch follows glib behaviour and also adds some of the CPU_SET(3)
macros. The maximum number of cpus supported is 32 for 32 bits machines
and 64 for 64 bits machines (cpu_set_t is a long). That said, this is
only a limitation for the macros, the system calls are more flexible.

Greetings,

Indan


Index: dietfeatures.h
===================================================================
RCS file: /cvs/dietlibc/dietfeatures.h,v
retrieving revision 1.69
diff -u -p -b -B -w -r1.69 dietfeatures.h
--- dietfeatures.h	1 Aug 2010 19:56:21 -0000	1.69
+++ dietfeatures.h	6 Dec 2010 10:58:17 -0000
@@ -22,6 +22,12 @@
 /* this is only for meaningful for ttyname and sysconf_cpus so far */
 #define SLASH_PROC_OK

+/*
+ * Only meaningful for sysconf_cpus so far.
+ * If set, you can unset SLASH_PROC_OK for sysconf(_SC_NPROCESSORS_ONLN).
+ */
+#define _HAVE_LINUX26
+
 /* use errno_location instead of errno; NEEDED FOR MULTI-THREADING! */
 #define WANT_THREAD_SAFE

Index: arm/dyn_syscalls.S
===================================================================
RCS file: /cvs/dietlibc/arm/dyn_syscalls.S,v
retrieving revision 1.31
diff -u -p -b -B -w -r1.31 dyn_syscalls.S
--- arm/dyn_syscalls.S	7 Jul 2008 12:31:53 -0000	1.31
+++ arm/dyn_syscalls.S	6 Dec 2010 10:58:17 -0000
@@ -125,6 +125,8 @@ __unified_syscall:
 #include "../syscalls.s/rt_sigqueueinfo.S"
 #include "../syscalls.s/rt_sigsuspend.S"
 #include "../syscalls.s/rt_sigtimedwait.S"
+#include "../syscalls.s/sched_getaffinity.S"
+#include "../syscalls.s/sched_setaffinity.S"
 #include "../syscalls.s/sched_get_priority_max.S"
 #include "../syscalls.s/sched_get_priority_min.S"
 #include "../syscalls.s/sched_getparam.S"
Index: i386/dyn_syscalls.S
===================================================================
RCS file: /cvs/dietlibc/i386/dyn_syscalls.S,v
retrieving revision 1.41
diff -u -p -b -B -w -r1.41 dyn_syscalls.S
--- i386/dyn_syscalls.S	27 Dec 2008 19:53:16 -0000	1.41
+++ i386/dyn_syscalls.S	6 Dec 2010 10:58:17 -0000
@@ -207,6 +207,8 @@ __unified_syscall:
 #include "../syscalls.s/rt_sigqueueinfo.S"
 #include "../syscalls.s/rt_sigsuspend.S"
 #include "../syscalls.s/rt_sigtimedwait.S"
+#include "../syscalls.s/sched_getaffinity.S"
+#include "../syscalls.s/sched_setaffinity.S"
 #include "../syscalls.s/sched_get_priority_max.S"
 #include "../syscalls.s/sched_get_priority_min.S"
 #include "../syscalls.s/sched_getparam.S"
Index: include/sched.h
===================================================================
RCS file: /cvs/dietlibc/include/sched.h,v
retrieving revision 1.10
diff -u -p -b -B -w -r1.10 sched.h
--- include/sched.h	19 Feb 2008 00:28:13 -0000	1.10
+++ include/sched.h	6 Dec 2010 10:58:18 -0000
@@ -69,6 +69,52 @@ int sched_rr_get_interval(pid_t pid, str
 int clone(void*(*fn)(void*),void*stack,int flags,void*arg);

 int unshare(int flags);
+
+/*
+ * Linux CPU affinity.
+ * For simplicity it supports up to 32 CPUs for 32 bits systems and up to
+ * 64 for 64 bits systems. Add the other CPU_SET(3) macros when needed.
+ */
+
+typedef	unsigned long cpu_set_t;
+
+static inline void CPU_ZERO(cpu_set_t *set) {*set = 0;}
+static inline void CPU_SET(int cpu, cpu_set_t *set) {*set |= (1UL << cpu);}
+static inline void CPU_CLR(int cpu, cpu_set_t *set) {*set &= ~(1UL << cpu);}
+static inline int CPU_ISSET(int cpu, cpu_set_t *set) {return *set &= (1UL <<
cpu);}
+
+static inline int CPU_COUNT(cpu_set_t *set)
+{
+	int c;
+	unsigned long v;
+
+	/* Peter Wegner/Derrick Lehmer/Brian Kernighan's method */
+	for (c = 0, v = *set; v; c++)
+		v &= v - 1; // clear the least significant bit set
+	return c;
+}
+
+static inline void CPU_AND(cpu_set_t *dest, cpu_set_t *s1, cpu_set_t *s2){
+	*dest = *s1 & *s2;
+}
+
+static inline void CPU_OR(cpu_set_t *dest, cpu_set_t *s1, cpu_set_t *s2){
+	*dest = *s1 | *s2;
+}
+
+static inline void CPU_XOR(cpu_set_t *dest, cpu_set_t *s1, cpu_set_t *s2){
+	*dest = *s1 ^ *s2;
+}
+
+static inline int  CPU_EQUAL(cpu_set_t *s1, cpu_set_t *s2){
+	return *s1 == *s2;
+}
+
+int sched_setaffinity(pid_t pid, size_t size, cpu_set_t *mask);
+int sched_getaffinity(pid_t pid, size_t size, cpu_set_t *mask);
+#define pthread_setaffinity_np sched_setaffinity
+#define pthread_getaffinity_np sched_getaffinity
+
 #endif

 __END_DECLS
Index: lib/__sched_getaffinity.c
===================================================================
RCS file: lib/__sched_getaffinity.c
diff -N lib/__sched_getaffinity.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ lib/__sched_getaffinity.c	6 Dec 2010 10:58:18 -0000
@@ -0,0 +1,15 @@
+#define _GNU_SOURCE
+#include <sched.h>
+
+extern int __syscall_sched_getaffinity(pid_t, size_t, cpu_set_t*);
+
+int sched_getaffinity(pid_t pid, size_t size, cpu_set_t *mask)
+{
+	int ret;
+
+	*mask = 0;
+	ret = __syscall_sched_getaffinity(pid, size, mask);
+	if (ret > 0)
+		return 0;
+	return ret;
+}
Index: syscalls.s/sched_getaffinity.S
===================================================================
RCS file: syscalls.s/sched_getaffinity.S
diff -N syscalls.s/sched_getaffinity.S
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ syscalls.s/sched_getaffinity.S	6 Dec 2010 10:58:18 -0000
@@ -0,0 +1,4 @@
+#include "syscalls.h"
+
+syscall(sched_getaffinity,__syscall_sched_getaffinity)
+
Index: syscalls.s/sched_setaffinity.S
===================================================================
RCS file: syscalls.s/sched_setaffinity.S
diff -N syscalls.s/sched_setaffinity.S
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ syscalls.s/sched_setaffinity.S	6 Dec 2010 10:58:18 -0000
@@ -0,0 +1,4 @@
+#include "syscalls.h"
+
+syscall(sched_setaffinity,sched_setaffinity)
+
Index: x86_64/dyn_syscalls.S
===================================================================
RCS file: /cvs/dietlibc/x86_64/dyn_syscalls.S,v
retrieving revision 1.6
diff -u -p -b -B -w -r1.6 dyn_syscalls.S
--- x86_64/dyn_syscalls.S	27 Dec 2008 19:53:16 -0000	1.6
+++ x86_64/dyn_syscalls.S	6 Dec 2010 10:58:19 -0000
@@ -158,6 +158,8 @@ _unified_syscall:
 #include "../syscalls.s/rt_sigqueueinfo.S"
 #include "../syscalls.s/rt_sigsuspend.S"
 #include "../syscalls.s/rt_sigtimedwait.S"
+#include "../syscalls.s/sched_getaffinity.S"
+#include "../syscalls.s/sched_setaffinity.S"
 #include "../syscalls.s/sched_get_priority_max.S"
 #include "../syscalls.s/sched_get_priority_min.S"
 #include "../syscalls.s/sched_getparam.S"