[PATCH] Fix ppc32

Franz Sirl Franz.Sirl-kernel@lauterbach.com
Mon Jan 6 19:07:00 GMT 2003


On Monday 06 January 2003 17:13, Jakub Jelinek wrote:
> On Sat, Jan 04, 2003 at 10:01:16PM +0100, Franz Sirl wrote:
> > On Saturday 04 January 2003 21:33, Jakub Jelinek wrote:
> > > On Sat, Jan 04, 2003 at 05:06:01PM +0100, Franz Sirl wrote:
> > > >	*
> > > > linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.
> > > >h: New file.
> > >
> > > Thanks for working on this.
> >
> > I'm forced to, if I want to keep my system uptodate :-). Any idea about
> > the AIO problem?
>
> Actually, I have - broken pread* and pwrite*.
> The following patch (on top of the LIBC_CANCEL_HANDLED patch) should fix
> it. __syscall_pread/__syscall_pwrite uses r3,r4,r5,r7,r8 regs to pass
> arguments, so syscalls.list needs to indicate that.
> Alternatively, you could do LIBC_CANCEL_ASYNC/LIBC_CANCEL_RESET in
> sysdeps/unix/sysv/linux/powerpc/p{read,write}{,64}.c.
>
> Also, sysdeps/unix/sysv/linux/powerpc/powerpc32/socket.S needs cancellation
> support.
>
> 2003-01-06  Jakub Jelinek  <jakub@redhat.com>
>
> 	* sysdeps/unix/sysv/linux/powerpc/powerpc32/syscalls.list
> 	(s_pread64, s_pwrite64): Add 6th argument.
> 	* sysdeps/unix/sysv/linux/powerpc/pread.c: Include sysdep-cancel.h,
> 	add LIBC_CANCEL_HANDLED.
> 	* sysdeps/unix/sysv/linux/powerpc/pread64.c: Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/pwrite.c: Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/pwrite64.c: Likewise.
> linuxthreads/
> 	* sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h
> 	(DOCARGS_6, UNDOCARGS_6): Define.

Uhm, sorry for the delay, I have a patch already for that. Your analysis for 
the pread/pwrite problem is correct though, I noted this myself yesterday 
morning, but the machines I have access to are quite slow...

Anyway, since I realized there is now a possible failure point with 64bit args 
to syscalls and PSEUDO stubs as well, my refusal to use INLINE_SYSCALL 
unfortunately has no advantage anymore (before the args argument simply 
wasn't used and couldn't cause failures). The appended patch adds 
*truncate64.c, pread*.c and pwrite*.c to PPC32. Would someone please so kind 
and move the old files down to the powerpc64 directory?

There's also a small hunk for elf/dl-misc.c that makes it explicit that we 
want the address of the IOV array. That way the sizeof safety checks I added 
don't need to mess around with __builtin_classify_type.

Franz.

	* elf/dl-misc.c (_dl_debug_vdprintf): Make taking address of array
	explicit.
	* sysdeps/powerpc/powerpc32/sysdep.h (PSEUDO_RET): Add branch hint.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/socket.S: Add cancellation
	support.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/syscalls.list: Remove
	ftruncate64, truncate64, pread64 and pwrite64 entries.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h
	(INLINE_SYSCALL): Add __builtin_expect.
	(LOADARGS_n): Add argument size safety checks.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/ftruncate64.c: New file.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/truncate64.c: New file.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/pread.c: New file.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/pread64.c: New file.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/pwrite.c: New file.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/pwrite64.c: New file.

linuxthreads:
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/Makefile: Remove s_pread64 and
	s_pwrite64.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h: Add support for
	syscalls with 6 arguments.

-------------- next part --------------
Index: elf/dl-misc.c
===================================================================
RCS file: /cvs/glibc/libc/elf/dl-misc.c,v
retrieving revision 1.27
diff -u -p -r1.27 dl-misc.c
--- elf/dl-misc.c	13 Dec 2002 19:42:53 -0000	1.27
+++ elf/dl-misc.c	6 Jan 2003 16:42:26 -0000
@@ -248,7 +248,7 @@ _dl_debug_vdprintf (int fd, int tag_p, c
 
   /* Finally write the result.  */
 #ifdef INTERNAL_SYSCALL
-  INTERNAL_SYSCALL (writev, 3, fd, iov, niov);
+  INTERNAL_SYSCALL (writev, 3, fd, &iov, niov);
 #elif RTLD_PRIVATE_ERRNO
   /* We have to take this lock just to be sure we don't clobber the private
      errno when it's being used by another thread that cares about it.
Index: linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc32/Makefile
===================================================================
RCS file: /cvs/glibc/libc/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc32/Makefile,v
retrieving revision 1.1
diff -u -p -r1.1 Makefile
--- linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc32/Makefile	5 Jan 2003 10:53:51 -0000	1.1
+++ linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc32/Makefile	6 Jan 2003 16:42:31 -0000
@@ -1 +1,2 @@
-libpthread-routines += sysdep s_pread64 s_pwrite64
+# pull in __syscall_error routine
+libpthread-routines += sysdep
Index: linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h
===================================================================
RCS file: /cvs/glibc/libc/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h,v
retrieving revision 1.1
diff -u -p -r1.1 sysdep-cancel.h
--- linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h	5 Jan 2003 10:54:19 -0000	1.1
+++ linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h	6 Jan 2003 16:42:31 -0000
@@ -71,6 +71,9 @@
 # define DOCARGS_5	stw 7,36(1); DOCARGS_4
 # define UNDOCARGS_5	lwz 7,36(1); UNDOCARGS_4
 
+# define DOCARGS_6	stw 8,40(1); DOCARGS_5
+# define UNDOCARGS_6	lwz 8,40(1); UNDOCARGS_5
+
 # ifdef IS_IN_libpthread
 #  define CENABLE	bl JUMPTARGET(__pthread_enable_asynccancel)
 #  define CDISABLE	bl JUMPTARGET(__pthread_disable_asynccancel)
Index: sysdeps/powerpc/powerpc32/sysdep.h
===================================================================
RCS file: /cvs/glibc/libc/sysdeps/powerpc/powerpc32/sysdep.h,v
retrieving revision 1.1
diff -u -p -r1.1 sysdep.h
--- sysdeps/powerpc/powerpc32/sysdep.h	20 Sep 2002 23:45:49 -0000	1.1
+++ sysdeps/powerpc/powerpc32/sysdep.h	6 Jan 2003 16:42:33 -0000
@@ -116,7 +116,7 @@
     DO_CALL (SYS_ify (syscall_name));
 
 #define PSEUDO_RET							      \
-    bnslr;								      \
+    bnslr+;								      \
     b JUMPTARGET(__syscall_error)
 #define ret PSEUDO_RET
 
Index: sysdeps/unix/sysv/linux/powerpc/powerpc32/socket.S
===================================================================
RCS file: /cvs/glibc/libc/sysdeps/unix/sysv/linux/powerpc/powerpc32/socket.S,v
retrieving revision 1.1
diff -u -p -r1.1 socket.S
--- sysdeps/unix/sysv/linux/powerpc/powerpc32/socket.S	5 Sep 2002 09:13:44 -0000	1.1
+++ sysdeps/unix/sysv/linux/powerpc/powerpc32/socket.S	6 Jan 2003 16:42:34 -0000
@@ -16,7 +16,7 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
-#include <sysdep.h>
+#include <sysdep-cancel.h>
 #include <socketcall.h>
 
 #define P(a, b) P2(a, b)
@@ -75,11 +75,41 @@ ENTRY(__socket)
 #if NARGS >= 9
 #error too many arguments!
 #endif
+
+#if defined NEED_CANCELLATION && defined CENABLE
+	SINGLE_THREAD_P
+	bne-	.Lsocket_cancel
+#endif
+
 	li	r3,P(SOCKOP_,socket)
 	addi	r4,r1,stackblock
 	DO_CALL(SYS_ify(socketcall))
 	addi	r1,r1,48
 	PSEUDO_RET
+
+#if defined NEED_CANCELLATION && defined CENABLE
+.Lsocket_cancel:
+	mflr	r9
+	stw	r9,52(r1)
+	CENABLE
+	stw	r3,16(r1)
+	li	r3,P(SOCKOP_,socket)
+	addi	r4,r1,stackblock
+	DO_CALL(SYS_ify(socketcall))
+	mfcr	r0
+	stw	r3,8(r1)
+	stw	r0,12(r1)
+	lwz	r3,16(r1)
+	CDISABLE
+	lwz	r4,52(r1)
+	lwz	r0,12(r1)
+	lwz	r3,8(r1)
+	mtlr	r4
+	mtcr	r0
+	addi	r1,r1,48
+	PSEUDO_RET
+#endif
+
 PSEUDO_END (__socket)
 
 weak_alias (__socket, socket)
Index: sysdeps/unix/sysv/linux/powerpc/powerpc32/syscalls.list
===================================================================
RCS file: /cvs/glibc/libc/sysdeps/unix/sysv/linux/powerpc/powerpc32/syscalls.list,v
retrieving revision 1.5
diff -u -p -r1.5 syscalls.list
--- sysdeps/unix/sysv/linux/powerpc/powerpc32/syscalls.list	5 Jan 2003 10:50:38 -0000	1.5
+++ sysdeps/unix/sysv/linux/powerpc/powerpc32/syscalls.list	6 Jan 2003 16:42:34 -0000
@@ -9,9 +9,3 @@ rt_sigsuspend	-	rt_sigsuspend	i:pi	__sys
 rt_sigtimedwait	-	rt_sigtimedwait	i:pppi	__syscall_rt_sigtimedwait
 oldgetrlimit	EXTRA	getrlimit	i:ip	__old_getrlimit	getrlimit@GLIBC_2.0
 oldsetrlimit	EXTRA	setrlimit	i:ip	__old_setrlimit	setrlimit@GLIBC_2.0
-
-# System calls with 64bit args
-s_ftruncate64	ftruncate64 ftruncate64	i:iii	__syscall_ftruncate64
-s_pread64	pread64	pread		Ci:ibnii	__syscall_pread
-s_pwrite64	pwrite64 pwrite		Ci:ibnii	__syscall_pwrite
-s_truncate64	truncate64 truncate64	i:sii	__syscall_truncate64
Index: sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h
===================================================================
RCS file: /cvs/glibc/libc/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h,v
retrieving revision 1.6
diff -u -p -r1.6 sysdep.h
--- sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h	5 Jan 2003 10:51:04 -0000	1.6
+++ sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h	6 Jan 2003 16:42:34 -0000
@@ -85,7 +85,7 @@
        : "cr0", "ctr", "memory");					\
     err = r0;								\
     ret = r3;								\
-    if (err & (1 << 28))						\
+    if (__builtin_expect (err & (1 << 28), 0))				\
       {									\
 	__set_errno (ret);						\
 	ret = -1L;							\
@@ -99,7 +99,7 @@
    gave back in the non-error (CR0.SO cleared) case, otherwise (CR0.SO set)
    the negation of the return value in the kernel gets reverted.  */
 
-#undef INTERNAL_SYSCALL
+# undef INTERNAL_SYSCALL
 # define INTERNAL_SYSCALL(name, nr, args...)				\
   ({									\
     register long r0  __asm__ ("r0");					\
@@ -127,31 +127,43 @@
     (int) r3;								\
   })
   
-#undef INTERNAL_SYSCALL_ERROR_P
-#define INTERNAL_SYSCALL_ERROR_P(val)   ((unsigned long) (val) >= -4095U)
+# undef INTERNAL_SYSCALL_ERROR_P
+# define INTERNAL_SYSCALL_ERROR_P(val)   ((unsigned long) (val) >= 0xfffff001u)
   
-#undef INTERNAL_SYSCALL_ERRNO
-#define INTERNAL_SYSCALL_ERRNO(val)     (-(val))
+# undef INTERNAL_SYSCALL_ERRNO
+# define INTERNAL_SYSCALL_ERRNO(val)     (-(val))
 
 # define LOADARGS_0(name, dummy) \
 	r0 = __NR_##name
 # define LOADARGS_1(name, arg1) \
 	LOADARGS_0(name, 0); \
+	extern void __illegally_sized_syscall_##name##_arg1 (void); \
+	if (sizeof (arg1) > 4) __illegally_sized_syscall_##name##_arg1 (); \
 	r3 = (long) (arg1)
 # define LOADARGS_2(name, arg1, arg2) \
 	LOADARGS_1(name, arg1); \
+	extern void __illegally_sized_syscall_##name##_arg2 (void); \
+	if (sizeof (arg2) > 4) __illegally_sized_syscall_##name##_arg2 (); \
 	r4 = (long) (arg2)
 # define LOADARGS_3(name, arg1, arg2, arg3) \
 	LOADARGS_2(name, arg1, arg2); \
+	extern void __illegally_sized_syscall_##name##_arg3 (void); \
+	if (sizeof (arg3) > 4) __illegally_sized_syscall_##name##_arg3 (); \
 	r5 = (long) (arg3)
 # define LOADARGS_4(name, arg1, arg2, arg3, arg4) \
 	LOADARGS_3(name, arg1, arg2, arg3); \
+	extern void __illegally_sized_syscall_##name##_arg4 (void); \
+	if (sizeof (arg4) > 4) __illegally_sized_syscall_##name##_arg4 (); \
 	r6 = (long) (arg4)
 # define LOADARGS_5(name, arg1, arg2, arg3, arg4, arg5) \
 	LOADARGS_4(name, arg1, arg2, arg3, arg4); \
+	extern void __illegally_sized_syscall_##name##_arg5 (void); \
+	if (sizeof (arg5) > 4) __illegally_sized_syscall_##name##_arg5 (); \
 	r7 = (long) (arg5)
 # define LOADARGS_6(name, arg1, arg2, arg3, arg4, arg5, arg6) \
 	LOADARGS_5(name, arg1, arg2, arg3, arg4, arg5); \
+	extern void __illegally_sized_syscall_##name##_arg6 (void); \
+	if (sizeof (arg6) > 4) __illegally_sized_syscall_##name##_arg6 (); \
 	r8 = (long) (arg6)
 
 # define ASM_INPUT_0 "0" (r0)
--- /dev/null	2002-11-11 17:51:46.000000000 -0700
+++ sysdeps/unix/sysv/linux/powerpc/powerpc32/ftruncate64.c	2003-01-05 10:48:57.000000000 -0700
@@ -0,0 +1,78 @@
+/* Copyright (C) 1997,1998,1999,2000,2001,2002 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 <sys/types.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include <sysdep.h>
+#include <sys/syscall.h>
+
+#include "kernel-features.h"
+
+#ifdef __NR_ftruncate64
+#ifndef __ASSUME_TRUNCATE64_SYSCALL
+/* The variable is shared between all wrappers around *truncate64 calls.  */
+extern int have_no_truncate64;
+#endif
+
+
+/* Truncate the file FD refers to to LENGTH bytes.  */
+int
+__ftruncate64 (fd, length)
+     int fd;
+     off64_t length;
+{
+#ifndef __ASSUME_TRUNCATE64_SYSCALL
+  if (! have_no_truncate64)
+#endif
+    {
+#ifndef __ASSUME_TRUNCATE64_SYSCALL
+      int saved_errno = errno;
+#endif
+      /* On PPC32 64bit values are aligned in odd/even register pairs.  */
+      int result = INLINE_SYSCALL (ftruncate64, 4, fd, 0,
+				   (long) (length >> 32),
+				   (long) length);
+
+#ifndef __ASSUME_TRUNCATE64_SYSCALL
+      if (result != -1 || errno != ENOSYS)
+#endif
+	return result;
+
+#ifndef __ASSUME_TRUNCATE64_SYSCALL
+      __set_errno (saved_errno);
+      have_no_truncate64 = 1;
+#endif
+    }
+
+#ifndef __ASSUME_TRUNCATE64_SYSCALL
+  if ((off_t) length != length)
+    {
+      __set_errno (EINVAL);
+      return -1;
+    }
+  return __ftruncate (fd, (off_t) length);
+#endif
+}
+weak_alias (__ftruncate64, ftruncate64)
+
+#else
+/* Use the generic implementation.  */
+# include <sysdeps/generic/ftruncate64.c>
+#endif
--- /dev/null	2002-11-11 17:51:46.000000000 -0700
+++ sysdeps/unix/sysv/linux/powerpc/powerpc32/truncate64.c	2003-01-05 10:48:37.000000000 -0700
@@ -0,0 +1,78 @@
+/* Copyright (C) 1997, 1998, 1999, 2000, 2002 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 <sys/types.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include <sysdep.h>
+#include <sys/syscall.h>
+#include <bp-checks.h>
+
+#include "kernel-features.h"
+
+#ifdef __NR_truncate64
+#ifndef __ASSUME_TRUNCATE64_SYSCALL
+/* The variable is shared between all wrappers around *truncate64 calls.  */
+int have_no_truncate64;
+#endif
+
+
+/* Truncate the file FD refers to to LENGTH bytes.  */
+int
+truncate64 (path, length)
+     const char *path;
+     off64_t length;
+{
+#ifndef __ASSUME_TRUNCATE64_SYSCALL
+  if (! have_no_truncate64)
+#endif
+    {
+#ifndef __ASSUME_TRUNCATE64_SYSCALL
+      int saved_errno = errno;
+#endif
+      /* On PPC32 64bit values are aligned in odd/even register pairs.  */
+      int result = INLINE_SYSCALL (truncate64, 4, CHECK_STRING (path), 0,
+				   (long) (length >> 32),
+				   (long) length);
+
+#ifndef __ASSUME_TRUNCATE64_SYSCALL
+      if (result != -1 || errno != ENOSYS)
+#endif
+	return result;
+
+#ifndef __ASSUME_TRUNCATE64_SYSCALL
+      __set_errno (saved_errno);
+      have_no_truncate64 = 1;
+#endif
+    }
+
+#ifndef __ASSUME_TRUNCATE64_SYSCALL
+  if ((off_t) length != length)
+    {
+      __set_errno (EINVAL);
+      return -1;
+    }
+  return truncate (path, (off_t) length);
+#endif
+}
+
+#else
+/* Use the generic implementation.  */
+# include <sysdeps/generic/truncate64.c>
+#endif
--- /dev/null	2002-11-11 17:51:46.000000000 -0700
+++ sysdeps/unix/sysv/linux/powerpc/powerpc32/pread.c	2003-01-05 10:36:10.000000000 -0700
@@ -0,0 +1,87 @@
+/* Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003
+   Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 <assert.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include <sysdep-cancel.h>
+#include <sys/syscall.h>
+#include <bp-checks.h>
+
+#include "kernel-features.h"
+
+#if defined __NR_pread || __ASSUME_PREAD_SYSCALL > 0
+
+# if __ASSUME_PREAD_SYSCALL == 0
+static ssize_t __emulate_pread (int fd, void *buf, size_t count,
+				off_t offset) internal_function;
+# endif
+
+
+ssize_t
+__libc_pread (fd, buf, count, offset)
+     int fd;
+     void *buf;
+     size_t count;
+     off_t offset;
+{
+  ssize_t result;
+
+  if (SINGLE_THREAD_P)
+    {
+      /* On PPC32 64bit values are aligned in odd/even register pairs.  */
+      result = INLINE_SYSCALL (pread, 6, fd, CHECK_N (buf, count), count,
+			       0, offset >> 31, offset);
+# if __ASSUME_PREAD_SYSCALL == 0
+      if (result == -1 && errno == ENOSYS)
+	/* No system call available.  Use the emulation.  */
+	result = __emulate_pread (fd, buf, count, offset);
+# endif
+
+      return result;
+    }
+  
+  int oldtype = LIBC_CANCEL_ASYNC ();
+
+  /* On PPC32 64bit values are aligned in odd/even register pairs.  */
+  result = INLINE_SYSCALL (pread, 6, fd, CHECK_N (buf, count), count,
+			       0, offset >> 31, offset);
+# if __ASSUME_PREAD_SYSCALL == 0
+  if (result == -1 && errno == ENOSYS)
+    /* No system call available.  Use the emulation.  */
+    result = __emulate_pread (fd, buf, count, offset);
+# endif
+
+  LIBC_CANCEL_RESET (oldtype);
+
+  return result;
+}
+
+strong_alias (__libc_pread, __pread)
+weak_alias (__libc_pread, pread)
+
+# define __libc_pread(fd, buf, count, offset) \
+     static internal_function __emulate_pread (fd, buf, count, offset)
+#endif
+
+#if __ASSUME_PREAD_SYSCALL == 0
+# include <sysdeps/posix/pread.c>
+#endif
--- /dev/null	2002-11-11 17:51:46.000000000 -0700
+++ sysdeps/unix/sysv/linux/powerpc/powerpc32/pread64.c	2003-01-05 10:43:41.000000000 -0700
@@ -0,0 +1,88 @@
+/* Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003
+   Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 <unistd.h>
+
+#include <sysdep-cancel.h>
+#include <sys/syscall.h>
+#include <bp-checks.h>
+
+#include "kernel-features.h"
+
+#if defined __NR_pread || __ASSUME_PREAD_SYSCALL > 0
+
+# if __ASSUME_PREAD_SYSCALL == 0
+static ssize_t __emulate_pread64 (int fd, void *buf, size_t count,
+				  off64_t offset) internal_function;
+# endif
+
+
+ssize_t
+__libc_pread64 (fd, buf, count, offset)
+     int fd;
+     void *buf;
+     size_t count;
+     off64_t offset;
+{
+  ssize_t result;
+
+  if (SINGLE_THREAD_P)
+    {
+      /* On PPC32 64bit values are aligned in odd/even register pairs.  */
+      result = INLINE_SYSCALL (pread, 6, fd, CHECK_N (buf, count), count,
+			       0, (long) (offset >> 32),
+			       (long) offset);
+# if __ASSUME_PREAD_SYSCALL == 0
+      if (result == -1 && errno == ENOSYS)
+	/* No system call available.  Use the emulation.  */
+	result = __emulate_pread64 (fd, buf, count, offset);
+# endif
+
+      return result;
+    }
+
+  int oldtype = LIBC_CANCEL_ASYNC ();
+
+  /* On PPC32 64bit values are aligned in odd/even register pairs.  */
+  result = INLINE_SYSCALL (pread, 6, fd, CHECK_N (buf, count), count,
+			   0, (long) (offset >> 32),
+			   (long) offset);
+# if __ASSUME_PREAD_SYSCALL == 0
+  if (result == -1 && errno == ENOSYS)
+    /* No system call available.  Use the emulation.  */
+    result = __emulate_pread64 (fd, buf, count, offset);
+# endif
+
+  LIBC_CANCEL_RESET (oldtype);
+
+  return result;
+}
+
+weak_alias (__libc_pread64, __pread64)
+weak_alias (__libc_pread64, pread64)
+
+# define __libc_pread64(fd, buf, count, offset) \
+     static internal_function __emulate_pread64 (fd, buf, count, offset)
+#endif
+
+# if __ASSUME_PREAD_SYSCALL == 0
+# include <sysdeps/posix/pread64.c>
+#endif
--- /dev/null	2002-11-11 17:51:46.000000000 -0700
+++ sysdeps/unix/sysv/linux/powerpc/powerpc32/pwrite.c	2003-01-05 12:39:35.000000000 -0700
@@ -0,0 +1,87 @@
+/* Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003
+   Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 <assert.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include <sysdep-cancel.h>
+#include <sys/syscall.h>
+#include <bp-checks.h>
+
+#include "kernel-features.h"
+
+#if defined __NR_pwrite || __ASSUME_PWRITE_SYSCALL > 0
+
+# if __ASSUME_PWRITE_SYSCALL == 0
+static ssize_t __emulate_pwrite (int fd, const void *buf, size_t count,
+				 off_t offset) internal_function;
+# endif
+
+
+ssize_t
+__libc_pwrite (fd, buf, count, offset)
+     int fd;
+     const void *buf;
+     size_t count;
+     off_t offset;
+{
+  ssize_t result;
+
+  if (SINGLE_THREAD_P)
+    {
+      /* On PPC32 64bit values are aligned in odd/even register pairs.  */
+      result = INLINE_SYSCALL (pwrite, 6, fd, CHECK_N (buf, count), count,
+			       0, offset >> 31, offset);
+# if __ASSUME_PWRITE_SYSCALL == 0
+      if (result == -1 && errno == ENOSYS)
+	/* No system call available.  Use the emulation.  */
+	result = __emulate_pwrite (fd, buf, count, offset);
+# endif
+
+      return result;
+    }
+
+  int oldtype = LIBC_CANCEL_ASYNC ();
+
+  /* On PPC32 64bit values are aligned in odd/even register pairs.  */
+  result = INLINE_SYSCALL (pwrite, 6, fd, CHECK_N (buf, count), count,
+			   0, offset >> 31, offset);
+# if __ASSUME_PWRITE_SYSCALL == 0
+  if (result == -1 && errno == ENOSYS)
+    /* No system call available.  Use the emulation.  */
+    result = __emulate_pwrite (fd, buf, count, offset);
+# endif
+
+  LIBC_CANCEL_RESET (oldtype);
+
+  return result;
+}
+
+strong_alias (__libc_pwrite, __pwrite)
+weak_alias (__libc_pwrite, pwrite)
+
+# define __libc_pwrite(fd, buf, count, offset) \
+     static internal_function __emulate_pwrite (fd, buf, count, offset)
+#endif
+
+#if __ASSUME_PWRITE_SYSCALL == 0
+# include <sysdeps/posix/pwrite.c>
+#endif
--- /dev/null	2002-11-11 17:51:46.000000000 -0700
+++ sysdeps/unix/sysv/linux/powerpc/powerpc32/pwrite64.c	2003-01-05 10:54:11.000000000 -0700
@@ -0,0 +1,89 @@
+/* Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003
+   Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 <unistd.h>
+
+#include <sysdep-cancel.h>
+#include <sys/syscall.h>
+#include <bp-checks.h>
+
+#include "kernel-features.h"
+
+#if defined __NR_pwrite || __ASSUME_PWRITE_SYSCALL > 0
+
+# if __ASSUME_PWRITE_SYSCALL == 0
+static ssize_t __emulate_pwrite64 (int fd, const void *buf, size_t count,
+				   off64_t offset) internal_function;
+# endif
+
+
+ssize_t
+__libc_pwrite64 (fd, buf, count, offset)
+     int fd;
+     const void *buf;
+     size_t count;
+     off64_t offset;
+{
+  ssize_t result;
+
+  if (SINGLE_THREAD_P)
+    {
+  /* On PPC32 64bit values are aligned in odd/even register pairs.  */
+      result = INLINE_SYSCALL (pwrite, 6, fd, CHECK_N (buf, count), count,
+			       0, (long) (offset >> 32),
+			       (long) offset);
+# if __ASSUME_PWRITE_SYSCALL == 0
+      if (result == -1 && errno == ENOSYS)
+	/* No system call available.  Use the emulation.  */
+	result = __emulate_pwrite64 (fd, buf, count, offset);
+# endif
+
+      return result;
+    }
+
+  int oldtype = LIBC_CANCEL_ASYNC ();
+
+  /* On PPC32 64bit values are aligned in odd/even register pairs.  */
+  result = INLINE_SYSCALL (pwrite, 6, fd, CHECK_N (buf, count), count,
+			   0, (long) (offset >> 32),
+			   (long) offset);
+# if __ASSUME_PWRITE_SYSCALL == 0
+  if (result == -1 && errno == ENOSYS)
+    /* No system call available.  Use the emulation.  */
+    result = __emulate_pwrite64 (fd, buf, count, offset);
+# endif
+
+  LIBC_CANCEL_RESET (oldtype);
+
+  return result;
+}
+
+weak_alias (__libc_pwrite64, __pwrite64)
+libc_hidden_weak (__pwrite64)
+weak_alias (__libc_pwrite64, pwrite64)
+
+# define __libc_pwrite64(fd, buf, count, offset) \
+     static internal_function __emulate_pwrite64 (fd, buf, count, offset)
+#endif
+
+#if __ASSUME_PWRITE_SYSCALL == 0
+# include <sysdeps/posix/pwrite64.c>
+#endif


More information about the Libc-alpha mailing list