Update.
authorUlrich Drepper <drepper@redhat.com>
Tue, 7 Jan 2003 00:42:43 +0000 (00:42 +0000)
committerUlrich Drepper <drepper@redhat.com>
Tue, 7 Jan 2003 00:42:43 +0000 (00:42 +0000)
2003-01-06  Franz Sirl  <Franz.Sirl-kernel@lauterbach.com>

* 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.

2003-01-06  Jakub Jelinek  <jakub@redhat.com>

* sysdeps/generic/sysdep-cancel.h (LIBC_CANCEL_HANDLED): Define.
* sysdeps/generic/creat.c: Include sysdep-cancel.h.
(LIBC_CANCEL_HANDLED): Add.

* sysdeps/unix/sysv/linux/alpha/sysdep.h
(inline_syscall_r0_constraint): Rename to...
(inline_syscall_r0_out_constraint): ... this.  Add =.
(inline_syscall[0-6]): Use inline_syscall_r0_out_constraint.

24 files changed:
ChangeLog
linuxthreads/ChangeLog
linuxthreads/internals.h
linuxthreads/pt-system.c
linuxthreads/signals.c
linuxthreads/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h [new file with mode: 0644]
linuxthreads/sysdeps/unix/sysv/linux/sigwait.c
linuxthreads/tst-cancel-wrappers.sh
nptl/pt-system.c
nptl/pthreadP.h
nptl/tst-cancel-wrappers.sh
sysdeps/generic/creat.c
sysdeps/generic/sysdep-cancel.h
sysdeps/powerpc/powerpc32/sysdep.h
sysdeps/unix/sysv/linux/alpha/sysdep.h
sysdeps/unix/sysv/linux/powerpc/powerpc32/ftruncate64.c [new file with mode: 0644]
sysdeps/unix/sysv/linux/powerpc/powerpc32/pread.c [new file with mode: 0644]
sysdeps/unix/sysv/linux/powerpc/powerpc32/pread64.c [new file with mode: 0644]
sysdeps/unix/sysv/linux/powerpc/powerpc32/pwrite.c [new file with mode: 0644]
sysdeps/unix/sysv/linux/powerpc/powerpc32/pwrite64.c [new file with mode: 0644]
sysdeps/unix/sysv/linux/powerpc/powerpc32/socket.S
sysdeps/unix/sysv/linux/powerpc/powerpc32/syscalls.list
sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h
sysdeps/unix/sysv/linux/powerpc/powerpc32/truncate64.c [new file with mode: 0644]

index 6ba8460..0c53dc7 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,31 @@
+2003-01-06  Franz Sirl  <Franz.Sirl-kernel@lauterbach.com>
+
+       * 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.
+
+2003-01-06  Jakub Jelinek  <jakub@redhat.com>
+
+       * sysdeps/generic/sysdep-cancel.h (LIBC_CANCEL_HANDLED): Define.
+       * sysdeps/generic/creat.c: Include sysdep-cancel.h.
+       (LIBC_CANCEL_HANDLED): Add.
+
+       * sysdeps/unix/sysv/linux/alpha/sysdep.h
+       (inline_syscall_r0_constraint): Rename to...
+       (inline_syscall_r0_out_constraint): ... this.  Add =.
+       (inline_syscall[0-6]): Use inline_syscall_r0_out_constraint.
+
 2003-01-06  Andreas Schwab  <schwab@suse.de>
 
        * sysdeps/m68k/dl-machine.h (elf_machine_runtime_setup): Make
index fc29ca7..5c7b818 100644 (file)
@@ -1,3 +1,17 @@
+2003-01-06  Philip Blundell  <philb@gnu.org>
+
+       * sysdeps/unix/sysv/linux/arm/sysdep-cancel.h: New file.
+
+2003-01-06  Jakub Jelinek  <jakub@redhat.com>
+
+       * internals.h (LIBC_CANCEL_HANDLED): Define.
+       * sysdeps/unix/sysv/linux/sigwait.c (LIBC_CANCEL_HANDLED): Add.
+       * signals.c (LIBC_CANCEL_HANDLED): Add.
+       * pt-system.c (LIBC_CANCEL_HANDLED): Add.
+       * tst-cancel-wrappers.sh: Remove all exceptions.
+
+       * sysdeps/unix/sysv/linux/alpha/Makefile: New file.
+
 2003-01-05  Andreas Schwab  <schwab@suse.de>
 
        * sysdeps/m68k/Makefile: New file, use -fPIC for nonshared
index f4c7653..36fdfe1 100644 (file)
@@ -475,14 +475,21 @@ extern pid_t __pthread_fork (struct fork_block *b) attribute_hidden;
   __libc_enable_asynccancel ()
 # define LIBC_CANCEL_RESET(oldtype) \
   __libc_disable_asynccancel (oldtype)
+# define LIBC_CANCEL_HANDLED() \
+  __asm (".globl " __SYMBOL_PREFIX "__libc_enable_asynccancel"); \
+  __asm (".globl " __SYMBOL_PREFIX "__libc_disable_asynccancel")
 #elif defined NOT_IN_libc && defined IS_IN_libpthread
 # define LIBC_CANCEL_ASYNC() \
   __pthread_enable_asynccancel ()
 # define LIBC_CANCEL_RESET(oldtype) \
   __pthread_disable_asynccancel (oldtype)
+# define LIBC_CANCEL_HANDLED() \
+  __asm (".globl " __SYMBOL_PREFIX "__pthread_enable_asynccancel"); \
+  __asm (".globl " __SYMBOL_PREFIX "__pthread_disable_asynccancel")
 #else
 # define LIBC_CANCEL_ASYNC()    0 /* Just a dummy value.  */
 # define LIBC_CANCEL_RESET(val) ((void)(val)) /* Nothing, but evaluate it.  */
+# define LIBC_CANCEL_HANDLED() /* Nothing.  */
 #endif
 
 /* Data type shared with libc.  The libc uses it to pass on calls to
index 3a5f46c..c3ed676 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Jakub Jelinek <jakub@redhat.com>, 2002.
 
@@ -27,3 +27,6 @@ system (const char *line)
 {
   return __libc_system (line);
 }
+
+/* __libc_system in libc.so handles cancellation.  */
+LIBC_CANCEL_HANDLED ();
index d0087d9..e1f67ab 100644 (file)
@@ -195,3 +195,6 @@ int __pthread_raise (int sig)
 #ifdef SHARED
 strong_alias (__pthread_raise, raise)
 #endif
+
+/* This files handles cancellation internally.  */
+LIBC_CANCEL_HANDLED ();
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h b/linuxthreads/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h
new file mode 100644 (file)
index 0000000..5f3709f
--- /dev/null
@@ -0,0 +1,127 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Phil Blundell <pb@nexus.co.uk>, 2003.
+
+   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 <sysdep.h>
+#ifndef __ASSEMBLER__
+# include <linuxthreads/internals.h>
+#endif
+
+#if !defined NOT_IN_libc || defined IS_IN_libpthread
+
+# undef PSEUDO_RET
+# define PSEUDO_RET                                                    \
+    ldrcc pc, [sp], $4;                                                        \
+    b PLTJMP(SYSCALL_ERROR)
+
+# undef PSEUDO
+# define PSEUDO(name, syscall_name, args)                              \
+  .section ".text";                                                    \
+    PSEUDO_PROLOGUE;                                                   \
+  ENTRY (name)                                                         \
+    SINGLE_THREAD_P;                                                   \
+    bne .Lpseudo_cancel;                                               \
+    DO_CALL (syscall_name, args);                                      \
+    cmn r0, $4096;                                                     \
+    PSEUDO_RET_MOV;                                                    \
+  .Lpseudo_cancel:                                                     \
+    MAYBE_SAVE_LR;                                                     \
+    DOCARGS_##args;    /* save syscall args around CENABLE.  */        \
+    CENABLE;                                                           \
+    mov ip, r0;                /* put mask in safe place.  */                  \
+    UNDOCARGS_##args;  /* restore syscall args.  */                    \
+    swi SYS_ify (syscall_name);        /* do the call.  */                     \
+    str r0, [sp, $-4]!; /* save syscall return value.  */              \
+    mov r0, ip;                /* get mask back.  */                           \
+    CDISABLE;                                                          \
+    ldr r0, [sp], $4;  /* retrieve return value.  */                   \
+    UNDOC2ARGS_##args; /* fix register damage.  */                     \
+    cmn r0, $4096;
+
+# define DOCARGS_0
+# define UNDOCARGS_0
+# define UNDOC2ARGS_0
+
+# define DOCARGS_1     str r0, [sp, #-4]!;
+# define UNDOCARGS_1   ldr r0, [sp], #4;
+# define UNDOC2ARGS_1
+
+# define DOCARGS_2     str r1, [sp, #-4]!; str r0, [sp, #-4]!;
+# define UNDOCARGS_2   ldr r0, [sp], #4; ldr r1, [sp], #4;
+# define UNDOC2ARGS_2
+
+# define DOCARGS_3     str r2, [sp, #-4]!; str r1, [sp, #-4]!; str r0, [sp, #-4]!;
+# define UNDOCARGS_3   ldr r0, [sp], #4; ldr r1, [sp], #4; ldr r2, [sp], #4
+# define UNDOC2ARGS_3
+
+# define DOCARGS_4     stmfd sp!, {r0-r3}
+# define UNDOCARGS_4   ldmfd sp!, {r0-r3}
+# define UNDOC2ARGS_4
+
+# define DOCARGS_5     stmfd sp!, {r0-r3}
+# define UNDOCARGS_5   str r4, [sp, #-4]!; ldmfd sp, {r0-r4}
+# define UNDOC2ARGS_5   ldr r4, [sp], #20
+
+# ifdef IS_IN_libpthread
+#  define CENABLE      bl PLTJMP(__pthread_enable_asynccancel)
+#  define CDISABLE     bl PLTJMP(__pthread_disable_asynccancel)
+#  define __local_multiple_threads __pthread_multiple_threads
+# else
+#  define CENABLE      bl PLTJMP(__libc_enable_asynccancel)
+#  define CDISABLE     bl PLTJMP(__libc_disable_asynccancel)
+#  define __local_multiple_threads __libc_multiple_threads
+# endif
+
+# ifndef __ASSEMBLER__
+extern int __local_multiple_threads attribute_hidden;
+#  define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1)
+# else
+#  if !defined PIC
+#   define SINGLE_THREAD_P                                             \
+  ldr ip, =__local_multiple_threads;                                   \
+  ldr ip, [ip];                                                                \
+  teq ip, #0;
+#   define MAYBE_SAVE_LR                                               \
+  str lr, [sp, $-4]!;
+#   define PSEUDO_RET_MOV                                              \
+  RETINSTR(movcc, pc, lr);                                             \
+  b PLTJMP(SYSCALL_ERROR)
+#   define PSEUDO_PROLOGUE
+#  else
+#   define SINGLE_THREAD_P                                             \
+  str lr, [sp, $-4]!;                                                  \
+  ldr ip, 1b;                                                          \
+  ldr lr, 2b;                                                          \
+3:                                                                     \
+  add ip, pc, ip;                                                      \
+  ldr ip, [ip, lr];                                                    \
+  teq ip, #0;
+#   define PSEUDO_PROLOGUE                                             \
+  1:  .word _GLOBAL_OFFSET_TABLE_ - 3f - 8;                            \
+  2:  .word __local_multiple_threads(GOTOFF);
+#   define MAYBE_SAVE_LR       /* lr already saved */
+#   define PSEUDO_RET_MOV PSEUDO_RET
+#  endif
+# endif
+
+#elif !defined __ASSEMBLER__
+
+/* This code should never be used but we define it anyhow.  */
+# define SINGLE_THREAD_P (1)
+
+#endif
index 460d3d5..c0cfb41 100644 (file)
@@ -82,3 +82,6 @@ __sigwait (set, sig)
 libc_hidden_def (__sigwait)
 weak_alias (__sigwait, sigwait)
 strong_alias (__sigwait, __libc_sigwait)
+
+/* Cancellation is handled in __pthread_sigwait.  */
+LIBC_CANCEL_HANDLED ();
index 9b739d2..c9ed40b 100644 (file)
@@ -67,13 +67,7 @@ C["__xpg_sigpause"]=1
 /:$/ {
   if (seen)
     {
-      # signals.c and sigwait.c in linuxthreads do the cancellation checks
-      # not using *_{enable,disable}_asynccancel.
-      # Similarly pt-system.o* is allowed to call __libc_system directly.
-      if ((!seen_enable || !seen_disable) \
-         && !(object ~ /^signals.o/) \
-         && !(object ~ /^sigwait.o/) \
-         && !(object ~ /^pt-system.o/))
+      if (!seen_enable || !seen_disable)
        {
          printf "in '$1'(%s) %s'\''s cancellation missing\n", object, seen
          ret = 1
index f638a6a..b3b45ab 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -28,3 +28,6 @@ system (const char *line)
 {
   return __libc_system (line);
 }
+
+/* __libc_system in libc.so handles cancellation.  */
+LIBC_CANCEL_HANDLED ();
index e485128..b298524 100644 (file)
@@ -92,12 +92,19 @@ extern int __pthread_debug attribute_hidden;
 /* Same as CANCEL_RESET, but for use in libc.so.  */
 # define LIBC_CANCEL_RESET(oldtype) \
   __libc_disable_asynccancel (oldtype)
+# define LIBC_CANCEL_HANDLED() \
+  __asm (".globl " __SYMBOL_PREFIX "__libc_enable_asynccancel"); \
+  __asm (".globl " __SYMBOL_PREFIX "__libc_disable_asynccancel")
 #elif defined NOT_IN_libc && defined IS_IN_libpthread
 # define LIBC_CANCEL_ASYNC() CANCEL_ASYNC ()
 # define LIBC_CANCEL_RESET(val) CANCEL_RESET (val)
+# define LIBC_CANCEL_HANDLED() \
+  __asm (".globl " __SYMBOL_PREFIX "__pthread_enable_asynccancel"); \
+  __asm (".globl " __SYMBOL_PREFIX "__pthread_disable_asynccancel")
 #else
 # define LIBC_CANCEL_ASYNC()   0 /* Just a dummy value.  */
 # define LIBC_CANCEL_RESET(val)        ((void)(val)) /* Nothing, but evaluate it.  */
+# define LIBC_CANCEL_HANDLED() /* Nothing.  */
 #endif
 
 
index 5b3944b..4561c02 100644 (file)
@@ -67,8 +67,7 @@ C["__xpg_sigpause"]=1
 /:$/ {
   if (seen)
     {
-      # pt-system.o* in NPTL calls __libc_system directly.
-      if ((!seen_enable || !seen_disable) && !(object ~ /^pt-system.o/))
+      if (!seen_enable || !seen_disable)
        {
          printf "in '$1'(%s) %s'\''s cancellation missing\n", object, seen
          ret = 1
index 3b1e93c..4628824 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 1996, 1997 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 1996, 1997, 2003 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
@@ -18,6 +18,7 @@
 
 #include <fcntl.h>
 #include <sys/types.h>
+#include <sysdep-cancel.h>
 
 #undef creat
 
@@ -30,3 +31,6 @@ __libc_creat (file, mode)
   return __open (file, O_WRONLY|O_CREAT|O_TRUNC, mode);
 }
 weak_alias (__libc_creat, creat)
+
+/* __open handles cancellation.  */
+LIBC_CANCEL_HANDLED ();
index 8422482..f07b784 100644 (file)
@@ -4,3 +4,4 @@
 #define SINGLE_THREAD_P (1)
 #define LIBC_CANCEL_ASYNC()    0 /* Just a dummy value.  */
 #define LIBC_CANCEL_RESET(val) ((void)(val)) /* Nothing, but evaluate it.  */
+#define LIBC_CANCEL_HANDLED()  /* Nothing.  */
index 9179746..169abf7 100644 (file)
     DO_CALL (SYS_ify (syscall_name));
 
 #define PSEUDO_RET                                                           \
-    bnslr                                                                  \
+    bnslr+;                                                                  \
     b JUMPTARGET(__syscall_error)
 #define ret PSEUDO_RET
 
index 60b6eda..53af4b7 100644 (file)
@@ -1,4 +1,5 @@
-/* Copyright (C) 1992, 1993, 1995, 1996, 1997, 2002 Free Software Foundation, Inc.
+/* Copyright (C) 1992, 1993, 1995, 1996, 1997, 2002, 2003
+   Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper, <drepper@gnu.ai.mit.edu>, August 1995.
 
 
 #ifdef USE_TLS
 #define inline_syscall_r0_asm
-#define inline_syscall_r0_constraint   "v"
+#define inline_syscall_r0_out_constraint       "=v"
 #else
-#define inline_syscall_r0_asm          __asm__("$0")
-#define inline_syscall_r0_constraint   "r"
+#define inline_syscall_r0_asm                  __asm__("$0")
+#define inline_syscall_r0_out_constraint       "=r"
 #endif
 
 /* It is moderately important optimization-wise to limit the lifetime
                                                                \
        _sc_0 = __NR_##name;                                    \
        __asm__("callsys # %0 %1 <= %2"                         \
-               : "=" inline_syscall_r0_constraint (_sc_0),     \
+               : inline_syscall_r0_out_constraint (_sc_0),     \
                  "=r"(_sc_19)                                  \
                : "0"(_sc_0)                                    \
                : inline_syscall_clobbers,                      \
        _sc_0 = __NR_##name;                                    \
        _sc_16 = (long) (arg1);                                 \
        __asm__("callsys # %0 %1 <= %2 %3"                      \
-               : "=" inline_syscall_r0_constraint (_sc_0),     \
+               : inline_syscall_r0_out_constraint (_sc_0),     \
                  "=r"(_sc_19), "=r"(_sc_16)                    \
                : "0"(_sc_0), "2"(_sc_16)                       \
                : inline_syscall_clobbers,                      \
        _sc_16 = (long) (arg1);                                 \
        _sc_17 = (long) (arg2);                                 \
        __asm__("callsys # %0 %1 <= %2 %3 %4"                   \
-               : "=" inline_syscall_r0_constraint (_sc_0),     \
+               : inline_syscall_r0_out_constraint (_sc_0),     \
                  "=r"(_sc_19), "=r"(_sc_16), "=r"(_sc_17)      \
                : "0"(_sc_0), "2"(_sc_16), "3"(_sc_17)          \
                : inline_syscall_clobbers,                      \
        _sc_17 = (long) (arg2);                                 \
        _sc_18 = (long) (arg3);                                 \
        __asm__("callsys # %0 %1 <= %2 %3 %4 %5"                \
-               : "=" inline_syscall_r0_constraint (_sc_0),     \
+               : inline_syscall_r0_out_constraint (_sc_0),     \
                  "=r"(_sc_19), "=r"(_sc_16), "=r"(_sc_17),     \
                  "=r"(_sc_18)                                  \
                : "0"(_sc_0), "2"(_sc_16), "3"(_sc_17),         \
        _sc_18 = (long) (arg3);                                 \
        _sc_19 = (long) (arg4);                                 \
        __asm__("callsys # %0 %1 <= %2 %3 %4 %5 %6"             \
-               : "=" inline_syscall_r0_constraint (_sc_0),     \
+               : inline_syscall_r0_out_constraint (_sc_0),     \
                  "=r"(_sc_19), "=r"(_sc_16), "=r"(_sc_17),     \
                  "=r"(_sc_18)                                  \
                : "0"(_sc_0), "2"(_sc_16), "3"(_sc_17),         \
        _sc_19 = (long) (arg4);                                 \
        _sc_20 = (long) (arg5);                                 \
        __asm__("callsys # %0 %1 <= %2 %3 %4 %5 %6 %7"          \
-               : "=" inline_syscall_r0_constraint (_sc_0),     \
+               : inline_syscall_r0_out_constraint (_sc_0),     \
                  "=r"(_sc_19), "=r"(_sc_16), "=r"(_sc_17),     \
                  "=r"(_sc_18), "=r"(_sc_20)                    \
                : "0"(_sc_0), "2"(_sc_16), "3"(_sc_17),         \
        _sc_20 = (long) (arg5);                                 \
        _sc_21 = (long) (arg6);                                 \
        __asm__("callsys # %0 %1 <= %2 %3 %4 %5 %6 %7 %8"       \
-               : "=" inline_syscall_r0_constraint (_sc_0),     \
+               : inline_syscall_r0_out_constraint (_sc_0),     \
                  "=r"(_sc_19) "=r"(_sc_16), "=r"(_sc_17),      \
                  "=r"(_sc_18), "=r"(_sc_20), "=r"(_sc_21)      \
                : "0"(_sc_0), "2"(_sc_16), "3"(_sc_17),         \
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/ftruncate64.c b/sysdeps/unix/sysv/linux/powerpc/powerpc32/ftruncate64.c
new file mode 100644 (file)
index 0000000..e79d74c
--- /dev/null
@@ -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
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/pread.c b/sysdeps/unix/sysv/linux/powerpc/powerpc32/pread.c
new file mode 100644 (file)
index 0000000..495c98a
--- /dev/null
@@ -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
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/pread64.c b/sysdeps/unix/sysv/linux/powerpc/powerpc32/pread64.c
new file mode 100644 (file)
index 0000000..d4fe1ee
--- /dev/null
@@ -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
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/pwrite.c b/sysdeps/unix/sysv/linux/powerpc/powerpc32/pwrite.c
new file mode 100644 (file)
index 0000000..3727fa7
--- /dev/null
@@ -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
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/pwrite64.c b/sysdeps/unix/sysv/linux/powerpc/powerpc32/pwrite64.c
new file mode 100644 (file)
index 0000000..080c88c
--- /dev/null
@@ -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
index dbdccef..d406f08 100644 (file)
@@ -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 cfefbf0..13f0e9b 100644 (file)
@@ -9,9 +9,3 @@ rt_sigsuspend   -       rt_sigsuspend   i:pi    __syscall_rt_sigsuspend
 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 d2cee1f..2b3dd03 100644 (file)
@@ -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");                                  \
     (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)
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/truncate64.c b/sysdeps/unix/sysv/linux/powerpc/powerpc32/truncate64.c
new file mode 100644 (file)
index 0000000..ce8ebc2
--- /dev/null
@@ -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