summaryrefslogtreecommitdiff
path: root/sysdeps/unix
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2010-08-11 11:18:52 -0700
committerUlrich Drepper <drepper@redhat.com>2010-08-11 11:18:52 -0700
commitc08fb0d7bba4015078406b28d3906ccc5fda9d5a (patch)
tree6952d7d0b4ddf0f57b1358918a80e8373c11c437 /sysdeps/unix
parent15bac72bac03faeb3b725b1d208c62160f0c3ad7 (diff)
downloadglibc-c08fb0d7bba4015078406b28d3906ccc5fda9d5a.tar.gz
Add support for prlimit and prlimit64 on Linux.
Diffstat (limited to 'sysdeps/unix')
-rw-r--r--sysdeps/unix/sysv/linux/Makefile2
-rw-r--r--sysdeps/unix/sysv/linux/Versions3
-rw-r--r--sysdeps/unix/sysv/linux/bits/resource.h30
-rw-r--r--sysdeps/unix/sysv/linux/i386/syscalls.list2
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/powerpc32/syscalls.list2
-rw-r--r--sysdeps/unix/sysv/linux/prlimit.c92
-rw-r--r--sysdeps/unix/sysv/linux/s390/s390-32/syscalls.list2
-rw-r--r--sysdeps/unix/sysv/linux/sh/syscalls.list2
-rw-r--r--sysdeps/unix/sysv/linux/sparc/sparc32/syscalls.list2
-rw-r--r--sysdeps/unix/sysv/linux/wordsize-64/syscalls.list1
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