diff options
author | Ulrich Drepper <drepper@redhat.com> | 2003-01-07 00:42:43 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2003-01-07 00:42:43 +0000 |
commit | 52f3d213311e34285c4809f043a5cf3a5876b897 (patch) | |
tree | b785902a0af0ab92aabf9e3f155ca1728a607fac | |
parent | a841816e175f7f7faeb5a019578b6b536ea336b6 (diff) | |
download | glibc-52f3d213311e34285c4809f043a5cf3a5876b897.tar.gz glibc-52f3d213311e34285c4809f043a5cf3a5876b897.tar.xz glibc-52f3d213311e34285c4809f043a5cf3a5876b897.zip |
Update.
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, 774 insertions, 37 deletions
diff --git a/ChangeLog b/ChangeLog index 6ba8460118..0c53dc75b4 100644 --- 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 diff --git a/linuxthreads/ChangeLog b/linuxthreads/ChangeLog index fc29ca771f..5c7b8181e6 100644 --- a/linuxthreads/ChangeLog +++ b/linuxthreads/ChangeLog @@ -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 diff --git a/linuxthreads/internals.h b/linuxthreads/internals.h index f4c7653659..36fdfe1bff 100644 --- a/linuxthreads/internals.h +++ b/linuxthreads/internals.h @@ -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 diff --git a/linuxthreads/pt-system.c b/linuxthreads/pt-system.c index 3a5f46c4f8..c3ed676f51 100644 --- a/linuxthreads/pt-system.c +++ b/linuxthreads/pt-system.c @@ -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 (); diff --git a/linuxthreads/signals.c b/linuxthreads/signals.c index d0087d9fab..e1f67ab0e8 100644 --- a/linuxthreads/signals.c +++ b/linuxthreads/signals.c @@ -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 index 0000000000..5f3709f742 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h @@ -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 diff --git a/linuxthreads/sysdeps/unix/sysv/linux/sigwait.c b/linuxthreads/sysdeps/unix/sysv/linux/sigwait.c index 460d3d56a7..c0cfb41753 100644 --- a/linuxthreads/sysdeps/unix/sysv/linux/sigwait.c +++ b/linuxthreads/sysdeps/unix/sysv/linux/sigwait.c @@ -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 (); diff --git a/linuxthreads/tst-cancel-wrappers.sh b/linuxthreads/tst-cancel-wrappers.sh index 9b739d2121..c9ed40b722 100644 --- a/linuxthreads/tst-cancel-wrappers.sh +++ b/linuxthreads/tst-cancel-wrappers.sh @@ -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 diff --git a/nptl/pt-system.c b/nptl/pt-system.c index f638a6ae32..b3b45ab938 100644 --- a/nptl/pt-system.c +++ b/nptl/pt-system.c @@ -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 (); diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h index e4851288fb..b298524245 100644 --- a/nptl/pthreadP.h +++ b/nptl/pthreadP.h @@ -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 diff --git a/nptl/tst-cancel-wrappers.sh b/nptl/tst-cancel-wrappers.sh index 5b3944bab7..4561c02ae8 100644 --- a/nptl/tst-cancel-wrappers.sh +++ b/nptl/tst-cancel-wrappers.sh @@ -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 diff --git a/sysdeps/generic/creat.c b/sysdeps/generic/creat.c index 3b1e93c409..462882415c 100644 --- a/sysdeps/generic/creat.c +++ b/sysdeps/generic/creat.c @@ -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 (); diff --git a/sysdeps/generic/sysdep-cancel.h b/sysdeps/generic/sysdep-cancel.h index 8422482819..f07b784f2e 100644 --- a/sysdeps/generic/sysdep-cancel.h +++ b/sysdeps/generic/sysdep-cancel.h @@ -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. */ diff --git a/sysdeps/powerpc/powerpc32/sysdep.h b/sysdeps/powerpc/powerpc32/sysdep.h index 9179746790..169abf72bf 100644 --- a/sysdeps/powerpc/powerpc32/sysdep.h +++ b/sysdeps/powerpc/powerpc32/sysdep.h @@ -116,7 +116,7 @@ DO_CALL (SYS_ify (syscall_name)); #define PSEUDO_RET \ - bnslr; \ + bnslr+; \ b JUMPTARGET(__syscall_error) #define ret PSEUDO_RET diff --git a/sysdeps/unix/sysv/linux/alpha/sysdep.h b/sysdeps/unix/sysv/linux/alpha/sysdep.h index 60b6eda4d3..53af4b7349 100644 --- a/sysdeps/unix/sysv/linux/alpha/sysdep.h +++ b/sysdeps/unix/sysv/linux/alpha/sysdep.h @@ -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. @@ -100,10 +101,10 @@ #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 @@ -117,7 +118,7 @@ \ _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, \ @@ -134,7 +135,7 @@ _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, \ @@ -153,7 +154,7 @@ _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, \ @@ -174,7 +175,7 @@ _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), \ @@ -197,7 +198,7 @@ _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), \ @@ -222,7 +223,7 @@ _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), \ @@ -249,7 +250,7 @@ _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 index 0000000000..e79d74cb75 --- /dev/null +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/ftruncate64.c @@ -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 index 0000000000..495c98ab97 --- /dev/null +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/pread.c @@ -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 index 0000000000..d4fe1eea2d --- /dev/null +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/pread64.c @@ -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 index 0000000000..3727fa7a42 --- /dev/null +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/pwrite.c @@ -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 index 0000000000..080c88cf29 --- /dev/null +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/pwrite64.c @@ -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 diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/socket.S b/sysdeps/unix/sysv/linux/powerpc/powerpc32/socket.S index dbdccefe4c..d406f08fdb 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/socket.S +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/socket.S @@ -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) diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/syscalls.list b/sysdeps/unix/sysv/linux/powerpc/powerpc32/syscalls.list index cfefbf0ece..13f0e9bba9 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/syscalls.list +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/syscalls.list @@ -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 diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h b/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h index d2cee1ffc7..2b3dd03b8d 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h @@ -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) diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/truncate64.c b/sysdeps/unix/sysv/linux/powerpc/powerpc32/truncate64.c new file mode 100644 index 0000000000..ce8ebc2a97 --- /dev/null +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/truncate64.c @@ -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 |