diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT index d0fa528f4..6e10daa53 100644 --- a/libc/SYSCALLS.TXT +++ b/libc/SYSCALLS.TXT @@ -62,12 +62,21 @@ int tkill(pid_t tid, int sig) all 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 + +# +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 3e5d191f7..653ef7059 100644 --- a/libc/arch-aarch64/syscalls.mk +++ b/libc/arch-aarch64/syscalls.mk @@ -123,6 +123,7 @@ syscall_src += arch-aarch64/syscalls/personality.S 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 8b6548fb2..21b471e10 100644 --- a/libc/arch-aarch64/syscalls/getrlimit.S +++ b/libc/arch-aarch64/syscalls/getrlimit.S @@ -19,3 +19,6 @@ ENTRY(getrlimit) 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 000000000..439e35522 --- /dev/null +++ b/libc/arch-aarch64/syscalls/prlimit64.S @@ -0,0 +1,24 @@ +/* Generated by gensyscalls.py. Do not edit. */ + +#include + +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 3591a8454..e72380632 100644 --- a/libc/arch-aarch64/syscalls/setrlimit.S +++ b/libc/arch-aarch64/syscalls/setrlimit.S @@ -19,3 +19,6 @@ ENTRY(setrlimit) 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 f1763efaf..83e6a970d 100644 --- a/libc/arch-arm/syscalls.mk +++ b/libc/arch-arm/syscalls.mk @@ -129,6 +129,7 @@ syscall_src += arch-arm/syscalls/personality.S 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 000000000..8d9c4ff64 --- /dev/null +++ b/libc/arch-arm/syscalls/prlimit64.S @@ -0,0 +1,14 @@ +/* Generated by gensyscalls.py. Do not edit. */ + +#include + +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 cc7e557d6..8d87b295f 100644 --- a/libc/arch-mips/syscalls.mk +++ b/libc/arch-mips/syscalls.mk @@ -129,6 +129,7 @@ syscall_src += arch-mips/syscalls/personality.S 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 000000000..17e9157fa --- /dev/null +++ b/libc/arch-mips/syscalls/prlimit64.S @@ -0,0 +1,23 @@ +/* Generated by gensyscalls.py. Do not edit. */ + +#include + .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 0699d091a..b7d1e0834 100644 --- a/libc/arch-x86/syscalls.mk +++ b/libc/arch-x86/syscalls.mk @@ -128,6 +128,7 @@ syscall_src += arch-x86/syscalls/personality.S 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 000000000..225642524 --- /dev/null +++ b/libc/arch-x86/syscalls/prlimit64.S @@ -0,0 +1,34 @@ +/* Generated by gensyscalls.py. Do not edit. */ + +#include + +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 cac7423dc..ec09e7744 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/personality.S 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 1417b28df..0b3536c3c 100644 --- a/libc/arch-x86_64/syscalls/getrlimit.S +++ b/libc/arch-x86_64/syscalls/getrlimit.S @@ -14,3 +14,6 @@ ENTRY(getrlimit) 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 000000000..b451e8f06 --- /dev/null +++ b/libc/arch-x86_64/syscalls/prlimit64.S @@ -0,0 +1,20 @@ +/* Generated by gensyscalls.py. Do not edit. */ + +#include + +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 de5b3b71a..e445ec0dc 100644 --- a/libc/arch-x86_64/syscalls/setrlimit.S +++ b/libc/arch-x86_64/syscalls/setrlimit.S @@ -14,3 +14,6 @@ ENTRY(setrlimit) 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 884dd8b27..d7ccdb95e 100644 --- a/libc/bionic/legacy_32_bit_support.cpp +++ b/libc/bionic/legacy_32_bit_support.cpp @@ -28,10 +28,9 @@ #include #include +#include #include #include -#include -#include #include #if __LP64__ @@ -86,3 +85,13 @@ ssize_t pread(int fd, void* buf, size_t byte_count, off_t offset) { ssize_t pwrite(int fd, const void* buf, size_t byte_count, off_t offset) { return pwrite64(fd, buf, byte_count, static_cast(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 ef325c7aa..a91fa5394 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 -#include /* MUST be included before linux/resource.h */ +#include -/* TRICK AHEAD: 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 -#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 916d0b28d..0540400c6 100644 --- a/tests/Android.mk +++ b/tests/Android.mk @@ -61,6 +61,7 @@ test_src_files = \ 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 000000000..bd974cb94 --- /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 + +#include + +#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); +}