diff mbox

pread/pwrite: handle targets that align 64bit values in register pairs

Message ID 1391561010-10984-1-git-send-email-jmaggard10@gmail.com
State New
Headers show

Commit Message

Justin Maggard Feb. 5, 2014, 12:43 a.m. UTC
Recent changes to pread/pwrite in the 0.9.33 branch to use the proper
linux kernel syscalls failed to consider architectures that align 64-bit
values in register pairs.  These targets are already marked because
their truncate64 syscall required a different number of args as well.

Use the existing __UCLIBC_TRUNCATE64_HAS_4_ARGS__ definition to also
determine whether we should use 5 or 6 args for pread/pwrite.
---
 libc/sysdeps/linux/common/pread_write.c |   51 +++++++++++++++++++++++++++++++
 1 file changed, 51 insertions(+)
diff mbox

Patch

diff --git a/libc/sysdeps/linux/common/pread_write.c b/libc/sysdeps/linux/common/pread_write.c
index b13de66..b8d527b 100644
--- a/libc/sysdeps/linux/common/pread_write.c
+++ b/libc/sysdeps/linux/common/pread_write.c
@@ -43,6 +43,19 @@  extern __typeof(pwrite64) __libc_pwrite64;
 #include <bits/kernel_types.h>
 
 # define __NR___syscall_pread __NR_pread64
+# ifdef __UCLIBC_TRUNCATE64_HAS_4_ARGS__
+static __inline__ _syscall6(ssize_t, __syscall_pread, int, fd, void *, buf,
+		size_t, count, int, dummy, off_t, offset_hi, off_t, offset_lo)
+
+ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset)
+{
+	int oldtype = LIBC_CANCEL_ASYNC ();
+	int result = __syscall_pread(fd, buf, count, 0, __LONG_LONG_PAIR(offset >> 31, offset));
+	LIBC_CANCEL_RESET (oldtype);
+	return result;
+
+}
+# else
 static __inline__ _syscall5(ssize_t, __syscall_pread, int, fd, void *, buf,
 		size_t, count, off_t, offset_hi, off_t, offset_lo)
 
@@ -54,9 +67,21 @@  ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset)
 	return result;
 
 }
+# endif
 weak_alias(__libc_pread,pread)
 
 # ifdef __UCLIBC_HAS_LFS__
+#  ifdef __UCLIBC_TRUNCATE64_HAS_4_ARGS__
+ssize_t __libc_pread64(int fd, void *buf, size_t count, off64_t offset)
+{
+	uint32_t low = offset & 0xffffffff;
+	uint32_t high = offset >> 32;
+	int oldtype = LIBC_CANCEL_ASYNC ();
+	int result = __syscall_pread(fd, buf, count, 0, __LONG_LONG_PAIR(high, low));
+	LIBC_CANCEL_RESET (oldtype);
+	return result;
+}
+#  else
 ssize_t __libc_pread64(int fd, void *buf, size_t count, off64_t offset)
 {
 	uint32_t low = offset & 0xffffffff;
@@ -66,6 +91,7 @@  ssize_t __libc_pread64(int fd, void *buf, size_t count, off64_t offset)
 	LIBC_CANCEL_RESET (oldtype);
 	return result;
 }
+#  endif
 weak_alias(__libc_pread64,pread64)
 # endif /* __UCLIBC_HAS_LFS__  */
 
@@ -75,6 +101,18 @@  weak_alias(__libc_pread64,pread64)
 #endif
 
 # define __NR___syscall_pwrite __NR_pwrite
+# ifdef __UCLIBC_TRUNCATE64_HAS_4_ARGS__
+static __inline__ _syscall6(ssize_t, __syscall_pwrite, int, fd, const void *, buf,
+		size_t, count, int, dummy, off_t, offset_hi, off_t, offset_lo)
+
+ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset)
+{
+	int oldtype = LIBC_CANCEL_ASYNC ();
+	int result = __syscall_pwrite(fd, buf, count, 0, __LONG_LONG_PAIR(offset >> 31, offset));
+	LIBC_CANCEL_RESET (oldtype);
+	return result;
+}
+# else
 static __inline__ _syscall5(ssize_t, __syscall_pwrite, int, fd, const void *, buf,
 		size_t, count, off_t, offset_hi, off_t, offset_lo)
 
@@ -85,9 +123,21 @@  ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset)
 	LIBC_CANCEL_RESET (oldtype);
 	return result;
 }
+# endif
 weak_alias(__libc_pwrite,pwrite)
 
 # ifdef __UCLIBC_HAS_LFS__
+#  ifdef __UCLIBC_TRUNCATE64_HAS_4_ARGS__
+ssize_t __libc_pwrite64(int fd, const void *buf, size_t count, off64_t offset)
+{
+	uint32_t low = offset & 0xffffffff;
+	uint32_t high = offset >> 32;
+	int oldtype = LIBC_CANCEL_ASYNC ();
+	int result = __syscall_pwrite(fd, buf, count, 0, __LONG_LONG_PAIR(high, low));
+	LIBC_CANCEL_RESET (oldtype);
+	return result;
+}
+#  else
 ssize_t __libc_pwrite64(int fd, const void *buf, size_t count, off64_t offset)
 {
 	uint32_t low = offset & 0xffffffff;
@@ -97,5 +147,6 @@  ssize_t __libc_pwrite64(int fd, const void *buf, size_t count, off64_t offset)
 	LIBC_CANCEL_RESET (oldtype);
 	return result;
 }
+#  endif
 weak_alias(__libc_pwrite64,pwrite64)
 # endif /* __UCLIBC_HAS_LFS__  */