Merge "Fix <sys/resource.h>."
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index d0fa528..6e10daa 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -62,12 +62,21 @@
int tgkill(pid_t tgid, pid_t tid, int sig) all
int __ptrace:ptrace(int request, int pid, void* addr, void* data) all
int __set_thread_area:set_thread_area(void* user_desc) mips,x86
-int __getpriority:getpriority(int, int) all
-int setpriority(int, int, int) all
-int setrlimit(int resource, const struct rlimit* rlp) all
-int getrlimit:ugetrlimit(int resource, struct rlimit* rlp) arm,x86
-int getrlimit:getrlimit(int resource, struct rlimit* rlp) aarch64,mips,x86_64
-int getrusage(int who, struct rusage* r_usage) all
+
+# <sys/resource.h>
+int getrusage(int, struct rusage*) all
+int __getpriority:getpriority(int, int) all
+int setpriority(int, int, int) all
+# On LP64, rlimit and rlimit64 are the same.
+# On 32-bit systems we use prlimit64 to implement the rlimit64 functions.
+int getrlimit:ugetrlimit(int, struct rlimit*) arm,x86
+int getrlimit(int, struct rlimit*) mips
+int getrlimit|getrlimit64(int, struct rlimit*) aarch64,x86_64
+int setrlimit(int, const struct rlimit*) arm,mips,x86
+int setrlimit|setrlimit64(int, const struct rlimit*) aarch64,x86_64
+int prlimit64|prlimit(pid_t, int, struct rlimit64*, const struct rlimit64*) aarch64,x86_64
+int prlimit64(pid_t, int, struct rlimit64*, const struct rlimit64*) arm,mips,x86
+
int setgroups:setgroups32(int, const gid_t*) arm,x86
int setgroups:setgroups(int, const gid_t*) aarch64,mips,x86_64
int setpgid(pid_t, pid_t) all
diff --git a/libc/arch-aarch64/syscalls.mk b/libc/arch-aarch64/syscalls.mk
index 3e5d191..653ef70 100644
--- a/libc/arch-aarch64/syscalls.mk
+++ b/libc/arch-aarch64/syscalls.mk
@@ -123,6 +123,7 @@
syscall_src += arch-aarch64/syscalls/pipe2.S
syscall_src += arch-aarch64/syscalls/prctl.S
syscall_src += arch-aarch64/syscalls/pread64.S
+syscall_src += arch-aarch64/syscalls/prlimit64.S
syscall_src += arch-aarch64/syscalls/pwrite64.S
syscall_src += arch-aarch64/syscalls/read.S
syscall_src += arch-aarch64/syscalls/readahead.S
diff --git a/libc/arch-aarch64/syscalls/getrlimit.S b/libc/arch-aarch64/syscalls/getrlimit.S
index 8b6548f..21b471e 100644
--- a/libc/arch-aarch64/syscalls/getrlimit.S
+++ b/libc/arch-aarch64/syscalls/getrlimit.S
@@ -19,3 +19,6 @@
ret
END(getrlimit)
+
+ .globl _C_LABEL(getrlimit64)
+ .equ _C_LABEL(getrlimit64), _C_LABEL(getrlimit)
diff --git a/libc/arch-aarch64/syscalls/prlimit64.S b/libc/arch-aarch64/syscalls/prlimit64.S
new file mode 100644
index 0000000..439e355
--- /dev/null
+++ b/libc/arch-aarch64/syscalls/prlimit64.S
@@ -0,0 +1,24 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+ENTRY(prlimit64)
+ stp x29, x30, [sp, #-16]!
+ mov x29, sp
+ str x8, [sp, #-16]!
+
+ mov x8, __NR_prlimit64
+ svc #0
+
+ ldr x8, [sp], #16
+ ldp x29, x30, [sp], #16
+
+ cmn x0, #(MAX_ERRNO + 1)
+ cneg x0, x0, hi
+ b.hi __set_errno
+
+ ret
+END(prlimit64)
+
+ .globl _C_LABEL(prlimit)
+ .equ _C_LABEL(prlimit), _C_LABEL(prlimit64)
diff --git a/libc/arch-aarch64/syscalls/setrlimit.S b/libc/arch-aarch64/syscalls/setrlimit.S
index 3591a84..e723806 100644
--- a/libc/arch-aarch64/syscalls/setrlimit.S
+++ b/libc/arch-aarch64/syscalls/setrlimit.S
@@ -19,3 +19,6 @@
ret
END(setrlimit)
+
+ .globl _C_LABEL(setrlimit64)
+ .equ _C_LABEL(setrlimit64), _C_LABEL(setrlimit)
diff --git a/libc/arch-arm/syscalls.mk b/libc/arch-arm/syscalls.mk
index f1763ef..83e6a97 100644
--- a/libc/arch-arm/syscalls.mk
+++ b/libc/arch-arm/syscalls.mk
@@ -129,6 +129,7 @@
syscall_src += arch-arm/syscalls/pipe2.S
syscall_src += arch-arm/syscalls/prctl.S
syscall_src += arch-arm/syscalls/pread64.S
+syscall_src += arch-arm/syscalls/prlimit64.S
syscall_src += arch-arm/syscalls/pwrite64.S
syscall_src += arch-arm/syscalls/read.S
syscall_src += arch-arm/syscalls/readahead.S
diff --git a/libc/arch-arm/syscalls/prlimit64.S b/libc/arch-arm/syscalls/prlimit64.S
new file mode 100644
index 0000000..8d9c4ff
--- /dev/null
+++ b/libc/arch-arm/syscalls/prlimit64.S
@@ -0,0 +1,14 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+ENTRY(prlimit64)
+ mov ip, r7
+ ldr r7, =__NR_prlimit64
+ swi #0
+ mov r7, ip
+ cmn r0, #(MAX_ERRNO + 1)
+ bxls lr
+ neg r0, r0
+ b __set_errno
+END(prlimit64)
diff --git a/libc/arch-mips/syscalls.mk b/libc/arch-mips/syscalls.mk
index cc7e557..8d87b29 100644
--- a/libc/arch-mips/syscalls.mk
+++ b/libc/arch-mips/syscalls.mk
@@ -129,6 +129,7 @@
syscall_src += arch-mips/syscalls/pipe2.S
syscall_src += arch-mips/syscalls/prctl.S
syscall_src += arch-mips/syscalls/pread64.S
+syscall_src += arch-mips/syscalls/prlimit64.S
syscall_src += arch-mips/syscalls/pwrite64.S
syscall_src += arch-mips/syscalls/read.S
syscall_src += arch-mips/syscalls/readahead.S
diff --git a/libc/arch-mips/syscalls/prlimit64.S b/libc/arch-mips/syscalls/prlimit64.S
new file mode 100644
index 0000000..17e9157
--- /dev/null
+++ b/libc/arch-mips/syscalls/prlimit64.S
@@ -0,0 +1,23 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <asm/unistd.h>
+ .text
+ .globl prlimit64
+ .align 4
+ .ent prlimit64
+
+prlimit64:
+ .set noreorder
+ .cpload $t9
+ li $v0, __NR_prlimit64
+ syscall
+ bnez $a3, 1f
+ move $a0, $v0
+ j $ra
+ nop
+1:
+ la $t9,__set_errno
+ j $t9
+ nop
+ .set reorder
+ .end prlimit64
diff --git a/libc/arch-x86/syscalls.mk b/libc/arch-x86/syscalls.mk
index 0699d09..b7d1e08 100644
--- a/libc/arch-x86/syscalls.mk
+++ b/libc/arch-x86/syscalls.mk
@@ -128,6 +128,7 @@
syscall_src += arch-x86/syscalls/pipe2.S
syscall_src += arch-x86/syscalls/prctl.S
syscall_src += arch-x86/syscalls/pread64.S
+syscall_src += arch-x86/syscalls/prlimit64.S
syscall_src += arch-x86/syscalls/pwrite64.S
syscall_src += arch-x86/syscalls/read.S
syscall_src += arch-x86/syscalls/readahead.S
diff --git a/libc/arch-x86/syscalls/prlimit64.S b/libc/arch-x86/syscalls/prlimit64.S
new file mode 100644
index 0000000..2256425
--- /dev/null
+++ b/libc/arch-x86/syscalls/prlimit64.S
@@ -0,0 +1,34 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+ENTRY(prlimit64)
+ pushl %ebx
+ pushl %ecx
+ pushl %edx
+ pushl %esi
+ .cfi_def_cfa_offset 16
+ .cfi_rel_offset ebx, 0
+ .cfi_rel_offset ecx, 4
+ .cfi_rel_offset edx, 8
+ .cfi_rel_offset esi, 12
+ mov 20(%esp), %ebx
+ mov 24(%esp), %ecx
+ mov 28(%esp), %edx
+ mov 32(%esp), %esi
+ movl $__NR_prlimit64, %eax
+ int $0x80
+ cmpl $-MAX_ERRNO, %eax
+ jb 1f
+ negl %eax
+ pushl %eax
+ call __set_errno
+ addl $4, %esp
+ orl $-1, %eax
+1:
+ popl %esi
+ popl %edx
+ popl %ecx
+ popl %ebx
+ ret
+END(prlimit64)
diff --git a/libc/arch-x86_64/syscalls.mk b/libc/arch-x86_64/syscalls.mk
index cac7423..ec09e77 100644
--- a/libc/arch-x86_64/syscalls.mk
+++ b/libc/arch-x86_64/syscalls.mk
@@ -124,6 +124,7 @@
syscall_src += arch-x86_64/syscalls/pipe2.S
syscall_src += arch-x86_64/syscalls/prctl.S
syscall_src += arch-x86_64/syscalls/pread64.S
+syscall_src += arch-x86_64/syscalls/prlimit64.S
syscall_src += arch-x86_64/syscalls/pwrite64.S
syscall_src += arch-x86_64/syscalls/read.S
syscall_src += arch-x86_64/syscalls/readahead.S
diff --git a/libc/arch-x86_64/syscalls/getrlimit.S b/libc/arch-x86_64/syscalls/getrlimit.S
index 1417b28..0b3536c 100644
--- a/libc/arch-x86_64/syscalls/getrlimit.S
+++ b/libc/arch-x86_64/syscalls/getrlimit.S
@@ -14,3 +14,6 @@
1:
ret
END(getrlimit)
+
+ .globl _C_LABEL(getrlimit64)
+ .equ _C_LABEL(getrlimit64), _C_LABEL(getrlimit)
diff --git a/libc/arch-x86_64/syscalls/prlimit64.S b/libc/arch-x86_64/syscalls/prlimit64.S
new file mode 100644
index 0000000..b451e8f
--- /dev/null
+++ b/libc/arch-x86_64/syscalls/prlimit64.S
@@ -0,0 +1,20 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+ENTRY(prlimit64)
+ movq %rcx, %r10
+ movl $__NR_prlimit64, %eax
+ syscall
+ cmpq $-MAX_ERRNO, %rax
+ jb 1f
+ negl %eax
+ movl %eax, %edi
+ call __set_errno
+ orq $-1, %rax
+1:
+ ret
+END(prlimit64)
+
+ .globl _C_LABEL(prlimit)
+ .equ _C_LABEL(prlimit), _C_LABEL(prlimit64)
diff --git a/libc/arch-x86_64/syscalls/setrlimit.S b/libc/arch-x86_64/syscalls/setrlimit.S
index de5b3b7..e445ec0 100644
--- a/libc/arch-x86_64/syscalls/setrlimit.S
+++ b/libc/arch-x86_64/syscalls/setrlimit.S
@@ -14,3 +14,6 @@
1:
ret
END(setrlimit)
+
+ .globl _C_LABEL(setrlimit64)
+ .equ _C_LABEL(setrlimit64), _C_LABEL(setrlimit)
diff --git a/libc/bionic/legacy_32_bit_support.cpp b/libc/bionic/legacy_32_bit_support.cpp
index 884dd8b..d7ccdb9 100644
--- a/libc/bionic/legacy_32_bit_support.cpp
+++ b/libc/bionic/legacy_32_bit_support.cpp
@@ -28,10 +28,9 @@
#include <errno.h>
#include <stdarg.h>
+#include <sys/resource.h>
#include <sys/types.h>
#include <sys/vfs.h>
-#include <sys/vfs.h>
-#include <unistd.h>
#include <unistd.h>
#if __LP64__
@@ -86,3 +85,13 @@
ssize_t pwrite(int fd, const void* buf, size_t byte_count, off_t offset) {
return pwrite64(fd, buf, byte_count, static_cast<off64_t>(offset));
}
+
+// There is no getrlimit64 system call, so we need to use prlimit64.
+int getrlimit64(int resource, rlimit64* limits64) {
+ return prlimit64(0, resource, NULL, limits64);
+}
+
+// There is no setrlimit64 system call, so we need to use prlimit64.
+int setrlimit64(int resource, const rlimit64* limits64) {
+ return prlimit64(0, resource, limits64, NULL);
+}
diff --git a/libc/include/sys/resource.h b/libc/include/sys/resource.h
index ef325c7..a91fa53 100644
--- a/libc/include/sys/resource.h
+++ b/libc/include/sys/resource.h
@@ -25,30 +25,35 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
+
#ifndef _SYS_RESOURCE_H_
#define _SYS_RESOURCE_H_
#include <sys/cdefs.h>
-#include <sys/types.h> /* MUST be included before linux/resource.h */
+#include <sys/types.h>
-/* TRICK AHEAD: <linux/resource.h> defines a getrusage function with
- * a non-standard signature. this is surprising because the
- * syscall seems to use the standard one instead.
- * once again, creative macro usage saves the days
- */
-#define getrusage __kernel_getrusage
#include <linux/resource.h>
-#undef getrusage
-
-typedef unsigned long rlim_t;
__BEGIN_DECLS
+typedef unsigned long rlim_t;
+
+extern int getrlimit(int, struct rlimit*);
+extern int setrlimit(int, const struct rlimit*);
+
+extern int getrlimit64(int, struct rlimit64*);
+extern int setrlimit64(int, const struct rlimit64*);
+
extern int getpriority(int, int);
extern int setpriority(int, int, int);
-extern int getrlimit(int resource, struct rlimit *rlp);
-extern int setrlimit(int resource, const struct rlimit *rlp);
-extern int getrusage(int who, struct rusage* r_usage);
+
+extern int getrusage(int, struct rusage*);
+
+#if __LP64__
+/* Implementing prlimit for 32-bit isn't worth the effort. */
+extern int prlimit(pid_t, int, const struct rlimit*, struct rlimit*);
+#endif
+extern int prlimit64(pid_t, int, const struct rlimit64*, struct rlimit64*);
__END_DECLS
diff --git a/tests/Android.mk b/tests/Android.mk
index 916d0b2..0540400 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -61,6 +61,7 @@
strings_test.cpp \
stubs_test.cpp \
sys_epoll_test.cpp \
+ sys_resource_test.cpp \
sys_select_test.cpp \
sys_sendfile_test.cpp \
sys_stat_test.cpp \
diff --git a/tests/sys_resource_test.cpp b/tests/sys_resource_test.cpp
new file mode 100644
index 0000000..bd974cb
--- /dev/null
+++ b/tests/sys_resource_test.cpp
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <sys/resource.h>
+
+#if __GLIBC__
+/* The host glibc we're currently building with doesn't have prlimit64 yet. */
+static int prlimit64(pid_t, int resource, const struct rlimit64* new_limit, struct rlimit64* old_limit) {
+ if (new_limit != NULL) {
+ return setrlimit64(resource, new_limit);
+ } else {
+ return getrlimit64(resource, old_limit);
+ }
+}
+#endif
+
+TEST(sys_resource, smoke) {
+#if __LP64__ || __GLIBC__
+ ASSERT_EQ(sizeof(rlimit), sizeof(rlimit64));
+ ASSERT_EQ(8U, sizeof(rlim_t));
+#else
+ ASSERT_NE(sizeof(rlimit), sizeof(rlimit64));
+ ASSERT_EQ(4U, sizeof(rlim_t));
+#endif
+
+ // Read with getrlimit, getrlimit64, and prlimit64.
+ // (prlimit is prlimit64 on LP64 and unimplemented on 32-bit.)
+ rlimit l32;
+ rlimit64 l64;
+ rlimit64 pr_l64;
+ ASSERT_EQ(0, getrlimit(RLIMIT_CORE, &l32));
+ ASSERT_EQ(0, getrlimit64(RLIMIT_CORE, &l64));
+ ASSERT_EQ(0, prlimit64(0, RLIMIT_CORE, NULL, &pr_l64));
+ ASSERT_EQ(l64.rlim_cur, l32.rlim_cur);
+ ASSERT_EQ(l64.rlim_cur, pr_l64.rlim_cur);
+ ASSERT_EQ(l64.rlim_max, pr_l64.rlim_max);
+ if (l64.rlim_max == RLIM64_INFINITY) {
+ ASSERT_EQ(RLIM_INFINITY, l32.rlim_max);
+ } else {
+ ASSERT_EQ(l64.rlim_max, l32.rlim_max);
+ }
+
+ // Write with setrlimit and read back with everything.
+ l32.rlim_cur = 123;
+ ASSERT_EQ(0, setrlimit(RLIMIT_CORE, &l32));
+ ASSERT_EQ(0, getrlimit(RLIMIT_CORE, &l32));
+ ASSERT_EQ(0, getrlimit64(RLIMIT_CORE, &l64));
+ ASSERT_EQ(0, prlimit64(0, RLIMIT_CORE, NULL, &pr_l64));
+ ASSERT_EQ(123U, l32.rlim_cur);
+ ASSERT_EQ(l64.rlim_cur, l32.rlim_cur);
+ ASSERT_EQ(l64.rlim_cur, pr_l64.rlim_cur);
+
+ // Write with setrlimit64 and read back with everything.
+ l64.rlim_cur = 456;
+ ASSERT_EQ(0, setrlimit64(RLIMIT_CORE, &l64));
+ ASSERT_EQ(0, getrlimit(RLIMIT_CORE, &l32));
+ ASSERT_EQ(0, getrlimit64(RLIMIT_CORE, &l64));
+ ASSERT_EQ(0, prlimit64(0, RLIMIT_CORE, NULL, &pr_l64));
+ ASSERT_EQ(456U, l32.rlim_cur);
+ ASSERT_EQ(l64.rlim_cur, l32.rlim_cur);
+ ASSERT_EQ(l64.rlim_cur, pr_l64.rlim_cur);
+
+ // Write with prlimit64 and read back with everything.
+ l64.rlim_cur = 789;
+ ASSERT_EQ(0, prlimit64(0, RLIMIT_CORE, &l64, NULL));
+ ASSERT_EQ(0, getrlimit(RLIMIT_CORE, &l32));
+ ASSERT_EQ(0, getrlimit64(RLIMIT_CORE, &l64));
+ ASSERT_EQ(0, prlimit64(0, RLIMIT_CORE, NULL, &pr_l64));
+ ASSERT_EQ(789U, l32.rlim_cur);
+ ASSERT_EQ(l64.rlim_cur, l32.rlim_cur);
+ ASSERT_EQ(l64.rlim_cur, pr_l64.rlim_cur);
+}