+2006-09-07 Carlos O'Donell <carlos@systemhalted.org>
+
+ * 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 <carlos@systemhalted.org>
* sysdeps/unix/sysv/linux/hppa/nptl/lowlevellock.h (FUTEX_LOCK_PI,
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;
}
/* 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
/* 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.
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 */
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
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
-
- /* 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
+ /* Load up the returned function descriptor */
+ copy %r28, %r22
+ copy %r29, %r19
+
+ /* 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
-
-
#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. */
# error "Never use <bits/mman.h> directly; include <sys/mman.h> 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
#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. */
#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
-
-
#include <bits/errno.h>
/* 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:
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
#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
#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
+
+.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
-thread_start:
+.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)
#include <sysdep.h>
#include <atomic.h>
-#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
#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)
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) \
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) \
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) \
__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. */
}
#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)
/* 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
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
#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)
# 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 \
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 \
/* 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 */
-/* 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
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 <sysdeps/pthread/unwind-forcedunwind.c>
+#include <dlfcn.h>
+#include <stdio.h>
+#include <unwind.h>
+#include <pthreadP.h>
+#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);
+}
-/* 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
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 <sysdeps/pthread/unwind-resume.c>
+#include <dlfcn.h>
+#include <stdio.h>
+#include <unwind.h>
+#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);
+}
#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 \
/* 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
#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))