am 848808c6: Merge "Add preadv/pwritev."
* commit '848808c660ec4811f4ff5a2748b6f754b008cd21': Add preadv/pwritev.
This commit is contained in:
commit
c6effb3af6
@ -94,6 +94,16 @@ ssize_t pread64(int, void*, size_t, off64_t) arm,mips,x86
|
||||
ssize_t pread64|pread(int, void*, size_t, off_t) arm64,mips64,x86_64
|
||||
ssize_t pwrite64(int, void*, size_t, off64_t) arm,mips,x86
|
||||
ssize_t pwrite64|pwrite(int, void*, size_t, off_t) arm64,mips64,x86_64
|
||||
|
||||
# On LP32, preadv/pwritev don't use off64_t --- they use pairs of 32-bit
|
||||
# arguments to avoid problems on architectures like ARM where 64-bit arguments
|
||||
# must be in a register pair starting with an even-numbered register.
|
||||
# See linux/fs/read_write.c and https://lwn.net/Articles/311630/.
|
||||
ssize_t __preadv64:preadv(int, const struct iovec*, int, long, long) arm,mips,x86
|
||||
ssize_t preadv|preadv64(int, const struct iovec*, int, off_t) arm64,mips64,x86_64
|
||||
ssize_t __pwritev64:pwritev(int, const struct iovec*, int, long, long) arm,mips,x86
|
||||
ssize_t pwritev|pwritev64(int, const struct iovec*, int, off_t) arm64,mips64,x86_64
|
||||
|
||||
int ___close:close(int) all
|
||||
pid_t __getpid:getpid() all
|
||||
int munmap(void*, size_t) all
|
||||
|
22
libc/arch-arm/syscalls/__preadv64.S
Normal file
22
libc/arch-arm/syscalls/__preadv64.S
Normal file
@ -0,0 +1,22 @@
|
||||
/* Generated by gensyscalls.py. Do not edit. */
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(__preadv64)
|
||||
mov ip, sp
|
||||
stmfd sp!, {r4, r5, r6, r7}
|
||||
.cfi_def_cfa_offset 16
|
||||
.cfi_rel_offset r4, 0
|
||||
.cfi_rel_offset r5, 4
|
||||
.cfi_rel_offset r6, 8
|
||||
.cfi_rel_offset r7, 12
|
||||
ldmfd ip, {r4, r5, r6}
|
||||
ldr r7, =__NR_preadv
|
||||
swi #0
|
||||
ldmfd sp!, {r4, r5, r6, r7}
|
||||
.cfi_def_cfa_offset 0
|
||||
cmn r0, #(MAX_ERRNO + 1)
|
||||
bxls lr
|
||||
neg r0, r0
|
||||
b __set_errno_internal
|
||||
END(__preadv64)
|
22
libc/arch-arm/syscalls/__pwritev64.S
Normal file
22
libc/arch-arm/syscalls/__pwritev64.S
Normal file
@ -0,0 +1,22 @@
|
||||
/* Generated by gensyscalls.py. Do not edit. */
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(__pwritev64)
|
||||
mov ip, sp
|
||||
stmfd sp!, {r4, r5, r6, r7}
|
||||
.cfi_def_cfa_offset 16
|
||||
.cfi_rel_offset r4, 0
|
||||
.cfi_rel_offset r5, 4
|
||||
.cfi_rel_offset r6, 8
|
||||
.cfi_rel_offset r7, 12
|
||||
ldmfd ip, {r4, r5, r6}
|
||||
ldr r7, =__NR_pwritev
|
||||
swi #0
|
||||
ldmfd sp!, {r4, r5, r6, r7}
|
||||
.cfi_def_cfa_offset 0
|
||||
cmn r0, #(MAX_ERRNO + 1)
|
||||
bxls lr
|
||||
neg r0, r0
|
||||
b __set_errno_internal
|
||||
END(__pwritev64)
|
16
libc/arch-arm64/syscalls/preadv.S
Normal file
16
libc/arch-arm64/syscalls/preadv.S
Normal file
@ -0,0 +1,16 @@
|
||||
/* Generated by gensyscalls.py. Do not edit. */
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(preadv)
|
||||
mov x8, __NR_preadv
|
||||
svc #0
|
||||
|
||||
cmn x0, #(MAX_ERRNO + 1)
|
||||
cneg x0, x0, hi
|
||||
b.hi __set_errno_internal
|
||||
|
||||
ret
|
||||
END(preadv)
|
||||
|
||||
ALIAS_SYMBOL(preadv64, preadv)
|
16
libc/arch-arm64/syscalls/pwritev.S
Normal file
16
libc/arch-arm64/syscalls/pwritev.S
Normal file
@ -0,0 +1,16 @@
|
||||
/* Generated by gensyscalls.py. Do not edit. */
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(pwritev)
|
||||
mov x8, __NR_pwritev
|
||||
svc #0
|
||||
|
||||
cmn x0, #(MAX_ERRNO + 1)
|
||||
cneg x0, x0, hi
|
||||
b.hi __set_errno_internal
|
||||
|
||||
ret
|
||||
END(pwritev)
|
||||
|
||||
ALIAS_SYMBOL(pwritev64, pwritev)
|
19
libc/arch-mips/syscalls/__preadv64.S
Normal file
19
libc/arch-mips/syscalls/__preadv64.S
Normal file
@ -0,0 +1,19 @@
|
||||
/* Generated by gensyscalls.py. Do not edit. */
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(__preadv64)
|
||||
.set noreorder
|
||||
.cpload t9
|
||||
li v0, __NR_preadv
|
||||
syscall
|
||||
bnez a3, 1f
|
||||
move a0, v0
|
||||
j ra
|
||||
nop
|
||||
1:
|
||||
la t9,__set_errno_internal
|
||||
j t9
|
||||
nop
|
||||
.set reorder
|
||||
END(__preadv64)
|
19
libc/arch-mips/syscalls/__pwritev64.S
Normal file
19
libc/arch-mips/syscalls/__pwritev64.S
Normal file
@ -0,0 +1,19 @@
|
||||
/* Generated by gensyscalls.py. Do not edit. */
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(__pwritev64)
|
||||
.set noreorder
|
||||
.cpload t9
|
||||
li v0, __NR_pwritev
|
||||
syscall
|
||||
bnez a3, 1f
|
||||
move a0, v0
|
||||
j ra
|
||||
nop
|
||||
1:
|
||||
la t9,__set_errno_internal
|
||||
j t9
|
||||
nop
|
||||
.set reorder
|
||||
END(__pwritev64)
|
27
libc/arch-mips64/syscalls/preadv.S
Normal file
27
libc/arch-mips64/syscalls/preadv.S
Normal file
@ -0,0 +1,27 @@
|
||||
/* Generated by gensyscalls.py. Do not edit. */
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(preadv)
|
||||
.set push
|
||||
.set noreorder
|
||||
li v0, __NR_preadv
|
||||
syscall
|
||||
bnez a3, 1f
|
||||
move a0, v0
|
||||
j ra
|
||||
nop
|
||||
1:
|
||||
move t0, ra
|
||||
bal 2f
|
||||
nop
|
||||
2:
|
||||
.cpsetup ra, t1, 2b
|
||||
LA t9,__set_errno_internal
|
||||
.cpreturn
|
||||
j t9
|
||||
move ra, t0
|
||||
.set pop
|
||||
END(preadv)
|
||||
|
||||
ALIAS_SYMBOL(preadv64, preadv)
|
27
libc/arch-mips64/syscalls/pwritev.S
Normal file
27
libc/arch-mips64/syscalls/pwritev.S
Normal file
@ -0,0 +1,27 @@
|
||||
/* Generated by gensyscalls.py. Do not edit. */
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(pwritev)
|
||||
.set push
|
||||
.set noreorder
|
||||
li v0, __NR_pwritev
|
||||
syscall
|
||||
bnez a3, 1f
|
||||
move a0, v0
|
||||
j ra
|
||||
nop
|
||||
1:
|
||||
move t0, ra
|
||||
bal 2f
|
||||
nop
|
||||
2:
|
||||
.cpsetup ra, t1, 2b
|
||||
LA t9,__set_errno_internal
|
||||
.cpreturn
|
||||
j t9
|
||||
move ra, t0
|
||||
.set pop
|
||||
END(pwritev)
|
||||
|
||||
ALIAS_SYMBOL(pwritev64, pwritev)
|
41
libc/arch-x86/syscalls/__preadv64.S
Normal file
41
libc/arch-x86/syscalls/__preadv64.S
Normal file
@ -0,0 +1,41 @@
|
||||
/* Generated by gensyscalls.py. Do not edit. */
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(__preadv64)
|
||||
pushl %ebx
|
||||
.cfi_def_cfa_offset 8
|
||||
.cfi_rel_offset ebx, 0
|
||||
pushl %ecx
|
||||
.cfi_adjust_cfa_offset 4
|
||||
.cfi_rel_offset ecx, 0
|
||||
pushl %edx
|
||||
.cfi_adjust_cfa_offset 4
|
||||
.cfi_rel_offset edx, 0
|
||||
pushl %esi
|
||||
.cfi_adjust_cfa_offset 4
|
||||
.cfi_rel_offset esi, 0
|
||||
pushl %edi
|
||||
.cfi_adjust_cfa_offset 4
|
||||
.cfi_rel_offset edi, 0
|
||||
mov 24(%esp), %ebx
|
||||
mov 28(%esp), %ecx
|
||||
mov 32(%esp), %edx
|
||||
mov 36(%esp), %esi
|
||||
mov 40(%esp), %edi
|
||||
movl $__NR_preadv, %eax
|
||||
int $0x80
|
||||
cmpl $-MAX_ERRNO, %eax
|
||||
jb 1f
|
||||
negl %eax
|
||||
pushl %eax
|
||||
call __set_errno_internal
|
||||
addl $4, %esp
|
||||
1:
|
||||
popl %edi
|
||||
popl %esi
|
||||
popl %edx
|
||||
popl %ecx
|
||||
popl %ebx
|
||||
ret
|
||||
END(__preadv64)
|
41
libc/arch-x86/syscalls/__pwritev64.S
Normal file
41
libc/arch-x86/syscalls/__pwritev64.S
Normal file
@ -0,0 +1,41 @@
|
||||
/* Generated by gensyscalls.py. Do not edit. */
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(__pwritev64)
|
||||
pushl %ebx
|
||||
.cfi_def_cfa_offset 8
|
||||
.cfi_rel_offset ebx, 0
|
||||
pushl %ecx
|
||||
.cfi_adjust_cfa_offset 4
|
||||
.cfi_rel_offset ecx, 0
|
||||
pushl %edx
|
||||
.cfi_adjust_cfa_offset 4
|
||||
.cfi_rel_offset edx, 0
|
||||
pushl %esi
|
||||
.cfi_adjust_cfa_offset 4
|
||||
.cfi_rel_offset esi, 0
|
||||
pushl %edi
|
||||
.cfi_adjust_cfa_offset 4
|
||||
.cfi_rel_offset edi, 0
|
||||
mov 24(%esp), %ebx
|
||||
mov 28(%esp), %ecx
|
||||
mov 32(%esp), %edx
|
||||
mov 36(%esp), %esi
|
||||
mov 40(%esp), %edi
|
||||
movl $__NR_pwritev, %eax
|
||||
int $0x80
|
||||
cmpl $-MAX_ERRNO, %eax
|
||||
jb 1f
|
||||
negl %eax
|
||||
pushl %eax
|
||||
call __set_errno_internal
|
||||
addl $4, %esp
|
||||
1:
|
||||
popl %edi
|
||||
popl %esi
|
||||
popl %edx
|
||||
popl %ecx
|
||||
popl %ebx
|
||||
ret
|
||||
END(__pwritev64)
|
18
libc/arch-x86_64/syscalls/preadv.S
Normal file
18
libc/arch-x86_64/syscalls/preadv.S
Normal file
@ -0,0 +1,18 @@
|
||||
/* Generated by gensyscalls.py. Do not edit. */
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(preadv)
|
||||
movq %rcx, %r10
|
||||
movl $__NR_preadv, %eax
|
||||
syscall
|
||||
cmpq $-MAX_ERRNO, %rax
|
||||
jb 1f
|
||||
negl %eax
|
||||
movl %eax, %edi
|
||||
call __set_errno_internal
|
||||
1:
|
||||
ret
|
||||
END(preadv)
|
||||
|
||||
ALIAS_SYMBOL(preadv64, preadv)
|
18
libc/arch-x86_64/syscalls/pwritev.S
Normal file
18
libc/arch-x86_64/syscalls/pwritev.S
Normal file
@ -0,0 +1,18 @@
|
||||
/* Generated by gensyscalls.py. Do not edit. */
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(pwritev)
|
||||
movq %rcx, %r10
|
||||
movl $__NR_pwritev, %eax
|
||||
syscall
|
||||
cmpq $-MAX_ERRNO, %rax
|
||||
jb 1f
|
||||
negl %eax
|
||||
movl %eax, %edi
|
||||
call __set_errno_internal
|
||||
1:
|
||||
ret
|
||||
END(pwritev)
|
||||
|
||||
ALIAS_SYMBOL(pwritev64, pwritev)
|
@ -33,6 +33,7 @@
|
||||
#include <stdarg.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/vfs.h>
|
||||
#include <unistd.h>
|
||||
|
||||
@ -43,6 +44,8 @@
|
||||
// System calls we need.
|
||||
extern "C" int __fcntl64(int, int, void*);
|
||||
extern "C" int __llseek(int, unsigned long, unsigned long, off64_t*, int);
|
||||
extern "C" int __preadv64(int, const struct iovec*, int, long, long);
|
||||
extern "C" int __pwritev64(int, const struct iovec*, int, long, long);
|
||||
|
||||
// For fcntl we use the fcntl64 system call to signal that we're using struct flock64.
|
||||
int fcntl(int fd, int cmd, ...) {
|
||||
@ -77,6 +80,23 @@ 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));
|
||||
}
|
||||
|
||||
// On LP32, there is no off_t preadv/pwritev, and even the 64-bit preadv/pwritev
|
||||
// don't use off64_t (see SYSCALLS.TXT for more). Here, this means that we need
|
||||
// to implement all four functions because the two system calls don't match any
|
||||
// of the userspace functions. Unlike llseek, the pair is split lo-hi, not hi-lo.
|
||||
ssize_t preadv(int fd, const struct iovec* ios, int count, off_t offset) {
|
||||
return __preadv64(fd, ios, count, offset, 0);
|
||||
}
|
||||
ssize_t preadv64(int fd, const struct iovec* ios, int count, off64_t offset) {
|
||||
return __preadv64(fd, ios, count, offset, offset >> 32);
|
||||
}
|
||||
ssize_t pwritev(int fd, const struct iovec* ios, int count, off_t offset) {
|
||||
return __pwritev64(fd, ios, count, offset, 0);
|
||||
}
|
||||
ssize_t pwritev64(int fd, const struct iovec* ios, int count, off64_t offset) {
|
||||
return __pwritev64(fd, ios, count, offset, offset >> 32);
|
||||
}
|
||||
|
||||
// There is no fallocate for 32-bit off_t, so we need to widen and call fallocate64.
|
||||
int fallocate(int fd, int mode, off_t offset, off_t length) {
|
||||
return fallocate64(fd, mode, static_cast<off64_t>(offset), static_cast<off64_t>(length));
|
||||
|
@ -37,6 +37,18 @@ __BEGIN_DECLS
|
||||
int readv(int, const struct iovec*, int);
|
||||
int writev(int, const struct iovec*, int);
|
||||
|
||||
#if defined(__USE_GNU)
|
||||
#if defined(__USE_FILE_OFFSET64)
|
||||
ssize_t preadv(int, const struct iovec*, int, off_t) __RENAME(preadv64);
|
||||
ssize_t pwritev(int, const struct iovec*, int, off_t) __RENAME(pwritev64);
|
||||
#else
|
||||
ssize_t preadv(int, const struct iovec*, int, off_t);
|
||||
ssize_t pwritev(int, const struct iovec*, int, off_t);
|
||||
#endif
|
||||
ssize_t preadv64(int, const struct iovec*, int, off64_t);
|
||||
ssize_t pwritev64(int, const struct iovec*, int, off64_t);
|
||||
#endif
|
||||
|
||||
#if defined(__USE_GNU)
|
||||
ssize_t process_vm_readv(pid_t, const struct iovec*, unsigned long, const struct iovec*, unsigned long, unsigned long);
|
||||
ssize_t process_vm_writev(pid_t, const struct iovec*, unsigned long, const struct iovec*, unsigned long, unsigned long);
|
||||
|
@ -1342,6 +1342,10 @@ LIBC_N {
|
||||
__write_chk;
|
||||
getgrgid_r;
|
||||
getgrnam_r;
|
||||
preadv;
|
||||
preadv64;
|
||||
pwritev;
|
||||
pwritev64;
|
||||
strchrnul;
|
||||
} LIBC;
|
||||
|
||||
|
@ -18,10 +18,60 @@
|
||||
|
||||
#include <sys/uio.h>
|
||||
|
||||
TEST(sys_uio, process_vm_readv_ESRCH) {
|
||||
#include "TemporaryFile.h"
|
||||
|
||||
TEST(sys_uio, readv_writev) {
|
||||
TemporaryFile tf;
|
||||
|
||||
char buf1[] = "hello";
|
||||
char buf2[] = "world";
|
||||
iovec ios[] = { { buf1, 5 }, { buf2, 5 } };
|
||||
|
||||
ASSERT_EQ(10, writev(tf.fd, ios, 2));
|
||||
|
||||
ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET));
|
||||
|
||||
memset(buf1, '1', sizeof(buf1));
|
||||
memset(buf2, '2', sizeof(buf2));
|
||||
|
||||
ASSERT_EQ(10, readv(tf.fd, ios, 2));
|
||||
buf1[5] = buf2[5] = '\0';
|
||||
ASSERT_STREQ("hello", buf1);
|
||||
ASSERT_STREQ("world", buf2);
|
||||
}
|
||||
|
||||
template <typename ReadFn, typename WriteFn>
|
||||
void TestPreadVPwriteV(ReadFn read_fn, WriteFn write_fn) {
|
||||
TemporaryFile tf;
|
||||
|
||||
char buf[] = "world";
|
||||
iovec ios[] = { { buf, 5 } };
|
||||
|
||||
ASSERT_EQ(5, write_fn(tf.fd, ios, 1, 5));
|
||||
ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_CUR));
|
||||
|
||||
strcpy(buf, "hello");
|
||||
ASSERT_EQ(5, write_fn(tf.fd, ios, 1, 0));
|
||||
ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_CUR));
|
||||
|
||||
ASSERT_EQ(5, read_fn(tf.fd, ios, 1, 5));
|
||||
ASSERT_STREQ("world", buf);
|
||||
ASSERT_EQ(5, read_fn(tf.fd, ios, 1, 0));
|
||||
ASSERT_STREQ("hello", buf);
|
||||
}
|
||||
|
||||
TEST(sys_uio, preadv_pwritev) {
|
||||
TestPreadVPwriteV(preadv, pwritev);
|
||||
}
|
||||
|
||||
TEST(sys_uio, preadv64_pwritev64) {
|
||||
TestPreadVPwriteV(preadv64, pwritev64);
|
||||
}
|
||||
|
||||
TEST(sys_uio, process_vm_readv) {
|
||||
ASSERT_EQ(0, process_vm_readv(0, nullptr, 0, nullptr, 0, 0));
|
||||
}
|
||||
|
||||
TEST(sys_uio, process_vm_writev_ESRCH) {
|
||||
TEST(sys_uio, process_vm_writev) {
|
||||
ASSERT_EQ(0, process_vm_writev(0, nullptr, 0, nullptr, 0, 0));
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user