about summary refs log tree commit diff
path: root/sysdeps/unix/sysv
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/sysv
parent15bac72bac03faeb3b725b1d208c62160f0c3ad7 (diff)
downloadglibc-c08fb0d7bba4015078406b28d3906ccc5fda9d5a.tar.gz
glibc-c08fb0d7bba4015078406b28d3906ccc5fda9d5a.tar.xz
glibc-c08fb0d7bba4015078406b28d3906ccc5fda9d5a.zip
Add support for prlimit and prlimit64 on Linux.
Diffstat (limited to 'sysdeps/unix/sysv')
-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