diff --git a/ChangeLog.hppa b/ChangeLog.hppa index 1f90c8dc2a..b0ccb9872d 100644 --- a/ChangeLog.hppa +++ b/ChangeLog.hppa @@ -1,3 +1,33 @@ +2006-09-07 Carlos O'Donell + + * sysdeps/hppa/dl-machine.h (elf_machine_fixup_plt): Remove + lvalue cast. + * sysdeps/hppa/dl-trampoline.S (_dl_fixup): Correct stack usage. + (_dl_runtime_profile): LA fixups. + * sysdeps/unix/sysv/linux/hppa/clone.S: Correct stack usage. Return + -1 on error. Use branch and link for error handler funciton. + * sysdeps/unix/sysv/linux/hppa/sysdep.h: Correct stack usage. + Avoid register shuffling. + * sysdeps/unix/sysv/linux/hppa/bits/atomic.h (ASM_EAGAIN): Define + as -EAGAIN. + * sysdeps/unix/sysv/linux/hppa/bits/mman.h: Adjust definitions to + match required standards. + * sysdeps/unix/sysv/linux/hppa/nptl/lowlevellock.h + (lll_futex_wait): Return __ret. + (lll_futex_timed_wait): Likewise. + (lll_futex_wake): Likewise. + (lll_futex_requeue): Likewise. + * sysdeps/unix/sysv/linux/hppa/nptl/pt-vfork.S: Correct stack + usage and adjust error return. + * sysdeps/unix/sysv/linux/hppa/nptl/sysdep-cancel.h: Adjust + stack usage for gdb, and avoid extra register loads. + * sysdeps/unix/sysv/linux/hppa/nptl/unwind-forcedunwind.c: Copy + nptl/sysdeps/pthread/unwind-forcedunwind.c. + (LIBGCC_SO): Define and use. + * sysdeps/unix/sysv/linux/hppa/nptl/unwind-resume.c: Copy + nptl/sysdeps/pthread/unwind-resume.c. + (LIBGCC_SO): Define and use. + 2006-08-13 Carlos O'Donell * sysdeps/unix/sysv/linux/hppa/nptl/lowlevellock.h (FUTEX_LOCK_PI, diff --git a/sysdeps/hppa/dl-machine.h b/sysdeps/hppa/dl-machine.h index dd5a28190b..67536c37d7 100644 --- a/sysdeps/hppa/dl-machine.h +++ b/sysdeps/hppa/dl-machine.h @@ -123,12 +123,13 @@ elf_machine_fixup_plt (struct link_map *map, lookup_t t, const Elf32_Rela *reloc, Elf32_Addr *reloc_addr, struct fdesc value) { + volatile Elf32_Addr *rfdesc = reloc_addr; /* map is the link_map for the caller, t is the link_map for the object being called */ - reloc_addr[1] = value.gp; + rfdesc[1] = value.gp; /* Need to ensure that the gp is visible before the code entry point is updated */ - ((volatile Elf32_Addr *) reloc_addr)[0] = value.ip; + rfdesc[0] = value.ip; return value; } diff --git a/sysdeps/hppa/dl-trampoline.S b/sysdeps/hppa/dl-trampoline.S index c476138ebe..e0d3b9b108 100644 --- a/sysdeps/hppa/dl-trampoline.S +++ b/sysdeps/hppa/dl-trampoline.S @@ -1,5 +1,5 @@ /* PLT trampolines. hppa version. - Copyright (C) 2005 Free Software Foundation, Inc. + Copyright (C) 2005, 2006 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 @@ -21,9 +21,9 @@ /* This code gets called via the .plt stub, and is used in dl-runtime.c to call the `_dl_fixup' function and then redirect - to the address it returns. `_dl_fixup' takes two - arguments, however `_dl_profile_fixup' takes a number of - parameters for use with library auditing (LA). + to the address it returns. `_dl_fixup' takes two arguments, however + `_dl_profile_fixup' takes a number of parameters for use with + library auditing (LA). WARNING: This template is also used by gcc's __cffc, and expects that the "bl" for _dl_runtime_resolve exist at a particular offset. @@ -34,43 +34,46 @@ Enter with r19 = reloc offset, r20 = got-8, r21 = fixup ltp. */ - /* FAKE bl to provide gcc's __cffc with fixup loc. */ + /* RELOCATION MARKER: bl to provide gcc's __cffc with fixup loc. */ .text + /* THIS CODE DOES NOT EXECUTE */ bl _dl_fixup, %r2 .text - .align 4 .global _dl_runtime_resolve .type _dl_runtime_resolve,@function + cfi_startproc + .align 4 _dl_runtime_resolve: .PROC .CALLINFO FRAME=128,CALLS,SAVE_RP,ENTRY_GR=3 .ENTRY /* SAVE_RP says we do */ - stw %rp, -20(%sp) + stw %rp, -20(%sp) /* Save static link register */ stw %r29,-16(%sp) - /* Save argument registers in the call stack frame. */ + /* Save argument registers */ stw %r26,-36(%sp) stw %r25,-40(%sp) stw %r24,-44(%sp) stw %r23,-48(%sp) /* Build a call frame, and save structure pointer. */ - copy %sp, %r26 /* Copy previous sp */ + copy %sp, %r1 /* Copy previous sp */ /* Save function result address (on entry) */ stwm %r28,128(%sp) - - /* Save floating point argument registers */ - ldo -56(%sp),%r26 - fstd,ma %fr4,-8(%r26) - fstd,ma %fr5,-8(%r26) - fstd,ma %fr6,-8(%r26) - fstd %fr7,0(%r26) - /* Fillin some frame info to follow ABI */ + stw %r1,-4(%sp) /* Previous sp */ stw %r21,-32(%sp) /* PIC register value */ - stw %r26,-4(%sp) /* Previous sp */ + + /* Save input floating point registers. This must be done + in the new frame since the previous frame doesn't have + enough space */ + ldo -56(%sp),%r1 + fstd,ma %fr4,-8(%r1) + fstd,ma %fr5,-8(%r1) + fstd,ma %fr6,-8(%r1) + fstd,ma %fr7,-8(%r1) /* Set up args to fixup func, needs only two arguments */ ldw 8+4(%r20),%r26 /* (1) got[1] == struct link_map */ @@ -81,15 +84,15 @@ _dl_runtime_resolve: copy %r21,%r19 /* set fixup func ltp */ /* Load up the returned func descriptor */ - copy %ret0, %r22 - copy %ret1, %r19 + copy %r28, %r22 + copy %r29, %r19 /* Reload arguments fp args */ - ldo -80(%sp),%r26 - fldd,ma 8(%r26),%fr7 - fldd,ma 8(%r26),%fr6 - fldd,ma 8(%r26),%fr5 - fldd 0(%r26),%fr4 + ldo -56(%sp),%r1 + fldd,ma -8(%r1),%fr4 + fldd,ma -8(%r1),%fr5 + fldd,ma -8(%r1),%fr6 + fldd,ma -8(%r1),%fr7 /* Adjust sp, and restore function result address*/ ldwm -128(%sp),%r28 @@ -107,91 +110,179 @@ _dl_runtime_resolve: ldw -20(%sp),%rp .EXIT .PROCEND + cfi_endproc .size _dl_runtime_resolve, . - _dl_runtime_resolve - - /* FIXME: - Need to largely rewrite the bottom half of - this code in order to save and restore the - LA struct from the stack along with - interpreted parameters. - */ .text - .align 4 .global _dl_runtime_profile .type _dl_runtime_profile,@function + cfi_startproc + .align 4 _dl_runtime_profile: .PROC - .CALLINFO FRAME=128,CALLS,SAVE_RP,ENTRY_GR=3 + .CALLINFO FRAME=192,CALLS,SAVE_RP,ENTRY_GR=3 .ENTRY /* SAVE_RP says we do */ - stw %rp, -20(%sp) - + stw %rp, -20(%sp) /* Save static link register */ stw %r29,-16(%sp) - /* Save argument registers in the call stack frame. */ - stw %r26,-36(%sp) - stw %r25,-40(%sp) - stw %r24,-44(%sp) - stw %r23,-48(%sp) /* Build a call frame, and save structure pointer. */ - copy %sp, %r26 /* Copy previous sp */ + copy %sp, %r1 /* Copy previous sp */ /* Save function result address (on entry) */ - stwm %r28,128(%sp) - - /* Save floating point argument registers */ - ldo -56(%sp),%r26 - fstd,ma %fr4,-8(%r26) - fstd,ma %fr5,-8(%r26) - fstd,ma %fr6,-8(%r26) - fstd %fr7,0(%r26) - + stwm %r28,192(%sp) /* Fillin some frame info to follow ABI */ + stw %r1,-4(%sp) /* Previous sp */ stw %r21,-32(%sp) /* PIC register value */ - stw %r26,-4(%sp) /* Previous sp */ + + /* Create La_hppa_retval */ + /* -140, lrv_r28 + -136, lrv_r29 + -132, 4 byte pad + -128, lr_fr4 (8 bytes) */ + + /* Create save space for _dl_profile_fixup arguments + -120, Saved reloc offset + -116, Saved struct link_map + -112, *framesizep */ + + /* Create La_hppa_regs */ + /* 32-bit registers */ + stw %r26,-108(%sp) + stw %r25,-104(%sp) + stw %r24,-100(%sp) + stw %r23,-96(%sp) + /* -92, 4 byte pad */ + /* 64-bit floating point registers */ + ldo -88(%sp),%r1 + fstd,ma %fr4,8(%r1) + fstd,ma %fr5,8(%r1) + fstd,ma %fr6,8(%r1) + fstd,ma %fr7,8(%r1) + /* 32-bit stack pointer and return register */ + stw %sp,-56(%sp) + stw %r2,-52(%sp) + /* Set up args to fixup func, needs five arguments */ ldw 8+4(%r20),%r26 /* (1) got[1] == struct link_map */ + stw %r26,-116(%sp) /* Save struct link_map */ copy %r19,%r25 /* (2) reloc offset */ + stw %r25,-120(%sp) /* Save reloc offset */ copy %rp,%r24 /* (3) profile_fixup needs rp */ - copy %r0,%r23 /* (4) regs */ - ldo -56(%sp), %r1 + ldo -56(%sp),%r23 /* (4) La_hppa_regs */ + ldo -112(%sp), %r1 stw %r1, -52(%sp) /* (5) long int *framesizep */ /* Call the real address resolver. */ bl _dl_profile_fixup,%rp copy %r21,%r19 /* set fixup func ltp */ - /* Load up the returned func descriptor */ - copy %ret0, %r22 - copy %ret1, %r19 + /* Load up the returned function descriptor */ + copy %r28, %r22 + copy %r29, %r19 - /* Reload arguments fp args */ - ldo -80(%sp),%r26 - fldd,ma 8(%r26),%fr7 - fldd,ma 8(%r26),%fr6 - fldd,ma 8(%r26),%fr5 - fldd 0(%r26),%fr4 + /* Restore gr/fr/sp/rp */ + ldw -108(%sp),%r26 + ldw -104(%sp),%r25 + ldw -100(%sp),%r24 + ldw -96(%sp),%r23 + /* -92, 4 byte pad, skip */ + ldo -88(%sp),%r1 + fldd,ma 8(%r1),%fr4 + fldd,ma 8(%r1),%fr5 + fldd,ma 8(%r1),%fr6 + fldd,ma 8(%r1),%fr7 + ldw -52(%sp),%rp + + /* Reload static link register -(192+16) without adjusting stack */ + ldw -208(%sp),%r29 + + /* *framesizep is >= 0 if we have to run pltexit */ + ldw -112(%sp),%r28 + cmpb,>>=,N %r0,%r28,L(cpe) /* Adjust sp, and restore function result address*/ - ldwm -128(%sp),%r28 - - /* Reload static link register */ - ldw -16(%sp),%r29 - /* Reload general args */ - ldw -36(%sp),%r26 - ldw -40(%sp),%r25 - ldw -44(%sp),%r24 - ldw -48(%sp),%r23 - + ldwm -192(%sp),%r28 /* Jump to new function, but return to previous function */ bv %r0(%r22) ldw -20(%sp),%rp + /* NO RETURN */ + +L(nf): + /* Call the returned function descriptor */ + bv %r0(%r22) + nop + b,n L(cont) + +L(cpe): + /* We are going to call the resolved function, but we have a + stack frame in the middle. We use the value of framesize to + guess how much extra frame we need, and how much frame to + copy forward. */ + + /* Round to nearest multiple of 64 */ + addi 63, %r28, %r28 + depi 0, 27, 6, %r28 + + /* Calcualte start of stack copy */ + ldo -192(%sp),%r2 + + /* Increate the stack by *framesizep */ + copy %sp, %r1 + add %sp, %r28, %sp + /* Save stack pointer */ + stw %r1, -4(%sp) + + /* Single byte copy of prevous stack onto newly allocated stack */ +1: ldb %r28(%r2), %r1 + add %r28, %sp, %r26 + stb %r1, 0(%r26) + addi,< -1,%r28,%r28 + b,n 1b + + /* Retore r28 and r27 and r2 already points at -192(%sp) */ + ldw 0(%r2),%r28 + ldw 84(%r2),%r26 + + /* Calculate address of L(cont) */ + b,l L(nf),%r2 + depwi 0,31,2,%r2 +L(cont): + /* Undo fake stack */ + ldw -4(%sp),%r1 + copy %r1, %sp + + /* Arguments to _dl_call_pltexit */ + ldw -116(%sp), %r26 /* (1) got[1] == struct link_map */ + ldw -120(%sp), %r25 /* (2) reloc offsets */ + ldo -56(%sp), %r24 /* (3) *La_hppa_regs */ + ldo -124(%sp), %r23 /* (4) *La_hppa_retval */ + + /* Fill *La_hppa_retval */ + stw %r28,-140(%sp) + stw %r29,-136(%sp) + ldo -128(%sp), %r1 + fstd %fr4,0(%r1) + + /* Call _dl_call_pltexit */ + bl _dl_call_pltexit,%rp + nop + + /* Restore *La_hppa_retval */ + ldw -140(%sp), %r28 + ldw -136(%sp), %r29 + ldo -128(%sp), %r1 + fldd 0(%r1), %fr4 + + /* Unwind the stack */ + ldo 192(%sp),%sp + /* Retore callers rp */ + ldw -20(%sp),%rp + /* Return */ + bv,n 0(%r2) .EXIT .PROCEND .size _dl_runtime_profile, . - _dl_runtime_profile - - diff --git a/sysdeps/unix/sysv/linux/hppa/bits/atomic.h b/sysdeps/unix/sysv/linux/hppa/bits/atomic.h index 36a540728e..ee381dc27b 100644 --- a/sysdeps/unix/sysv/linux/hppa/bits/atomic.h +++ b/sysdeps/unix/sysv/linux/hppa/bits/atomic.h @@ -60,7 +60,7 @@ typedef uintmax_t uatomic_max_t; #define LWS_CAS 0x0 /* Note r31 is the link register */ #define LWS_CLOBBER "r1", "r26", "r25", "r24", "r23", "r22", "r21", "r20", "r28", "r31", "memory" -#define ASM_EAGAIN "11" +#define ASM_EAGAIN -EAGAIN #if __ASSUME_LWS_CAS /* The only basic operation needed is compare and exchange. */ diff --git a/sysdeps/unix/sysv/linux/hppa/bits/mman.h b/sysdeps/unix/sysv/linux/hppa/bits/mman.h index 54531ecf28..f065322175 100644 --- a/sysdeps/unix/sysv/linux/hppa/bits/mman.h +++ b/sysdeps/unix/sysv/linux/hppa/bits/mman.h @@ -21,12 +21,12 @@ # error "Never use directly; include instead." #endif -/* these are basically taken from the kernel definitions */ +/* These are taken from the kernel definitions. */ -#define PROT_READ 0x1 /* page can be read */ -#define PROT_WRITE 0x2 /* page can be written */ -#define PROT_EXEC 0x4 /* page can be executed */ -#define PROT_NONE 0x0 /* page can not be accessed */ +#define PROT_READ 0x1 /* Page can be read */ +#define PROT_WRITE 0x2 /* Page can be written */ +#define PROT_EXEC 0x4 /* Page can be executed */ +#define PROT_NONE 0x0 /* Page can not be accessed */ #define PROT_GROWSDOWN 0x01000000 /* Extend change to start of growsdown vma (mprotect only). */ #define PROT_GROWSUP 0x02000000 /* Extend change to start of @@ -34,33 +34,53 @@ #define MAP_SHARED 0x01 /* Share changes */ #define MAP_PRIVATE 0x02 /* Changes are private */ -#define MAP_TYPE 0x03 /* Mask for type of mapping */ +#ifdef __USE_MISC +# define MAP_TYPE 0x03 /* Mask for type of mapping */ +#endif + +/* Other flags. */ #define MAP_FIXED 0x04 /* Interpret addr exactly */ -#define MAP_ANONYMOUS 0x10 /* don't use a file */ +#ifdef __USE_MISC +# define MAP_FILE 0x0 +# define MAP_ANONYMOUS 0x10 /* Don't use a file */ +# define MAP_ANON MAP_ANONYMOUS +# define MAP_VARIABLE 0 +#endif -#define MAP_DENYWRITE 0x0800 /* ETXTBSY */ -#define MAP_EXECUTABLE 0x1000 /* mark it as an executable */ -#define MAP_LOCKED 0x2000 /* pages are locked */ -#define MAP_NORESERVE 0x4000 /* don't check for reservations */ -#define MAP_GROWSDOWN 0x8000 /* stack-like segment */ -#define MAP_POPULATE 0x10000 /* populate (prefault) pagetables */ -#define MAP_NONBLOCK 0x20000 /* do not block on IO */ +/* These are Linux-specific. */ +#ifdef __USE_MISC +# define MAP_DENYWRITE 0x0800 /* ETXTBSY */ +# define MAP_EXECUTABLE 0x1000 /* Mark it as an executable */ +# define MAP_LOCKED 0x2000 /* Pages are locked */ +# define MAP_NORESERVE 0x4000 /* Don't check for reservations */ +# define MAP_GROWSDOWN 0x8000 /* Stack-like segment */ +# define MAP_POPULATE 0x10000 /* Populate (prefault) pagetables */ +# define MAP_NONBLOCK 0x20000 /* Do not block on IO */ +#endif -#define MS_SYNC 1 /* synchronous memory sync */ -#define MS_ASYNC 2 /* sync memory asynchronously */ -#define MS_INVALIDATE 4 /* invalidate the caches */ +/* Flags to "msync" */ +#define MS_SYNC 1 /* Synchronous memory sync */ +#define MS_ASYNC 2 /* Sync memory asynchronously */ +#define MS_INVALIDATE 4 /* Invalidate the caches */ -#define MCL_CURRENT 1 /* lock all current mappings */ -#define MCL_FUTURE 2 /* lock all future mappings */ +/* Flags to "mlockall" */ +#define MCL_CURRENT 1 /* Lock all current mappings */ +#define MCL_FUTURE 2 /* Lock all future mappings */ -/* Advice to "madvise" */ +/* Flags for `mremap'. */ +#ifdef __USE_GNU +# define MREMAP_MAYMOVE 1 +# define MREMAP_FIXED 2 +#endif + +/* Advice to "madvise" */ #ifdef __USE_BSD -# define MADV_NORMAL 0 /* no further special treatment */ -# define MADV_RANDOM 1 /* expect random page references */ -# define MADV_SEQUENTIAL 2 /* expect sequential page references */ -# define MADV_WILLNEED 3 /* will need these pages */ -# define MADV_DONTNEED 4 /* dont need these pages */ -# define MADV_SPACEAVAIL 5 /* insure that resources are reserved */ +# define MADV_NORMAL 0 /* No further special treatment */ +# define MADV_RANDOM 1 /* Expect random page references */ +# define MADV_SEQUENTIAL 2 /* Expect sequential page references */ +# define MADV_WILLNEED 3 /* Will need these pages */ +# define MADV_DONTNEED 4 /* Dont need these pages */ +# define MADV_SPACEAVAIL 5 /* Insure that resources are reserved */ # define MADV_VPS_PURGE 6 /* Purge pages from VM page cache */ # define MADV_VPS_INHERIT 7 /* Inherit parents page size */ # define MADV_REMOVE 9 /* Remove these pages and resources. */ @@ -78,15 +98,11 @@ #define MADV_16M_PAGES 24 /* Use 16 Megabyte pages */ #define MADV_64M_PAGES 26 /* Use 64 Megabyte pages */ -/* compatibility flags */ -#define MAP_ANON MAP_ANONYMOUS -#define MAP_FILE 0 -#define MAP_VARIABLE 0 - -/* Flags for `mremap'. */ -#ifdef __USE_GNU -# define MREMAP_MAYMOVE 1 -# define MREMAP_FIXED 2 +/* The POSIX people had to invent similar names for the same things. */ +#ifdef __USE_XOPEN2K +# define POSIX_MADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_MADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_MADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_MADV_DONTNEED 4 /* Don't need these pages. */ #endif - - diff --git a/sysdeps/unix/sysv/linux/hppa/clone.S b/sysdeps/unix/sysv/linux/hppa/clone.S index 1884518a3d..231989518e 100644 --- a/sysdeps/unix/sysv/linux/hppa/clone.S +++ b/sysdeps/unix/sysv/linux/hppa/clone.S @@ -27,11 +27,19 @@ #include /* Non-thread code calls __clone with the following parameters: - int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg) + int clone(int (*fn)(void *arg), + void *child_stack, + int flags, + void *arg) NPTL Code will call __clone with the following parameters: - int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg, - int *parent_tidptr, struct user_desc *newtls, int *child_pidptr) + int clone(int (*fn)(void *arg), + void *child_stack, + int flags, + void *arg, + int *parent_tidptr, + struct user_desc *newtls, + int *child_pidptr) The code should not mangle the extra input registers. Syscall expects: Input to __clone: @@ -43,32 +51,37 @@ r23 - struct user_desc newtls pointer. (stack - 56) r22 - child tid pointer. (stack - 60) r20 - clone syscall number (constant) + + Return: + + On success the thread ID of the child process is returend in + the callers context. + On error return -1, and set errno to the value returned by + the syscall. */ .text ENTRY(__clone) + /* Prologue */ + stwm %r3, 64(%sp) + stw %sp, -4(%sp) + stw %r19, -32(%sp) /* Sanity check arguments. */ - ldi -EINVAL,%ret0 - comib,=,n 0,%arg0,.Lerror /* no NULL function pointers */ - comib,=,n 0,%arg1,.Lerror /* no NULL stack pointers */ + comib,=,n 0, %arg0, .LerrorSanity /* no NULL function pointers */ + comib,=,n 0, %arg1, .LerrorSanity /* no NULL stack pointers */ /* Save the fn ptr and arg on the new stack. */ - stwm %r26,64(%r25) - stw %r23,-60(%r25) + stwm %r26, 64(%r25) + stw %r23, -60(%r25) /* Clone arguments are (int flags, void * child_stack) */ - copy %r24,%r26 /* flags are first */ + copy %r24, %r26 /* flags are first */ /* User stack pointer is in the correct register already */ /* Load args from stack... */ - ldw -52(%sp), %r24 /* Load parent_tidptr */ - ldw -56(%sp), %r23 /* Load newtls */ - ldw -60(%sp), %r22 /* Load child_tidptr */ - - /* Create frame to get r3 free */ - copy %sp, %r21 - stwm %r3, 64(%sp) - stw %r21, -4(%sp) + ldw -116(%sp), %r24 /* Load parent_tidptr */ + ldw -120(%sp), %r23 /* Load newtls */ + ldw -124(%sp), %r22 /* Load child_tidptr */ /* Save the PIC register. */ #ifdef PIC @@ -76,19 +89,20 @@ ENTRY(__clone) #endif /* Do the system call */ - ble 0x100(%sr2,%r0) - ldi __NR_clone,%r20 + ble 0x100(%sr2, %r0) + ldi __NR_clone, %r20 - ldi -4096,%r1 - comclr,>>= %r1,%ret0,%r0 /* Note: unsigned compare. */ + ldi -4096, %r1 + comclr,>>= %r1, %ret0, %r0 /* Note: unsigned compare. */ b,n .LerrorRest - comib,=,n 0,%ret0,thread_start + comib,=,n 0, %ret0, .LthreadStart /* Successful return from the parent No need to restore the PIC register, since we return immediately. */ + ldw -84(%sp), %rp bv %r0(%rp) ldwm -64(%sp), %r3 @@ -97,36 +111,40 @@ ENTRY(__clone) #ifdef PIC copy %r3, %r19 /* parent */ #endif - /* Something bad happened -- no child created */ -.Lerror: - - /* Set errno, save ret0 so we return with that value. */ - copy %ret0, %r3 - b __syscall_error - sub %r0,%ret0,%arg0 - copy %r3, %ret0 - /* Return after setting errno, and restoring ret0 */ + bl __syscall_error, %rp + sub %r0, %ret0, %arg0 + ldw -84(%sp), %rp + /* Return after setting errno, ret0 is set to -1 by __syscall_error. */ bv %r0(%rp) ldwm -64(%sp), %r3 -thread_start: +.LerrorSanity: + /* Sanity checks failed, return -1, and set errno to EINVAL. */ + bl __syscall_error, %rp + ldi EINVAL, %arg0 + /* Lazy, don't restore r19 */ + ldw -84(%sp), %rp + bv %r0(%rp) + ldwm -64(%sp), %r3 + +.LthreadStart: /* Load up the arguments. */ - ldw -60(%sr0, %sp),%arg0 - ldw -64(%sr0, %sp),%r22 + ldw -60(%sp), %arg0 + ldw -64(%sp), %r22 /* $$dyncall fixes childs PIC register */ /* Call the user's function */ - bl $$dyncall,%r31 - copy %r31,%rp + bl $$dyncall, %r31 + copy %r31, %rp - bl _exit,%rp - copy %ret0,%arg0 + bl _exit, %rp + copy %ret0, %arg0 - /* Die horribly. */ - iitlbp %r0,(%sr0,%r0) + /* We should not return from _exit. */ + iitlbp %r0, (%sr0, %r0) PSEUDO_END(__clone) diff --git a/sysdeps/unix/sysv/linux/hppa/nptl/lowlevellock.h b/sysdeps/unix/sysv/linux/hppa/nptl/lowlevellock.h index a5412bfd5a..3b2b0f1adb 100644 --- a/sysdeps/unix/sysv/linux/hppa/nptl/lowlevellock.h +++ b/sysdeps/unix/sysv/linux/hppa/nptl/lowlevellock.h @@ -25,34 +25,10 @@ #include #include -#if 0 /* The hppa only has one atomic read and modify memory operation, - load and clear, so hppa spinlocks must use zero to signify that - someone is holding the lock. The address used for the ldcw - semaphore must be 16-byte aligned. */ -#define __ldcw(a) \ -({ \ - unsigned int __ret; \ - __asm__ __volatile__("ldcw 0(%1),%0" \ - : "=r" (__ret) : "r" (a) : "memory"); \ - __ret; \ -}) - -/* Because malloc only guarantees 8-byte alignment for malloc'd data, - and GCC only guarantees 8-byte alignment for stack locals, we can't - be assured of 16-byte alignment for atomic lock data even if we - specify "__attribute ((aligned(16)))" in the type declaration. So, - we use a struct containing an array of four ints for the atomic lock - type and dynamically select the 16-byte aligned int from the array - for the semaphore. */ -#define __PA_LDCW_ALIGNMENT 16 -#define __ldcw_align(a) ({ \ - volatile unsigned int __ret = (unsigned int) a; \ - if ((__ret & ~(__PA_LDCW_ALIGNMENT - 1)) < (unsigned int) a) \ - __ret = (__ret & ~(__PA_LDCW_ALIGNMENT - 1)) + __PA_LDCW_ALIGNMENT; \ - (unsigned int *) __ret; \ -}) -#endif + load and clear, so hppa uses a kernel helper routine to implement + compare_and_exchange. See atomic.h for the userspace calling + sequence. */ #define FUTEX_WAIT 0 #define FUTEX_WAKE 1 @@ -64,11 +40,7 @@ #define FUTEX_UNLOCK_PI 7 #define FUTEX_TRYLOCK_PI 8 -/* Initializer for compatibility lock. */ -#if 0 -#define LLL_INITIALIZER_NOT_ZERO -#define LLL_MUTEX_LOCK_INITIALIZER ((__atomic_lock_t){ { 1, 1, 1, 1 } }) -#endif +/* Initialize locks to zero. */ #define LLL_MUTEX_LOCK_INITIALIZER (0) @@ -82,7 +54,7 @@ typedef int lll_lock_t; long int __ret; \ __ret = INTERNAL_SYSCALL (futex, __err, 4, \ (futexp), FUTEX_WAIT, (val), 0); \ - INTERNAL_SYSCALL_ERROR_P (__ret, __err) ? -__ret : __ret; \ + __ret; \ }) #define lll_futex_timed_wait(futexp, val, timespec) \ @@ -91,7 +63,7 @@ typedef int lll_lock_t; long int __ret; \ __ret = INTERNAL_SYSCALL (futex, __err, 4, \ (futexp), FUTEX_WAIT, (val), (timespec)); \ - INTERNAL_SYSCALL_ERROR_P (__ret, __err) ? -__ret : __ret; \ + __ret; \ }) #define lll_futex_wake(futexp, nr) \ @@ -100,7 +72,7 @@ typedef int lll_lock_t; long int __ret; \ __ret = INTERNAL_SYSCALL (futex, __err, 4, \ (futexp), FUTEX_WAKE, (nr), 0); \ - INTERNAL_SYSCALL_ERROR_P (__ret, __err) ? -__ret : __ret; \ + __ret; \ }) #define lll_robust_mutex_dead(futexv) \ @@ -120,7 +92,7 @@ typedef int lll_lock_t; __ret = INTERNAL_SYSCALL (futex, __err, 6, \ (futexp), FUTEX_CMP_REQUEUE, (nr_wake), \ (nr_move), (mutex), (val)); \ - INTERNAL_SYSCALL_ERROR_P (__ret, __err); \ + __ret; \ }) /* Returns non-zero if error happened, zero if success. */ @@ -253,25 +225,12 @@ __lll_mutex_unlock_force (lll_lock_t *futex) } #define lll_mutex_unlock_force(futex) __lll_mutex_unlock_force(&(futex)) - -static inline int __attribute__ ((always_inline)) -__lll_mutex_islocked (lll_lock_t *futex) -{ - return (*futex != 0); -} -#define lll_mutex_islocked(futex) __lll_mutex_islocked(&(futex)) - +#define lll_mutex_islocked(futex) \ + (futex != 0) /* Our internal lock implementation is identical to the binary-compatible mutex implementation. */ -/* Initializers for lock. */ -#if 0 -#define LLL_LOCK_INITIALIZER ((__atomic_lock_t){ { 1, 1, 1, 1 } }) -#define LLL_LOCK_INITIALIZER_CONST { { 1, 1, 1, 1 } } -#define LLL_LOCK_INITIALIZER_LOCKED ((__atomic_lock_t){ { 0, 0, 0, 0 } }) -#endif - #define LLL_LOCK_INITIALIZER (0) #define LLL_LOCK_INITIALIZER_CONST (0) #define LLL_LOCK_INITIALIZER_LOCKED (1) diff --git a/sysdeps/unix/sysv/linux/hppa/nptl/pt-vfork.S b/sysdeps/unix/sysv/linux/hppa/nptl/pt-vfork.S index a44e785bb6..83a70b71cb 100644 --- a/sysdeps/unix/sysv/linux/hppa/nptl/pt-vfork.S +++ b/sysdeps/unix/sysv/linux/hppa/nptl/pt-vfork.S @@ -50,6 +50,10 @@ /* r26, r25, r24, r23 are free since vfork has no arguments */ ENTRY(__vfork) + /* Prologue */ + stwm %r3, 64(%sp) + stw %sp, -4(%sp) + stw %r19, -32(%sp) /* Save the PIC register. */ #ifdef PIC @@ -72,9 +76,12 @@ ENTRY(__vfork) b,n .Lerror /* Return, no need to restore the PIC register. */ - bv,n %r0(%rp) + ldw -84(%sp), %rp + bv %r0(%rp) + ldwm -64(%sp), %r3 .Lerror: + sub %r0,%ret0,%r3 SYSCALL_ERROR_HANDLER /* Restore the PIC register (in delay slot) on error */ #ifdef PIC @@ -82,8 +89,11 @@ ENTRY(__vfork) #else nop #endif - sub %r0,%ret0,%arg0 - /* Return error */ + /* Write syscall return into errno location */ + stw %r3, 0(%ret0) + ldw -84(%sp), %rp + bv %r0(%rp) + ldwm -64(%sp), %r3 PSEUDO_END (__vfork) libc_hidden_def (__vfork) weak_alias (__vfork, vfork) diff --git a/sysdeps/unix/sysv/linux/hppa/nptl/sysdep-cancel.h b/sysdeps/unix/sysv/linux/hppa/nptl/sysdep-cancel.h index 748fe6961c..2d3de3efed 100644 --- a/sysdeps/unix/sysv/linux/hppa/nptl/sysdep-cancel.h +++ b/sysdeps/unix/sysv/linux/hppa/nptl/sysdep-cancel.h @@ -63,11 +63,9 @@ # define PSEUDO(name, syscall_name, args) \ ENTRY (name) \ DOARGS_##args ASM_LINE_SEP \ - copy TREG, %r1 ASM_LINE_SEP \ - copy %sp, TREG ASM_LINE_SEP \ - stwm %r1, 64(%sp) ASM_LINE_SEP \ - stw %rp, -20(%sp) ASM_LINE_SEP \ - stw TREG, -4(%sp) ASM_LINE_SEP \ + stwm TREG, 64(%sp) ASM_LINE_SEP \ + stw %sp, -4(%sp) ASM_LINE_SEP \ + stw %r19, -32(%sp) ASM_LINE_SEP \ /* Done setting up frame, continue... */ ASM_LINE_SEP \ SINGLE_THREAD_P ASM_LINE_SEP \ cmpib,<>,n 0,%ret0,L(pseudo_cancel) ASM_LINE_SEP \ @@ -91,7 +89,7 @@ L(unthreaded): ASM_LINE_SEP \ stw TREG, 0(%sr0,%ret0) ASM_LINE_SEP \ b L(pre_end) ASM_LINE_SEP \ /* return -1 as error */ ASM_LINE_SEP \ - ldo -1(%r0), %ret0 /* delay */ ASM_LINE_SEP \ + ldi -1, %ret0 /* delay */ ASM_LINE_SEP \ L(pseudo_cancel): ASM_LINE_SEP \ PUSHARGS_##args /* Save args */ ASM_LINE_SEP \ /* Save r19 into TREG */ ASM_LINE_SEP \ @@ -125,13 +123,13 @@ L(pseudo_cancel): ASM_LINE_SEP \ /* store into errno location */ ASM_LINE_SEP \ stw TREG, 0(%sr0,%ret0) ASM_LINE_SEP \ /* return -1 */ ASM_LINE_SEP \ - ldo -1(%r0), %ret0 ASM_LINE_SEP \ + ldi -1, %ret0 ASM_LINE_SEP \ L(pre_end): ASM_LINE_SEP \ - /* Restore rp before exit */ ASM_LINE_SEP \ - ldw -84(%sr0,%sp), %rp ASM_LINE_SEP \ + /* No need to LOAD_PIC */ ASM_LINE_SEP \ /* Undo frame */ ASM_LINE_SEP \ ldwm -64(%sp),TREG ASM_LINE_SEP \ - /* No need to LOAD_PIC */ ASM_LINE_SEP + /* Restore rp before exit */ ASM_LINE_SEP \ + ldw -20(%sp), %rp ASM_LINE_SEP /* Save arguments into our frame */ # define PUSHARGS_0 /* nothing to do */ diff --git a/sysdeps/unix/sysv/linux/hppa/nptl/unwind-forcedunwind.c b/sysdeps/unix/sysv/linux/hppa/nptl/unwind-forcedunwind.c index c8142cb543..8666bbb3c8 100644 --- a/sysdeps/unix/sysv/linux/hppa/nptl/unwind-forcedunwind.c +++ b/sysdeps/unix/sysv/linux/hppa/nptl/unwind-forcedunwind.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2005 Free Software Foundation, Inc. +/* Copyright (C) 2005, 2006 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 @@ -16,6 +16,100 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#define LIBGCC_S_SO "libgcc_s.so.2" -#include +#include +#include +#include +#include +#define LIBGCC_S_SO "libgcc_s.so.4" + +static void (*libgcc_s_resume) (struct _Unwind_Exception *exc); +static _Unwind_Reason_Code (*libgcc_s_personality) + (int, _Unwind_Action, _Unwind_Exception_Class, struct _Unwind_Exception *, + struct _Unwind_Context *); +static _Unwind_Reason_Code (*libgcc_s_forcedunwind) + (struct _Unwind_Exception *, _Unwind_Stop_Fn, void *); +static _Unwind_Word (*libgcc_s_getcfa) (struct _Unwind_Context *); + +#ifndef LIBGCC_S_SO +#define LIBGCC_S_SO "libgcc_s.so.1" +#endif + +void +__attribute_noinline__ +pthread_cancel_init (void) +{ + void *resume, *personality, *forcedunwind, *getcfa; + void *handle; + + if (__builtin_expect (libgcc_s_getcfa != NULL, 1)) + { + /* Force gcc to reload all values. */ + asm volatile ("" ::: "memory"); + return; + } + + handle = __libc_dlopen (LIBGCC_S_SO); + + if (handle == NULL + || (resume = __libc_dlsym (handle, "_Unwind_Resume")) == NULL + || (personality = __libc_dlsym (handle, "__gcc_personality_v0")) == NULL + || (forcedunwind = __libc_dlsym (handle, "_Unwind_ForcedUnwind")) + == NULL + || (getcfa = __libc_dlsym (handle, "_Unwind_GetCFA")) == NULL +#ifdef ARCH_CANCEL_INIT + || ARCH_CANCEL_INIT (handle) +#endif + ) + __libc_fatal ("libgcc_s.so must be installed for pthread_cancel to work\n"); + + libgcc_s_resume = resume; + libgcc_s_personality = personality; + libgcc_s_forcedunwind = forcedunwind; + /* Make sure libgcc_s_getcfa is written last. Otherwise, + pthread_cancel_init might return early even when the pointer the + caller is interested in is not initialized yet. */ + atomic_write_barrier (); + libgcc_s_getcfa = getcfa; +} + +void +_Unwind_Resume (struct _Unwind_Exception *exc) +{ + if (__builtin_expect (libgcc_s_resume == NULL, 0)) + pthread_cancel_init (); + + libgcc_s_resume (exc); +} + +_Unwind_Reason_Code +__gcc_personality_v0 (int version, _Unwind_Action actions, + _Unwind_Exception_Class exception_class, + struct _Unwind_Exception *ue_header, + struct _Unwind_Context *context) +{ + if (__builtin_expect (libgcc_s_personality == NULL, 0)) + pthread_cancel_init (); + + return libgcc_s_personality (version, actions, exception_class, + ue_header, context); +} + +_Unwind_Reason_Code +_Unwind_ForcedUnwind (struct _Unwind_Exception *exc, _Unwind_Stop_Fn stop, + void *stop_argument) +{ + if (__builtin_expect (libgcc_s_forcedunwind == NULL, 0)) + pthread_cancel_init (); + + return libgcc_s_forcedunwind (exc, stop, stop_argument); +} + +_Unwind_Word +_Unwind_GetCFA (struct _Unwind_Context *context) +{ + if (__builtin_expect (libgcc_s_getcfa == NULL, 0)) + pthread_cancel_init (); + + return libgcc_s_getcfa (context); +} diff --git a/sysdeps/unix/sysv/linux/hppa/nptl/unwind-resume.c b/sysdeps/unix/sysv/linux/hppa/nptl/unwind-resume.c index 6d1da85504..a7485e950f 100644 --- a/sysdeps/unix/sysv/linux/hppa/nptl/unwind-resume.c +++ b/sysdeps/unix/sysv/linux/hppa/nptl/unwind-resume.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2005 Free Software Foundation, Inc. +/* Copyright (C) 2005, 2006 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 @@ -16,6 +16,55 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#define LIBGCC_S_SO "libgcc_s.so.2" -#include +#include +#include +#include +#define LIBGCC_S_SO "libgcc_s.so.4" + +static void (*libgcc_s_resume) (struct _Unwind_Exception *exc); +static _Unwind_Reason_Code (*libgcc_s_personality) + (int, _Unwind_Action, _Unwind_Exception_Class, struct _Unwind_Exception *, + struct _Unwind_Context *); + +#ifndef LIBGCC_S_SO +#error LIBGCC_S_SO +#define LIBGCC_S_SO "libgcc_s.so.1" +#endif + +static void +init (void) +{ + void *resume, *personality; + void *handle; + + handle = __libc_dlopen (LIBGCC_S_SO); + + if (handle == NULL + || (resume = __libc_dlsym (handle, "_Unwind_Resume")) == NULL + || (personality = __libc_dlsym (handle, "__gcc_personality_v0")) == NULL) + __libc_fatal ("libgcc_s.so must be installed for pthread_cancel to work\n"); + + libgcc_s_resume = resume; + libgcc_s_personality = personality; +} + +void +_Unwind_Resume (struct _Unwind_Exception *exc) +{ + if (__builtin_expect (libgcc_s_resume == NULL, 0)) + init (); + libgcc_s_resume (exc); +} + +_Unwind_Reason_Code +__gcc_personality_v0 (int version, _Unwind_Action actions, + _Unwind_Exception_Class exception_class, + struct _Unwind_Exception *ue_header, + struct _Unwind_Context *context) +{ + if (__builtin_expect (libgcc_s_personality == NULL, 0)) + init (); + return libgcc_s_personality (version, actions, exception_class, + ue_header, context); +} diff --git a/sysdeps/unix/sysv/linux/hppa/sysdep.h b/sysdeps/unix/sysv/linux/hppa/sysdep.h index b302d37f7b..5b12bc5062 100644 --- a/sysdeps/unix/sysv/linux/hppa/sysdep.h +++ b/sysdeps/unix/sysv/linux/hppa/sysdep.h @@ -278,12 +278,10 @@ #undef DO_CALL #define DO_CALL(syscall_name, args) \ - copy TREG,%r1 ASM_LINE_SEP \ - copy %sp,TREG ASM_LINE_SEP \ /* Create a frame */ ASM_LINE_SEP \ - stwm %r1, 64(%sp) ASM_LINE_SEP \ - stw %rp, -20(%sp) ASM_LINE_SEP \ - stw TREG, -4(%sp) ASM_LINE_SEP \ + stwm TREG, 64(%sp) ASM_LINE_SEP \ + stw %sp, -4(%sp) ASM_LINE_SEP \ + stw %r19, -32(%sp) ASM_LINE_SEP \ /* Save r19 */ ASM_LINE_SEP \ SAVE_PIC(TREG) ASM_LINE_SEP \ /* Do syscall, delay loads # */ ASM_LINE_SEP \ @@ -304,10 +302,10 @@ /* return -1 as error */ ASM_LINE_SEP \ ldo -1(%r0), %ret0 ASM_LINE_SEP \ L(pre_end): ASM_LINE_SEP \ - /* Restore return pointer */ ASM_LINE_SEP \ - ldw -84(%sp),%rp ASM_LINE_SEP \ /* Restore our frame, restoring TREG */ ASM_LINE_SEP \ - ldwm -64(%sp), TREG ASM_LINE_SEP + ldwm -64(%sp), TREG ASM_LINE_SEP \ + /* Restore return pointer */ ASM_LINE_SEP \ + ldw -20(%sp),%rp ASM_LINE_SEP /* We do nothing with the return, except hand it back to someone else */ #undef DO_CALL_NOERRNO @@ -386,10 +384,9 @@ L(pre_end): ASM_LINE_SEP \ #undef INTERNAL_SYSCALL_DECL #define INTERNAL_SYSCALL_DECL(err) -/* Equivalent to (val < 0)&&(val > -4095) which is what we want */ #undef INTERNAL_SYSCALL_ERROR_P #define INTERNAL_SYSCALL_ERROR_P(val, err) \ - ((unsigned long)val >= (unsigned long)-4095) + ((val < 0) && (val > -4095)) #undef INTERNAL_SYSCALL_ERRNO #define INTERNAL_SYSCALL_ERRNO(val, err) (-(val))