From 2becc16ecbef71c496644d9dc6cbd7383d7cdca3 Mon Sep 17 00:00:00 2001 From: Henning Heinold Date: Sat, 4 Jun 2011 21:21:41 +0200 Subject: [PATCH 1/2] libc: updates the linux scheduler functions, most stuff was taken from the eglibc Signed-off-by: Henning Heinold --- include/sched.h | 52 ++++++++++++---- libc/sysdeps/linux/common/Makefile.in | 4 +- libc/sysdeps/linux/common/bits/sched.h | 96 +++++++++++++++++++++++----- libc/sysdeps/linux/common/sched_cpualloc.c | 27 ++++++++ libc/sysdeps/linux/common/sched_cpucount.c | 60 +++++++++++++++++ libc/sysdeps/linux/common/sched_cpufree.c | 27 ++++++++ libc/sysdeps/linux/common/sched_getcpu.c | 37 +++++++++++ libc/sysdeps/linux/common/unshare.c | 12 ++++ 8 files changed, 286 insertions(+), 29 deletions(-) create mode 100644 libc/sysdeps/linux/common/sched_cpualloc.c create mode 100644 libc/sysdeps/linux/common/sched_cpucount.c create mode 100644 libc/sysdeps/linux/common/sched_cpufree.c create mode 100644 libc/sysdeps/linux/common/sched_getcpu.c create mode 100644 libc/sysdeps/linux/common/unshare.c diff --git a/include/sched.h b/include/sched.h index 0d110c3..e265b84 100644 --- a/include/sched.h +++ b/include/sched.h @@ -1,5 +1,5 @@ /* Definitions for POSIX 1003.1b-1993 (aka POSIX.4) scheduling interface. - Copyright (C) 1996,1997,1999,2001-2003,2004 Free Software Foundation, Inc. + Copyright (C) 1996,1997,1999,2001-2004,2007 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -25,6 +25,9 @@ /* Get type definitions. */ #include +#define __need_size_t +#include + #define __need_timespec #include @@ -65,11 +68,42 @@ extern int sched_rr_get_interval (__pid_t __pid, struct timespec *__t) __THROW; #if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ /* Access macros for `cpu_set'. */ -#define CPU_SETSIZE __CPU_SETSIZE -#define CPU_SET(cpu, cpusetp) __CPU_SET (cpu, cpusetp) -#define CPU_CLR(cpu, cpusetp) __CPU_CLR (cpu, cpusetp) -#define CPU_ISSET(cpu, cpusetp) __CPU_ISSET (cpu, cpusetp) -#define CPU_ZERO(cpusetp) __CPU_ZERO (cpusetp) +# define CPU_SETSIZE __CPU_SETSIZE +# define CPU_SET(cpu, cpusetp) __CPU_SET_S (cpu, sizeof (cpu_set_t), cpusetp) +# define CPU_CLR(cpu, cpusetp) __CPU_CLR_S (cpu, sizeof (cpu_set_t), cpusetp) +# define CPU_ISSET(cpu, cpusetp) __CPU_ISSET_S (cpu, sizeof (cpu_set_t), \ + cpusetp) +# define CPU_ZERO(cpusetp) __CPU_ZERO_S (sizeof (cpu_set_t), cpusetp) +# define CPU_COUNT(cpusetp) __CPU_COUNT_S (sizeof (cpu_set_t), cpusetp) + +# define CPU_SET_S(cpu, setsize, cpusetp) __CPU_SET_S (cpu, setsize, cpusetp) +# define CPU_CLR_S(cpu, setsize, cpusetp) __CPU_CLR_S (cpu, setsize, cpusetp) +# define CPU_ISSET_S(cpu, setsize, cpusetp) __CPU_ISSET_S (cpu, setsize, \ + cpusetp) +# define CPU_ZERO_S(setsize, cpusetp) __CPU_ZERO_S (setsize, cpusetp) +# define CPU_COUNT_S(setsize, cpusetp) __CPU_COUNT_S (setsize, cpusetp) + +# define CPU_EQUAL(cpusetp1, cpusetp2) \ + __CPU_EQUAL_S (sizeof (cpu_set_t), cpusetp1, cpusetp2) +# define CPU_EQUAL_S(setsize, cpusetp1, cpusetp2) \ + __CPU_EQUAL_S (setsize, cpusetp1, cpusetp2) + +# define CPU_AND(destset, srcset1, srcset2) \ + __CPU_OP_S (sizeof (cpu_set_t), destset, srcset1, srcset2, &) +# define CPU_OR(destset, srcset1, srcset2) \ + __CPU_OP_S (sizeof (cpu_set_t), destset, srcset1, srcset2, |) +# define CPU_XOR(destset, srcset1, srcset2) \ + __CPU_OP_S (sizeof (cpu_set_t), destset, srcset1, srcset2, ^) +# define CPU_AND_S(setsize, destset, srcset1, srcset2) \ + __CPU_OP_S (setsize, destset, srcset1, srcset2, &) +# define CPU_OR_S(setsize, destset, srcset1, srcset2) \ + __CPU_OP_S (setsize, destset, srcset1, srcset2, |) +# define CPU_XOR_S(setsize, destset, srcset1, srcset2) \ + __CPU_OP_S (setsize, destset, srcset1, srcset2, ^) + +# define CPU_ALLOC_SIZE(count) __CPU_ALLOC_SIZE (count) +# define CPU_ALLOC(count) __CPU_ALLOC (count) +# define CPU_FREE(cpuset) __CPU_FREE (cpuset) /* Set the CPU affinity for a task */ @@ -79,12 +113,6 @@ extern int sched_setaffinity (__pid_t __pid, size_t __cpusetsize, /* Get the CPU affinity for a task */ extern int sched_getaffinity (__pid_t __pid, size_t __cpusetsize, cpu_set_t *__cpuset) __THROW; - -extern int __clone (int (*__fn) (void *__arg), void *__child_stack, - int __flags, void *__arg, ...); -extern int __clone2 (int (*__fn) (void *__arg), void *__child_stack_base, - size_t __child_stack_size, int __flags, void *__arg, ...); - #endif __END_DECLS diff --git a/libc/sysdeps/linux/common/Makefile.in b/libc/sysdeps/linux/common/Makefile.in index 8f936ff..cb8c153 100644 --- a/libc/sysdeps/linux/common/Makefile.in +++ b/libc/sysdeps/linux/common/Makefile.in @@ -22,9 +22,11 @@ CSRC-$(UCLIBC_LINUX_SPECIFIC) += capget.c capset.c inotify.c ioperm.c iopl.c \ modify_ldt.c pipe2.c personality.c ppoll.c prctl.c \ readahead.c reboot.c \ remap_file_pages.c sched_getaffinity.c sched_setaffinity.c \ + sched_cpualloc.c sched_cpucount.c sched_cpufree.c \ sendfile64.c sendfile.c setfsgid.c setfsuid.c setresuid.c \ splice.c vmsplice.c tee.c signalfd.c swapoff.c swapon.c \ - sync_file_range.c sysctl.c sysinfo.c timerfd.c uselib.c vhangup.c + sync_file_range.c sysctl.c sysinfo.c timerfd.c unshare.c \ + uselib.c vhangup.c # NPTL needs these internally: madvise.c CSRC-$(findstring y,$(UCLIBC_LINUX_SPECIFIC)$(UCLIBC_HAS_THREADS_NATIVE)) += madvise.c ifeq ($(UCLIBC_HAS_THREADS_NATIVE),y) diff --git a/libc/sysdeps/linux/common/bits/sched.h b/libc/sysdeps/linux/common/bits/sched.h index b48a0c8..fea66a8 100644 --- a/libc/sysdeps/linux/common/bits/sched.h +++ b/libc/sysdeps/linux/common/bits/sched.h @@ -1,6 +1,7 @@ /* Definitions of constants and data structure for POSIX 1003.1b-1993 scheduling interface. - Copyright (C) 1996-1999,2001-2003,2005,2006 Free Software Foundation, Inc. + Copyright (C) 1996-1999,2001-2003,2005,2006,2007,2008 + Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -58,7 +59,13 @@ force CLONE_PTRACE on this clone. */ # define CLONE_CHILD_SETTID 0x01000000 /* Store TID in userlevel buffer in the child. */ -# define CLONE_STOPPED 0x02000000 /* Start in stopped state. */ +# define CLONE_STOPPED 0x02000000 /* Start in stopped state. */ +# define CLONE_NEWUTS 0x04000000 /* New utsname group. */ +# define CLONE_NEWIPC 0x08000000 /* New ipcs. */ +# define CLONE_NEWUSER 0x10000000 /* New user namespace. */ +# define CLONE_NEWPID 0x20000000 /* New pid namespace. */ +# define CLONE_NEWNET 0x40000000 /* New network namespace. */ +# define CLONE_IO 0x80000000 /* Clone I/O context. */ #endif /* The official definition. */ @@ -74,10 +81,11 @@ __BEGIN_DECLS extern int clone (int (*__fn) (void *__arg), void *__child_stack, int __flags, void *__arg, ...) __THROW; -#if 0 /* Unshare the specified resources. */ extern int unshare (int __flags) __THROW; -#endif + +/* Get index of currently used CPU. */ +extern int sched_getcpu (void) __THROW; #endif __END_DECLS @@ -102,7 +110,7 @@ struct __sched_param # define __CPU_SETSIZE 1024 # define __NCPUBITS (8 * sizeof (__cpu_mask)) -/* Type for array elements in 'cpu_set'. */ +/* Type for array elements in 'cpu_set_t'. */ typedef unsigned long int __cpu_mask; /* Basic access functions. */ @@ -116,17 +124,73 @@ typedef struct } cpu_set_t; /* Access functions for CPU masks. */ -# define __CPU_ZERO(cpusetp) \ +# define __CPU_ZERO_S(setsize, cpusetp) \ do { \ - unsigned int __i; \ - cpu_set_t *__arr = (cpusetp); \ - for (__i = 0; __i < sizeof (cpu_set_t) / sizeof (__cpu_mask); ++__i) \ - __arr->__bits[__i] = 0; \ + size_t __i; \ + size_t __imax = (setsize) / sizeof (__cpu_mask); \ + __cpu_mask *__bits = (cpusetp)->__bits; \ + for (__i = 0; __i < __imax; ++__i) \ + __bits[__i] = 0; \ } while (0) -# define __CPU_SET(cpu, cpusetp) \ - ((cpusetp)->__bits[__CPUELT (cpu)] |= __CPUMASK (cpu)) -# define __CPU_CLR(cpu, cpusetp) \ - ((cpusetp)->__bits[__CPUELT (cpu)] &= ~__CPUMASK (cpu)) -# define __CPU_ISSET(cpu, cpusetp) \ - (((cpusetp)->__bits[__CPUELT (cpu)] & __CPUMASK (cpu)) != 0) +# define __CPU_SET_S(cpu, setsize, cpusetp) \ + (__extension__ \ + ({ size_t __cpu = (cpu); \ + __cpu < 8 * (setsize) \ + ? (((__cpu_mask *) ((cpusetp)->__bits))[__CPUELT (__cpu)] \ + |= __CPUMASK (__cpu)) \ + : 0; })) +# define __CPU_CLR_S(cpu, setsize, cpusetp) \ + (__extension__ \ + ({ size_t __cpu = (cpu); \ + __cpu < 8 * (setsize) \ + ? (((__cpu_mask *) ((cpusetp)->__bits))[__CPUELT (__cpu)] \ + &= ~__CPUMASK (__cpu)) \ + : 0; })) +# define __CPU_ISSET_S(cpu, setsize, cpusetp) \ + (__extension__ \ + ({ size_t __cpu = (cpu); \ + __cpu < 8 * (setsize) \ + ? ((((__cpu_mask *) ((cpusetp)->__bits))[__CPUELT (__cpu)] \ + & __CPUMASK (__cpu))) != 0 \ + : 0; })) + +# define __CPU_COUNT_S(setsize, cpusetp) \ + __sched_cpucount (setsize, cpusetp) + +# define __CPU_EQUAL_S(setsize, cpusetp1, cpusetp2) \ + (__extension__ \ + ({ __cpu_mask *__arr1 = (cpusetp1)->__bits; \ + __cpu_mask *__arr2 = (cpusetp2)->__bits; \ + size_t __imax = (setsize) / sizeof (__cpu_mask); \ + size_t __i; \ + for (__i = 0; __i < __imax; ++__i) \ + if (__arr1[__i] != __arr2[__i]) \ + break; \ + __i == __imax; })) + +# define __CPU_OP_S(setsize, destset, srcset1, srcset2, op) \ + (__extension__ \ + ({ cpu_set_t *__dest = (destset); \ + __cpu_mask *__arr1 = (srcset1)->__bits; \ + __cpu_mask *__arr2 = (srcset2)->__bits; \ + size_t __imax = (setsize) / sizeof (__cpu_mask); \ + size_t __i; \ + for (__i = 0; __i < __imax; ++__i) \ + ((__cpu_mask *) __dest->__bits)[__i] = __arr1[__i] op __arr2[__i]; \ + __dest; })) + +# define __CPU_ALLOC_SIZE(count) \ + ((((count) + __NCPUBITS - 1) / __NCPUBITS) * sizeof (__cpu_mask)) +# define __CPU_ALLOC(count) __sched_cpualloc (count) +# define __CPU_FREE(cpuset) __sched_cpufree (cpuset) + +__BEGIN_DECLS + +extern int __sched_cpucount (size_t __setsize, const cpu_set_t *__setp) + __THROW; +extern cpu_set_t *__sched_cpualloc (size_t __count) __THROW __wur; +extern void __sched_cpufree (cpu_set_t *__set) __THROW; + +__END_DECLS + #endif diff --git a/libc/sysdeps/linux/common/sched_cpualloc.c b/libc/sysdeps/linux/common/sched_cpualloc.c new file mode 100644 index 0000000..2642a80 --- /dev/null +++ b/libc/sysdeps/linux/common/sched_cpualloc.c @@ -0,0 +1,27 @@ +/* Copyright (C) 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +cpu_set_t * +__sched_cpualloc (size_t count) +{ + return malloc (CPU_ALLOC_SIZE (count)); +} diff --git a/libc/sysdeps/linux/common/sched_cpucount.c b/libc/sysdeps/linux/common/sched_cpucount.c new file mode 100644 index 0000000..331c0b8 --- /dev/null +++ b/libc/sysdeps/linux/common/sched_cpucount.c @@ -0,0 +1,60 @@ +/* Copyright (C) 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +int +__sched_cpucount (size_t setsize, const cpu_set_t *setp) +{ + int s = 0; + const __cpu_mask *p = setp->__bits; + const __cpu_mask *end = &setp->__bits[setsize / sizeof (__cpu_mask)]; + + while (p < end) + { + __cpu_mask l = *p++; + +#ifdef POPCNT + s += POPCNT (l); +#else + if (l == 0) + continue; + +# if LONG_BIT > 32 + l = (l & 0x5555555555555555ul) + ((l >> 1) & 0x5555555555555555ul); + l = (l & 0x3333333333333333ul) + ((l >> 2) & 0x3333333333333333ul); + l = (l & 0x0f0f0f0f0f0f0f0ful) + ((l >> 4) & 0x0f0f0f0f0f0f0f0ful); + l = (l & 0x00ff00ff00ff00fful) + ((l >> 8) & 0x00ff00ff00ff00fful); + l = (l & 0x0000ffff0000fffful) + ((l >> 16) & 0x0000ffff0000fffful); + l = (l & 0x00000000fffffffful) + ((l >> 32) & 0x00000000fffffffful); +# else + l = (l & 0x55555555ul) + ((l >> 1) & 0x55555555ul); + l = (l & 0x33333333ul) + ((l >> 2) & 0x33333333ul); + l = (l & 0x0f0f0f0ful) + ((l >> 4) & 0x0f0f0f0ful); + l = (l & 0x00ff00fful) + ((l >> 8) & 0x00ff00fful); + l = (l & 0x0000fffful) + ((l >> 16) & 0x0000fffful); +# endif + + s += l; +#endif + } + + return s; +} diff --git a/libc/sysdeps/linux/common/sched_cpufree.c b/libc/sysdeps/linux/common/sched_cpufree.c new file mode 100644 index 0000000..dd4c613 --- /dev/null +++ b/libc/sysdeps/linux/common/sched_cpufree.c @@ -0,0 +1,27 @@ +/* Copyright (C) 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +void +__sched_cpufree (cpu_set_t *set) +{ + free (set); +} diff --git a/libc/sysdeps/linux/common/sched_getcpu.c b/libc/sysdeps/linux/common/sched_getcpu.c new file mode 100644 index 0000000..b193d65 --- /dev/null +++ b/libc/sysdeps/linux/common/sched_getcpu.c @@ -0,0 +1,37 @@ +/* Copyright (C) 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + + +int +sched_getcpu (void) +{ +#ifdef __NR_getcpu + unsigned int cpu; + int r = INLINE_SYSCALL (getcpu, 3, &cpu, NULL, NULL); + + return r == -1 ? r : cpu; +#else + __set_errno (ENOSYS); + return -1; +#endif +} diff --git a/libc/sysdeps/linux/common/unshare.c b/libc/sysdeps/linux/common/unshare.c new file mode 100644 index 0000000..485bf88 --- /dev/null +++ b/libc/sysdeps/linux/common/unshare.c @@ -0,0 +1,12 @@ +/* vi: set sw=4 ts=4: */ +/* + * unshare() for uClibc + * + * Copyright (C) 2011 Henning Heinold + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +_syscall1(int, unshare, int, flags) -- 1.7.5.3