diff options
author | Ulrich Drepper <drepper@redhat.com> | 2010-08-11 11:18:52 -0700 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2010-08-11 11:18:52 -0700 |
commit | c08fb0d7bba4015078406b28d3906ccc5fda9d5a (patch) | |
tree | 6952d7d0b4ddf0f57b1358918a80e8373c11c437 /sysdeps/unix | |
parent | 15bac72bac03faeb3b725b1d208c62160f0c3ad7 (diff) | |
download | glibc-c08fb0d7bba4015078406b28d3906ccc5fda9d5a.tar.gz |
Add support for prlimit and prlimit64 on Linux.
Diffstat (limited to 'sysdeps/unix')
-rw-r--r-- | sysdeps/unix/sysv/linux/Makefile | 2 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/Versions | 3 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/bits/resource.h | 30 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/i386/syscalls.list | 2 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/powerpc/powerpc32/syscalls.list | 2 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/prlimit.c | 92 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/s390/s390-32/syscalls.list | 2 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/sh/syscalls.list | 2 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/sparc/sparc32/syscalls.list | 2 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/wordsize-64/syscalls.list | 1 |
10 files changed, 136 insertions, 2 deletions
diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile index 9c53b2d228..5ab6a4f1e9 100644 --- a/sysdeps/unix/sysv/linux/Makefile +++ b/sysdeps/unix/sysv/linux/Makefile @@ -18,7 +18,7 @@ endif ifeq ($(subdir),misc) sysdep_routines += sysctl clone llseek umount umount2 readahead \ setfsuid setfsgid makedev epoll_pwait signalfd \ - eventfd eventfd_read eventfd_write + eventfd eventfd_read eventfd_write prlimit CFLAGS-gethostid.c = -fexceptions diff --git a/sysdeps/unix/sysv/linux/Versions b/sysdeps/unix/sysv/linux/Versions index f09ef6d983..c662765751 100644 --- a/sysdeps/unix/sysv/linux/Versions +++ b/sysdeps/unix/sysv/linux/Versions @@ -149,6 +149,9 @@ libc { recvmmsg; } + GLIBC_2.13 { + prlimit; prlimit64; + } GLIBC_PRIVATE { # functions used in other libraries __syscall_rt_sigqueueinfo; diff --git a/sysdeps/unix/sysv/linux/bits/resource.h b/sysdeps/unix/sysv/linux/bits/resource.h index cb3acf1622..ca2c9f0160 100644 --- a/sysdeps/unix/sysv/linux/bits/resource.h +++ b/sysdeps/unix/sysv/linux/bits/resource.h @@ -1,5 +1,5 @@ /* Bit values & structures for resource limits. Linux version. - Copyright (C) 1994, 1996, 1997, 1998, 1999, 2000, 2004, 2005, 2008, 2009 + Copyright (C) 1994, 1996-2000, 2004, 2005, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -232,3 +232,31 @@ enum __priority_which PRIO_USER = 2 /* WHO is a user ID. */ #define PRIO_USER PRIO_USER }; + + +__BEGIN_DECLS + +#ifdef __USE_GNU +/* Modify and return resource limits of a process atomically. */ +# ifndef __USE_FILE_OFFSET64 +extern int prlimit (__pid_t __pid, enum __rlimit_resource __resource, + __const struct rlimit *__new_limit, + struct rlimit *__old_limit) __THROW; +# else +# ifdef __REDIRECT_NTH +extern int __REDIRECT_NTH (prlimit, (__pid_t __pid, + enum __rlimit_resource __resource, + __const struct rlimit *__new_limit, + struct rlimit *__old_limit), prlimit64); +# else +# define prlimit prlimit64 +# endif +# endif +# ifdef __USE_LARGEFILE64 +extern int prlimit64 (__pid_t __pid, enum __rlimit_resource __resource, + __const struct rlimit64 *__new_limit, + struct rlimit64 *__old_limit) __THROW; +# endif +#endif + +__END_DECLS diff --git a/sysdeps/unix/sysv/linux/i386/syscalls.list b/sysdeps/unix/sysv/linux/i386/syscalls.list index 3ff3a73aab..597e5989c4 100644 --- a/sysdeps/unix/sysv/linux/i386/syscalls.list +++ b/sysdeps/unix/sysv/linux/i386/syscalls.list @@ -6,3 +6,5 @@ vm86 - vm86 i:ip __vm86 vm86@@GLIBC_2.3.4 oldgetrlimit EXTRA getrlimit i:ip __old_getrlimit getrlimit@GLIBC_2.0 oldsetrlimit EXTRA setrlimit i:ip __old_setrlimit setrlimit@GLIBC_2.0 waitpid - waitpid Ci:ipi __waitpid waitpid __libc_waitpid + +prlimit64 EXTRA prlimit64 i:iipp prlimit64 diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/syscalls.list b/sysdeps/unix/sysv/linux/powerpc/powerpc32/syscalls.list index 1233be671a..30122853a1 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/syscalls.list +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/syscalls.list @@ -6,3 +6,5 @@ oldsetrlimit EXTRA setrlimit i:ip __old_setrlimit setrlimit@GLIBC_2.0 # Due to 64bit alignment there is a dummy second parameter readahead - readahead i:iiiii __readahead readahead + +prlimit64 EXTRA prlimit64 i:iipp prlimit64 diff --git a/sysdeps/unix/sysv/linux/prlimit.c b/sysdeps/unix/sysv/linux/prlimit.c new file mode 100644 index 0000000000..6d61e9a2a4 --- /dev/null +++ b/sysdeps/unix/sysv/linux/prlimit.c @@ -0,0 +1,92 @@ +/* Copyright (C) 2010 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 <errno.h> +#include <sys/resource.h> +#include <sys/syscall.h> + + +#ifdef __NR_prlimit64 +int +prlimit (__pid_t pid, enum __rlimit_resource resource, + __const struct rlimit *new_limit, struct rlimit *old_limit) +{ + struct rlimit64 new_rlimit64_mem; + struct rlimit64 *new_rlimit64 = NULL; + struct rlimit64 old_rlimit64_mem; + struct rlimit64 *old_rlimit64 = (old_rlimiit != NULL + ? &old_rlimit64_mem : NULL); + + if (new_rlimit != NULL) + { + if (new_rlimit->rlim_cur == RLIM_INFINITY) + new_rlimit64_mem.rlim_cur = RLIM64_INFINITY; + else + new_rlimit64_mem.rlim_cur = new_rlimit->rlim_cur; + if (new_rlimit->rlim_max == RLIM_INFINITY) + new_rlimit64_mem.rlim_max = = RLIM64_INFINITY; + else + new_rlimit64_mem.rlim_max = new_rlimit->rlim_max; + new_rlimit64 = &new_rlimit64_mem; + } + + int res = INLINE_SYSCALL (prlimit64, 4, pid, resource, new_rlimit64, + old_rlimit64); + + if (res == 0 && old_limit != NULL) + { + /* The prlimit64 syscall is ill-designed for 32-bit machines. + We have to provide a 32-bit variant since otherwise the LFS + system would not work. But what shall we do if the syscall + succeeds but the old values do not fit into a rlimit + structure? We cannot return an error because the operation + itself worked. Best is perhaps to return RLIM_INFINITY. */ + old_rlimit->rlim_cur = old_rlimit64_mem.rlim_cur; + if (old_rlimit->rlim_cur != old_rlimit64_mem.rlim_cur) + { + if (new_limit == NULL) + { + __set_errno (EOVERFLOW); + return -1; + } + old_rlimit->rlim_cur = RLIM_INFINITY; + } + old_rlimit->rlim_max = old_rlimit64_mem.rlim_max; + if (old_rlimit->rlim_max != old_rlimit64_mem.rlim_max) + { + if (new_limit == NULL) + { + __set_errno (EOVERFLOW); + return -1; + } + old_rlimit->rlim_max = RLIM_INFINITY; + } + } + + return res; +} +#else +int +prlimit (__pid_t pid, enum __rlimit_resource resource, + __const struct rlimit *new_limit, struct rlimit *old_limit) +{ + __set_errno (ENOSYS); + return -1; +} +stub_warning (prlimit) +#endif diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/syscalls.list b/sysdeps/unix/sysv/linux/s390/s390-32/syscalls.list index 0e76857308..d3a05d2d2e 100644 --- a/sysdeps/unix/sysv/linux/s390/s390-32/syscalls.list +++ b/sysdeps/unix/sysv/linux/s390/s390-32/syscalls.list @@ -3,3 +3,5 @@ oldgetrlimit EXTRA getrlimit i:ip __old_getrlimit getrlimit@GLIBC_2.0 oldsetrlimit EXTRA setrlimit i:ip __old_setrlimit setrlimit@GLIBC_2.0 vfork - vfork 0 __vfork vfork + +prlimit64 EXTRA prlimit64 i:iipp prlimit64 diff --git a/sysdeps/unix/sysv/linux/sh/syscalls.list b/sysdeps/unix/sysv/linux/sh/syscalls.list index a6665936e8..be9ffed224 100644 --- a/sysdeps/unix/sysv/linux/sh/syscalls.list +++ b/sysdeps/unix/sysv/linux/sh/syscalls.list @@ -1,3 +1,5 @@ # File name Caller Syscall name # args Strong name Weak names waitpid - waitpid Ci:ipi __waitpid waitpid __libc_waitpid + +prlimit64 EXTRA prlimit64 i:iipp prlimit64 diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/syscalls.list b/sysdeps/unix/sysv/linux/sparc/sparc32/syscalls.list index 2bfe376a3b..8b1d6829bf 100644 --- a/sysdeps/unix/sysv/linux/sparc/sparc32/syscalls.list +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/syscalls.list @@ -4,3 +4,5 @@ setrlimit - setrlimit 2 __setrlimit setrlimit getrlimit - getrlimit 2 __getrlimit getrlimit getresuid - getresuid32 3 getresuid getresgid - getresgid32 3 getresgid + +prlimit64 EXTRA prlimit64 i:iipp prlimit64 diff --git a/sysdeps/unix/sysv/linux/wordsize-64/syscalls.list b/sysdeps/unix/sysv/linux/wordsize-64/syscalls.list index 60915507b5..b2e21638d0 100644 --- a/sysdeps/unix/sysv/linux/wordsize-64/syscalls.list +++ b/sysdeps/unix/sysv/linux/wordsize-64/syscalls.list @@ -17,3 +17,4 @@ sendfile - sendfile i:iipi sendfile sendfile64 sync_file_range - sync_file_range i:iiii sync_file_range creat - creat Ci:si __libc_creat creat creat64 open - open Ci:siv __libc_open __open open __open64 open64 +prlimit EXTRA prlimit64 i:iipp prlimit prlimit64 |