This is the mail archive of the libc-hacker@sources.redhat.com mailing list for the glibc project.

Note that libc-hacker is a closed list. You may look at the archives of this list, but subscription and posting are not open.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: new syscall stub support for ia64 libc


Here is an updated patch.  I'm going to be on travel for a good part
of this week, so I thought I'd send out the latest patch in case
someone wants to try it out or had some feedback.  I haven't
incorporated Rich's suggestion yet and the current "struct pthread"
version still is bigger than strictly needed, but with the patch "make
check" for NPTL-enabled libc succeeds for the most part (modulo
tst-tls1, tst-local{1,2}, and tst-cancel{6,9,17}).  Also, the number
of "break 0x100000" calls inside libc is down to about 4 (primarily
due to clone2(), syscall(), and vfork()).

Note that there was a relatively large change to lowlevellock.h.
Apart from include-file headaches, I didn't see why this code
couldn't/shouldn't use Jakub's syscall inline macros so I changed them
accordingly (perhaps the code was originaly written before Jakub's
inline-macro existed?).  Obviously, the include-file issue still needs
to be worked out (for now, I just copied the relevant definitions from
sysdep.h).

Oh, one more thing: I think my change to nptl/descr.h may have broken
all other platforms which define TLS_DTV_AT_TP.  I thought there was
an odd asymmetry between platforms which do or do not define
TLS_DTV_AT_TP and I thought it would be cleaner if each platform were
to define a tcbhead_t (plus it allows moving the multiple_threads
member close to the sysinfo member, which means cancellable syscall
stubs will touch only one extra cache line), but for now, I only
changed the ia64 header, so the other platforms would break (alpha,
powerpc, and sh appear to be affected by this).

	--david

Index: elf/rtld.c
===================================================================
RCS file: /cvs/glibc/libc/elf/rtld.c,v
retrieving revision 1.299
diff -u -r1.299 rtld.c
--- elf/rtld.c	27 Oct 2003 20:08:32 -0000	1.299
+++ elf/rtld.c	3 Nov 2003 21:26:41 -0000
@@ -1169,8 +1169,10 @@
 		  l->l_ldnum = ph->p_memsz / sizeof (ElfW(Dyn));
 		  break;
 		}
+#if 0
 	      if (ph->p_type == PT_LOAD)
 		assert ((void *) ph->p_vaddr == GL(dl_sysinfo_dso));
+#endif
 	    }
 	  elf_get_dynamic_info (l, dyn_temp);
 	  _dl_setup_hash (l);
Index: linuxthreads/descr.h
===================================================================
RCS file: /cvs/glibc/libc/linuxthreads/descr.h,v
retrieving revision 1.14
diff -u -r1.14 descr.h
--- linuxthreads/descr.h	17 Sep 2003 09:39:00 -0000	1.14
+++ linuxthreads/descr.h	3 Nov 2003 21:26:42 -0000
@@ -189,7 +189,23 @@
 #endif
   size_t p_alloca_cutoff;	/* Maximum size which should be allocated
 				   using alloca() instead of malloc().  */
+#if TLS_TCB_AT_TP
   /* New elements must be added at the end.  */
+#else
+  union {
+    struct {
+      void *reserved[11];	/* reserve for future use */
+      void *tcb;		/* XXX do we really need this? */
+      union dtv *dtvp;		/* XXX do we really need this? */
+      pthread_descr self;	/* XXX do we really need this? */
+      int multiple_threads;
+#ifdef NEED_DL_SYSINFO
+      uintptr_t sysinfo;
+#endif
+    } data;
+    void *__padding[16];
+  } p_header __attribute__ ((aligned(32)));
+#endif
 } __attribute__ ((aligned(32))); /* We need to align the structure so that
 				    doubles are aligned properly.  This is 8
 				    bytes on MIPS and 16 bytes on MIPS64.
Index: linuxthreads/sysdeps/ia64/tls.h
===================================================================
RCS file: /cvs/glibc/libc/linuxthreads/sysdeps/ia64/tls.h,v
retrieving revision 1.6
diff -u -r1.6 tls.h
--- linuxthreads/sysdeps/ia64/tls.h	31 Jul 2003 19:16:34 -0000	1.6
+++ linuxthreads/sysdeps/ia64/tls.h	3 Nov 2003 21:26:43 -0000
@@ -20,10 +20,13 @@
 #ifndef _TLS_H
 #define _TLS_H
 
+#include <dl-sysdep.h>
+
 #ifndef __ASSEMBLER__
 
 # include <pt-machine.h>
 # include <stddef.h>
+# include <stdint.h>
 
 /* Type for the dtv.  */
 typedef union dtv
@@ -83,8 +86,10 @@
 /* Code to initially initialize the thread pointer.  This might need
    special attention since 'errno' is not yet available and if the
    operation can cause a failure 'errno' must not be touched.  */
-#  define TLS_INIT_TP(tcbp, secondcall) \
-  (__thread_self = (__typeof (__thread_self)) (tcbp), NULL)
+#  define TLS_INIT_TP(tcbp, secondcall)			\
+  (__thread_self = (__typeof (__thread_self)) (tcbp),	\
+   THREAD_SELF->p_header.data.sysinfo = GL(dl_sysinfo),	\
+   NULL)
 
 /* Return the address of the dtv for the current thread.  */
 #  define THREAD_DTV() \
Index: linuxthreads/sysdeps/unix/sysv/linux/ia64/vfork.S
===================================================================
RCS file: /cvs/glibc/libc/linuxthreads/sysdeps/unix/sysv/linux/ia64/vfork.S,v
retrieving revision 1.4
diff -u -r1.4 vfork.S
--- linuxthreads/sysdeps/unix/sysv/linux/ia64/vfork.S	11 Feb 2003 06:27:53 -0000	1.4
+++ linuxthreads/sysdeps/unix/sysv/linux/ia64/vfork.S	3 Nov 2003 21:26:43 -0000
@@ -43,9 +43,8 @@
 	mov out0=CLONE_VM+CLONE_VFORK+SIGCHLD
 	mov out1=0		/* Standard sp value.			*/
 	;;
-	DO_CALL (SYS_ify (clone))
+	DO_CALL_VIA_BREAK (SYS_ify (clone))
 	cmp.eq p6,p0=-1,r10
-	;;
 (p6)	br.cond.spnt.few __syscall_error
 	ret
 PSEUDO_END(__vfork)
Index: nptl/descr.h
===================================================================
RCS file: /cvs/glibc/libc/nptl/descr.h,v
retrieving revision 1.20
diff -u -r1.20 descr.h
--- nptl/descr.h	22 Jul 2003 23:04:00 -0000	1.20
+++ nptl/descr.h	3 Nov 2003 21:26:44 -0000
@@ -95,17 +95,11 @@
 /* Thread descriptor data structure.  */
 struct pthread
 {
+#if !TLS_DTV_AT_TP
   union
   {
-#if !TLS_DTV_AT_TP
     /* This overlaps the TCB as used for TLS without threads (see tls.h).  */
     tcbhead_t header;
-#else
-    struct
-    {
-      int multiple_threads;
-    } header;
-#endif
 
     /* This extra padding has no special purpose, and this structure layout
        is private and subject to change without affecting the official ABI.
@@ -113,6 +107,7 @@
        implementation-specific instrumentation hack or suchlike.  */
     void *__padding[16];
   };
+#endif
 
   /* This descriptor's link on the `stack_used' or `__stack_user' list.  */
   list_t list;
@@ -239,6 +234,19 @@
 
   /* Resolver state.  */
   struct __res_state res;
+
+#if TLS_DTV_AT_TP
+  union
+  {
+    tcbhead_t header;
+
+    /* This extra padding has no special purpose, and this structure layout
+       is private and subject to change without affecting the official ABI.
+       We just have it here in case it might be convenient for some
+       implementation-specific instrumentation hack or suchlike.  */
+    void *__padding[16];
+  };
+#endif
 } __attribute ((aligned (TCB_ALIGNMENT)));
 
 
Index: nptl/sysdeps/ia64/tcb-offsets.sym
===================================================================
RCS file: /cvs/glibc/libc/nptl/sysdeps/ia64/tcb-offsets.sym,v
retrieving revision 1.4
diff -u -r1.4 tcb-offsets.sym
--- nptl/sysdeps/ia64/tcb-offsets.sym	25 Apr 2003 22:15:55 -0000	1.4
+++ nptl/sysdeps/ia64/tcb-offsets.sym	3 Nov 2003 21:26:44 -0000
@@ -2,3 +2,4 @@
 #include <tls.h>
 
 MULTIPLE_THREADS_OFFSET offsetof (struct pthread, header.multiple_threads) - sizeof (struct pthread)
+SYSINFO_OFFSET		offsetof (struct pthread, header.sysinfo) - sizeof (struct pthread)
Index: nptl/sysdeps/ia64/tls.h
===================================================================
RCS file: /cvs/glibc/libc/nptl/sysdeps/ia64/tls.h,v
retrieving revision 1.4
diff -u -r1.4 tls.h
--- nptl/sysdeps/ia64/tls.h	9 Sep 2003 07:00:21 -0000	1.4
+++ nptl/sysdeps/ia64/tls.h	3 Nov 2003 21:26:44 -0000
@@ -36,10 +36,15 @@
 } dtv_t;
 
 
+/* tcbhead_t must be exactly 16 64-bit words, such that sysinfo lines
+   up with the end of "struct pthread". */
 typedef struct
 {
+  void *reserved[12];
   dtv_t *dtv;
   void *private;
+  int multiple_threads;
+  uintptr_t sysinfo;	/* must be the last word in the tcb! */
 } tcbhead_t;
 
 # define TLS_MULTIPLE_THREADS_IN_TCB 1
@@ -100,11 +105,19 @@
 #  define GET_DTV(descr) \
   (((tcbhead_t *) (descr))->dtv)
 
+#if defined NEED_DL_SYSINFO
+# define INIT_SYSINFO   THREAD_SELF->header.sysinfo = GL(dl_sysinfo)
+#else
+# define INIT_SYSINFO   NULL
+#endif
+
 /* Code to initially initialize the thread pointer.  This might need
    special attention since 'errno' is not yet available and if the
    operation can cause a failure 'errno' must not be touched.  */
-# define TLS_INIT_TP(thrdescr, secondcall) \
-  (__thread_self = (thrdescr), NULL)
+#  define TLS_INIT_TP(thrdescr, secondcall)	\
+  (__thread_self = (thrdescr),			\
+   INIT_SYSINFO,				\
+   NULL)
 
 /* Return the address of the dtv for the current thread.  */
 #  define THREAD_DTV() \
Index: nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.h
===================================================================
RCS file: /cvs/glibc/libc/nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.h,v
retrieving revision 1.14
diff -u -r1.14 lowlevellock.h
--- nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.h	22 Sep 2003 21:27:26 -0000	1.14
+++ nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.h	3 Nov 2003 21:26:45 -0000
@@ -26,7 +26,7 @@
 #include <ia64intrin.h>
 #include <atomic.h>
 
-#define SYS_futex		1230
+#define __NR_futex		1230
 #define FUTEX_WAIT		0
 #define FUTEX_WAKE		1
 #define FUTEX_REQUEUE		3
@@ -34,6 +34,102 @@
 /* Initializer for compatibility lock.	*/
 #define LLL_MUTEX_LOCK_INITIALIZER (0)
 
+/* XXX share this with sysdep.h! */
+
+#define DO_INLINE_SYSCALL(name, nr, args...)				\
+    register long _r8 __asm ("r8");					\
+    register long _r10 __asm ("r10");					\
+    register long _r15 __asm ("r15") = __NR_##name;			\
+    long _retval;							\
+    LOAD_ARGS_##nr (args);						\
+    /*									\
+     * Don't specify any unwind info here.  We mark ar.pfs as		\
+     * clobbered.  This will force the compiler to save ar.pfs		\
+     * somewhere and emit appropriate unwind info for that save.	\
+     */									\
+    __asm __volatile ("adds r2 = -8, r13;;\n"				\
+		      "ld8 r2 = [r2];;\n"				\
+		      "mov b7=r2;\n"					\
+		      "br.call.sptk.many b6=b7;;\n"			\
+                      : "=r" (_r8), "=r" (_r10), "=r" (_r15)		\
+		        ASM_OUTARGS_##nr				\
+                      : "2" (_r15) ASM_ARGS_##nr			\
+		      : "memory", "ar.pfs" ASM_CLOBBERS_##nr);		\
+    _retval = _r8;
+
+#define LOAD_ARGS_0()   do { } while (0)
+#define LOAD_ARGS_1(out0)				\
+  register long _out0 asm ("out0") = (long) (out0);	\
+  LOAD_ARGS_0 ()
+#define LOAD_ARGS_2(out0, out1)				\
+  register long _out1 asm ("out1") = (long) (out1);	\
+  LOAD_ARGS_1 (out0)
+#define LOAD_ARGS_3(out0, out1, out2)			\
+  register long _out2 asm ("out2") = (long) (out2);	\
+  LOAD_ARGS_2 (out0, out1)
+#define LOAD_ARGS_4(out0, out1, out2, out3)		\
+  register long _out3 asm ("out3") = (long) (out3);	\
+  LOAD_ARGS_3 (out0, out1, out2)
+#define LOAD_ARGS_5(out0, out1, out2, out3, out4)	\
+  register long _out4 asm ("out4") = (long) (out4);	\
+  LOAD_ARGS_4 (out0, out1, out2, out3)
+
+#define ASM_OUTARGS_0
+#define ASM_OUTARGS_1	ASM_OUTARGS_0, "=r" (_out0)
+#define ASM_OUTARGS_2	ASM_OUTARGS_1, "=r" (_out1)
+#define ASM_OUTARGS_3	ASM_OUTARGS_2, "=r" (_out2)
+#define ASM_OUTARGS_4	ASM_OUTARGS_3, "=r" (_out3)
+#define ASM_OUTARGS_5	ASM_OUTARGS_4, "=r" (_out4)
+
+#define ASM_ARGS_0
+#define ASM_ARGS_1	ASM_ARGS_0, "3" (_out0)
+#define ASM_ARGS_2	ASM_ARGS_1, "4" (_out1)
+#define ASM_ARGS_3	ASM_ARGS_2, "5" (_out2)
+#define ASM_ARGS_4	ASM_ARGS_3, "6" (_out3)
+#define ASM_ARGS_5	ASM_ARGS_4, "7" (_out4)
+
+#define ASM_CLOBBERS_0	ASM_CLOBBERS_1, "out0"
+#define ASM_CLOBBERS_1	ASM_CLOBBERS_2, "out1"
+#define ASM_CLOBBERS_2	ASM_CLOBBERS_3, "out2"
+#define ASM_CLOBBERS_3	ASM_CLOBBERS_4, "out3"
+#define ASM_CLOBBERS_4	ASM_CLOBBERS_5, "out4"
+#define ASM_CLOBBERS_5	ASM_CLOBBERS_6, "out5"
+#define ASM_CLOBBERS_6	, "out6", "out7",				\
+  /* Non-stacked integer registers, minus r8, r10, r15.  */		\
+  "r2", "r3", "r9", "r11", "r12", "r13", "r14", "r16", "r17", "r18",	\
+  "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26", "r27",	\
+  "r28", "r29", "r30", "r31",						\
+  /* Predicate registers.  */						\
+  "p6", "p7", "p8", "p9", "p10", "p11", "p12", "p13", "p14", "p15",	\
+  /* Non-rotating fp registers.  */					\
+  "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",	\
+  /* Branch registers.  */						\
+  "b6", "b7"
+
+/* XXX end sharable stuff */
+
+#define lll_futex_wait(futex, val) lll_futex_timed_wait (futex, val, 0)
+
+#define lll_futex_timed_wait(ftx, val, timespec)						\
+({												\
+   DO_INLINE_SYSCALL(futex, 4, (long) (ftx), FUTEX_WAIT, (int) (val), (long) (timespec));	\
+   _r10 == -1 ? -_retval : _retval;								\
+})
+
+#define lll_futex_wake(ftx, nr)									\
+({												\
+   DO_INLINE_SYSCALL(futex, 3, (long) (ftx), FUTEX_WAKE, (int) (nr));				\
+   _r10 == -1 ? -_retval : _retval;								\
+})
+
+#define lll_futex_requeue(ftx, nr_wake, nr_move, mutex)						\
+({												\
+   DO_INLINE_SYSCALL(futex, 5, (long) (ftx), FUTEX_REQUEUE, (int) (nr_wake),			\
+		     (int) (nr_move), (long) (mutex));						\
+   _r10 == -1 ? -_retval : _retval;								\
+})
+
+#if 0
 #define lll_futex_clobbers \
   "out5", "out6", "out7",						      \
   /* Non-stacked integer registers, minus r8, r10, r15.  */		      \
@@ -48,9 +144,8 @@
   "b6", "b7",								      \
   "memory"
 
-#define lll_futex_wait(futex, val) lll_futex_timed_wait (futex, val, 0)
 
-#define lll_futex_timed_wait(futex, val, timespec) \
+#define lll_futex_timed_wait(futex, val, timespec)			      \
   ({									      \
      register long int __o0 asm ("out0") = (long int) (futex);		      \
      register long int __o1 asm ("out1") = FUTEX_WAIT;			      \
@@ -69,7 +164,6 @@
      __r10 == -1 ? -__r8 : __r8;					      \
   })
 
-
 #define lll_futex_wake(futex, nr) \
   ({									      \
      register long int __o0 asm ("out0") = (long int) (futex);		      \
@@ -109,6 +203,7 @@
 		       : lll_futex_clobbers);				      \
      __r10 == -1 ? -__r8 : __r8;					      \
   })
+#endif
 
 
 static inline int
Index: nptl/sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h
===================================================================
RCS file: /cvs/glibc/libc/nptl/sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h,v
retrieving revision 1.7
diff -u -r1.7 sysdep-cancel.h
--- nptl/sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h	8 Jul 2003 03:47:52 -0000	1.7
+++ nptl/sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h	3 Nov 2003 21:26:45 -0000
@@ -29,13 +29,21 @@
 # define PSEUDO(name, syscall_name, args)				      \
 .text;									      \
 ENTRY (name)								      \
-     adds r14 = MULTIPLE_THREADS_OFFSET, r13;;				      \
+     .prologue;								      \
+     adds r2 = SYSINFO_OFFSET, r13;					      \
+     adds r14 = MULTIPLE_THREADS_OFFSET, r13;				      \
+     .save ar.pfs, r11;							      \
+     mov r11 = ar.pfs;;							      \
+     .body;								      \
      ld4 r14 = [r14];							      \
+     ld8 r2 = [r2];							      \
      mov r15 = SYS_ify(syscall_name);;					      \
      cmp4.ne p6, p7 = 0, r14;						      \
-(p6) br.cond.spnt .Lpseudo_cancel;;					      \
-     break __BREAK_SYSCALL;;						      \
-     cmp.eq p6,p0=-1,r10;						      \
+     mov b7 = r2;							      \
+(p6) br.cond.spnt .Lpseudo_cancel;					      \
+     br.call.sptk.many b6 = b7;;					      \
+     mov ar.pfs = r11;							      \
+     cmp.eq p6,p0 = -1, r10;						      \
 (p6) br.cond.spnt.few __syscall_error;					      \
      ret;;								      \
      .endp name;							      \
@@ -45,17 +53,20 @@
 __GC_##name:								      \
 .Lpseudo_cancel:							      \
      .prologue;								      \
-     .regstk args, 5, args, 0;						      \
+     .regstk args, 6, args, 0;						      \
      .save ar.pfs, loc0;						      \
-     alloc loc0 = ar.pfs, args, 5, args, 0;				      \
+     alloc loc0 = ar.pfs, args, 6, args, 0;				      \
+     adds loc5 = SYSINFO_OFFSET, r13;					      \
      .save rp, loc1;							      \
      mov loc1 = rp;;							      \
      .body;								      \
+     ld8 loc5 = [loc5];							      \
      CENABLE;;								      \
      mov loc2 = r8;							      \
+     mov b7 = loc5;							      \
      COPY_ARGS_##args							      \
      mov r15 = SYS_ify(syscall_name);					      \
-     break __BREAK_SYSCALL;;						      \
+     br.call.sptk.many b6 = b7;;					      \
      mov loc3 = r8;							      \
      mov loc4 = r10;							      \
      mov out0 = loc2;							      \
Index: sysdeps/ia64/elf/start.S
===================================================================
RCS file: /cvs/glibc/libc/sysdeps/ia64/elf/start.S,v
retrieving revision 1.12
diff -u -r1.12 start.S
--- sysdeps/ia64/elf/start.S	29 Mar 2003 19:18:27 -0000	1.12
+++ sysdeps/ia64/elf/start.S	3 Nov 2003 21:26:47 -0000
@@ -19,6 +19,8 @@
 
 #include <sysdep.h>
 
+#undef ret
+
 #include <asm/unistd.h>
 #include <asm/fpu.h>
 
Index: sysdeps/unix/sysv/linux/ia64/brk.S
===================================================================
RCS file: /cvs/glibc/libc/sysdeps/unix/sysv/linux/ia64/brk.S,v
retrieving revision 1.4
diff -u -r1.4 brk.S
--- sysdeps/unix/sysv/linux/ia64/brk.S	3 Mar 2003 07:11:46 -0000	1.4
+++ sysdeps/unix/sysv/linux/ia64/brk.S	3 Nov 2003 21:26:52 -0000
@@ -35,19 +35,17 @@
 weak_alias (__curbrk, ___brk_addr)
 
 LEAF(__brk)
-	mov	r15=__NR_brk
-	break.i	__BREAK_SYSCALL
+	.regstk 1, 0, 0, 0
+	DO_CALL(__NR_brk)
+	cmp.ltu	p6, p0 = ret0, in0
+	addl r9 = @ltoff(__curbrk), gp
 	;;
-	cmp.ltu	p6,p0=ret0,r32	/* r32 is the input register, even though we
-				   haven't allocated a frame */
-	addl	r9=@ltoff(__curbrk),gp
-	;;
-	ld8	r9=[r9]
-(p6) 	mov	ret0=ENOMEM
+	ld8 r9 = [r9]
+(p6) 	mov ret0 = ENOMEM
 (p6)	br.cond.spnt.few __syscall_error
 	;;
-	st8	[r9]=ret0
-	mov 	ret0=0
+	st8 [r9] = ret0
+	mov ret0 = 0
 	ret
 END(__brk)
 
Index: sysdeps/unix/sysv/linux/ia64/clone2.S
===================================================================
RCS file: /cvs/glibc/libc/sysdeps/unix/sysv/linux/ia64/clone2.S,v
retrieving revision 1.7
diff -u -r1.7 clone2.S
--- sysdeps/unix/sysv/linux/ia64/clone2.S	13 Mar 2003 04:36:59 -0000	1.7
+++ sysdeps/unix/sysv/linux/ia64/clone2.S	3 Nov 2003 21:26:52 -0000
@@ -25,49 +25,56 @@
 /* 	         size_t child_stack_size, int flags, void *arg,		*/
 /*	         pid_t *parent_tid, void *tls, pid_t *child_tid)	*/
 
+#define CHILD	p8
+#define PARENT	p9
+
 ENTRY(__clone2)
-	alloc r2=ar.pfs,8,2,6,0
+	.prologue
+	alloc r2=ar.pfs,8,0,6,0
 	cmp.eq p6,p0=0,in0
 	mov r8=EINVAL
-(p6)	br.cond.spnt.few __syscall_error
-	;;
-	flushrs			/* This is necessary, since the child	*/
-				/* will be running with the same 	*/
-				/* register backing store for a few 	*/
-				/* instructions.  We need to ensure	*/
-				/* that it will not read or write the	*/
-				/* backing store.			*/
-	mov loc0=in0		/* save fn	*/
-	mov loc1=in4		/* save arg	*/
 	mov out0=in3		/* Flags are first syscall argument.	*/
 	mov out1=in1		/* Stack address.			*/
+(p6)	br.cond.spnt.many __syscall_error
+	;;
 	mov out2=in2		/* Stack size.				*/
 	mov out3=in5		/* Parent TID Pointer			*/
 	mov out4=in7		/* Child TID Pointer			*/
  	mov out5=in6		/* TLS pointer				*/
-        DO_CALL (SYS_ify (clone2))
+	/*
+	 * clone2() is special: the child cannot execute br.ret right
+	 * after the system call returns, because it starts out
+	 * executing on an empty stack.  Because of this, we can't use
+	 * the new (lightweight) syscall convention here.  Instead, we
+	 * just fall back on always using "break".
+	 *
+	 * Furthermore, since the child starts with an empty stack, we
+	 * need to avoid unwinding past invalid memory.  To that end,
+	 * we'll pretend now that __clone2() is the end of the
+	 * call-chain.  This is wrong for the parent, but only until
+	 * it returns from clone2() but it's better than the
+	 * alternative.
+	 */
+	mov r15=SYS_ify (clone2)
+	.save rp, r0
+	break __BREAK_SYSCALL
+	.body
         cmp.eq p6,p0=-1,r10
+	cmp.eq CHILD,PARENT=0,r8 /* Are we the child?   */
+(p6)	br.cond.spnt.many __syscall_error
 	;;
-(p6)	br.cond.spnt.few __syscall_error
-
-#	define CHILD p6
-#	define PARENT p7
-	cmp.eq CHILD,PARENT=0,r8 /* Are we the child?	*/
-	;;
-(CHILD)	ld8 out1=[loc0],8	/* Retrieve code pointer.	*/
-(CHILD)	mov out0=loc1		/* Pass proper argument	to fn */
+(CHILD)	ld8 out1=[in0],8	/* Retrieve code pointer.	*/
+(CHILD)	mov out0=in4		/* Pass proper argument	to fn */
 (PARENT) ret
 	;;
-	ld8 gp=[loc0]		/* Load function gp.		*/
+	ld8 gp=[in0]		/* Load function gp.		*/
 	mov b6=out1
-	;;
-	br.call.dptk.few rp=b6	/* Call fn(arg) in the child 	*/
+	br.call.dptk.many rp=b6	/* Call fn(arg) in the child 	*/
 	;;
 	mov out0=r8		/* Argument to _exit		*/
 	.globl _exit
-	br.call.dpnt.few rp=_exit /* call _exit with result from fn.	*/
+	br.call.dpnt.many rp=_exit /* call _exit with result from fn.	*/
 	ret			/* Not reached.		*/
-
 PSEUDO_END(__clone2)
 
 /* For now we leave __clone undefined.  This is unlikely to be a	*/
Index: sysdeps/unix/sysv/linux/ia64/getcontext.S
===================================================================
RCS file: /cvs/glibc/libc/sysdeps/unix/sysv/linux/ia64/getcontext.S,v
retrieving revision 1.8
diff -u -r1.8 getcontext.S
--- sysdeps/unix/sysv/linux/ia64/getcontext.S	26 Sep 2003 08:41:51 -0000	1.8
+++ sysdeps/unix/sysv/linux/ia64/getcontext.S	3 Nov 2003 21:26:53 -0000
@@ -35,26 +35,27 @@
 
 ENTRY(__getcontext)
 	.prologue
-	alloc r16 = ar.pfs, 1, 0, 4, 0
+	.body
+	alloc r11 = ar.pfs, 1, 0, 4, 0
 
 	// sigprocmask (SIG_BLOCK, NULL, &sc->sc_mask):
 
-	mov r2 = SC_MASK
-	mov r15 = __NR_rt_sigprocmask
-	;;
+	mov r3 = SC_MASK
 	mov out0 = SIG_BLOCK
-	mov out1 = 0
-	add out2 = r2, in0
-	mov out3 = 8	// sizeof kernel sigset_t
 
-	break __BREAK_SYSCALL
 	flushrs					// save dirty partition on rbs
+	mov out1 = 0
+	add out2 = r3, in0
+
+	mov out3 = 8	// sizeof kernel sigset_t
+	DO_CALL(__NR_rt_sigprocmask)
 
 	mov.m rFPSR = ar.fpsr
 	mov.m rRSC = ar.rsc
 	add r2 = SC_GR+1*8, r32
 	;;
 	mov.m rBSP = ar.bsp
+	.prologue
 	.save ar.unat, rUNAT
 	mov.m rUNAT = ar.unat
 	.body
@@ -63,7 +64,7 @@
 
 .mem.offset 0,0; st8.spill [r2] = r1, (5*8 - 1*8)
 .mem.offset 8,0; st8.spill [r3] = r4, 16
-	mov.i rPFS = ar.pfs
+	mov rPFS = r11
 	;;
 .mem.offset 0,0; st8.spill [r2] = r5, 16
 .mem.offset 8,0; st8.spill [r3] = r6, 48
Index: sysdeps/unix/sysv/linux/ia64/setcontext.S
===================================================================
RCS file: /cvs/glibc/libc/sysdeps/unix/sysv/linux/ia64/setcontext.S,v
retrieving revision 1.4
diff -u -r1.4 setcontext.S
--- sysdeps/unix/sysv/linux/ia64/setcontext.S	28 May 2003 20:45:25 -0000	1.4
+++ sysdeps/unix/sysv/linux/ia64/setcontext.S	3 Nov 2003 21:26:53 -0000
@@ -32,20 +32,21 @@
   other than the PRESERVED state.  */
 
 ENTRY(__setcontext)
-	alloc r16 = ar.pfs, 1, 0, 4, 0
+	.prologue
+	.body
+	alloc r11 = ar.pfs, 1, 0, 4, 0
 
 	// sigprocmask (SIG_SETMASK, &sc->sc_mask, NULL):
 
-	mov r2 = SC_MASK
-	mov r15 = __NR_rt_sigprocmask
-	;;
+	mov r3 = SC_MASK
 	mov out0 = SIG_SETMASK
-	add out1 = r2, in0
+	;;
+	add out1 = r3, in0
 	mov out2 = 0
 	mov out3 = 8	// sizeof kernel sigset_t
 
 	invala
-	break __BREAK_SYSCALL
+	DO_CALL(__NR_rt_sigprocmask)
 	add r2 = SC_NAT, r32
 
 	add r3 = SC_RNAT, r32			// r3 <- &sc_ar_rnat
Index: sysdeps/unix/sysv/linux/ia64/sysdep.h
===================================================================
RCS file: /cvs/glibc/libc/sysdeps/unix/sysv/linux/ia64/sysdep.h,v
retrieving revision 1.17
diff -u -r1.17 sysdep.h
--- sysdeps/unix/sysv/linux/ia64/sysdep.h	16 Aug 2003 08:00:24 -0000	1.17
+++ sysdeps/unix/sysv/linux/ia64/sysdep.h	3 Nov 2003 21:26:53 -0000
@@ -23,6 +23,8 @@
 
 #include <sysdeps/unix/sysdep.h>
 #include <sysdeps/ia64/sysdep.h>
+#include <dl-sysdep.h>
+#include <tls.h>
 
 /* For Linux we can use the system call table in the header file
 	/usr/include/asm/unistd.h
@@ -51,6 +53,13 @@
 # define __NR_semtimedop 1247
 #endif
 
+#if defined USE_DL_SYSINFO \
+	&& (!defined NOT_IN_libc || defined IS_IN_libpthread)
+# define IA64_USE_NEW_STUB
+#else
+# undef IA64_USE_NEW_STUB
+#endif
+
 #ifdef __ASSEMBLER__
 
 #undef CALL_MCOUNT
@@ -95,9 +104,41 @@
 	cmp.eq p6,p0=-1,r10;			\
 (p6)	br.cond.spnt.few __syscall_error;
 
-#define DO_CALL(num)				\
+#define DO_CALL_VIA_BREAK(num)			\
 	mov r15=num;				\
-	break __BREAK_SYSCALL;
+	break __BREAK_SYSCALL
+
+#ifdef IA64_USE_NEW_STUB
+# ifdef SHARED
+#  define DO_CALL(num)				\
+	.prologue;				\
+        adds r2 = SYSINFO_OFFSET, r13;;		\
+        ld8 r2 = [r2];				\
+	.save ar.pfs, r11;			\
+        mov r11 = ar.pfs;;			\
+	.body;					\
+	mov r15 = num;				\
+        mov b7 = r2;				\
+        br.call.sptk.many b6 = b7;;		\
+	.restore sp;				\
+        mov ar.pfs = r11
+# else /* !SHARED */
+#  define DO_CALL(num)				\
+	.prologue;				\
+	movl r2 = _dl_sysinfo;;			\
+        ld8 r2 = [r2];				\
+	.save ar.pfs, r11;			\
+        mov r11 = ar.pfs;;			\
+	.body;					\
+	mov r15 = num;				\
+        mov b7 = r2;				\
+        br.call.sptk.many b6 = b7;;		\
+	.restore sp;				\
+        mov ar.pfs = r11
+# endif
+#else
+# define DO_CALL(num)				DO_CALL_VIA_BREAK(num)
+#endif
 
 #undef PSEUDO_END
 #define PSEUDO_END(name)	.endp C_SYMBOL_NAME(name);
@@ -144,6 +185,48 @@
    (non-negative) errno on error or the return value on success.
  */
 #undef INLINE_SYSCALL
+#undef INTERNAL_SYSCALL
+
+#ifdef IA64_USE_NEW_STUB
+#define DO_INLINE_SYSCALL(name, nr, args...)				\
+    register long _r8 __asm ("r8");					\
+    register long _r10 __asm ("r10");					\
+    register long _r15 __asm ("r15") = __NR_##name;			\
+    long _retval;							\
+    LOAD_ARGS_##nr (args);						\
+    /*									\
+     * Don't specify any unwind info here.  We mark ar.pfs as		\
+     * clobbered.  This will force the compiler to save ar.pfs		\
+     * somewhere and emit appropriate unwind info for that save.	\
+     */									\
+    __asm __volatile ("adds r2 = -8, r13;;\n"				\
+		      "ld8 r2 = [r2];;\n"				\
+		      "mov b7=r2;\n"					\
+		      "br.call.sptk.many b6=b7;;\n"			\
+                      : "=r" (_r8), "=r" (_r10), "=r" (_r15)		\
+		        ASM_OUTARGS_##nr				\
+                      : "2" (_r15) ASM_ARGS_##nr			\
+		      : "memory", "ar.pfs" ASM_CLOBBERS_##nr);		\
+    _retval = _r8;
+
+#define INLINE_SYSCALL(name, nr, args...)	\
+  ({						\
+    DO_INLINE_SYSCALL(name, nr, args)		\
+    if (_r10 == -1)				\
+      {						\
+        __set_errno (_retval);			\
+        _retval = -1;				\
+      }						\
+    _retval; })
+
+#define INTERNAL_SYSCALL(name, err, nr, args...)	\
+  ({							\
+    DO_INLINE_SYSCALL(name, nr, args)			\
+    err = _r10;						\
+    _retval; })
+
+#else /* !IA64_USE_NEW_STUB */
+
 #define INLINE_SYSCALL(name, nr, args...)			\
   ({								\
     register long _r8 asm ("r8");				\
@@ -164,10 +247,6 @@
       }								\
     _retval; })
 
-#undef INTERNAL_SYSCALL_DECL
-#define INTERNAL_SYSCALL_DECL(err) long int err
-
-#undef INTERNAL_SYSCALL
 #define INTERNAL_SYSCALL(name, err, nr, args...)		\
   ({								\
     register long _r8 asm ("r8");				\
@@ -184,6 +263,11 @@
     err = _r10;							\
     _retval; })
 
+#endif /* !IA64_USE_NEW_STUB */
+
+#undef INTERNAL_SYSCALL_DECL
+#define INTERNAL_SYSCALL_DECL(err) long int err
+
 #undef INTERNAL_SYSCALL_ERROR_P
 #define INTERNAL_SYSCALL_ERROR_P(val, err)	(err == -1)
 
@@ -226,12 +310,6 @@
 #define ASM_ARGS_5	ASM_ARGS_4, "7" (_out4)
 #define ASM_ARGS_6	ASM_ARGS_5, "8" (_out5)
 
-#define ASM_CLOBBERS_0	ASM_CLOBBERS_1, "out0"
-#define ASM_CLOBBERS_1	ASM_CLOBBERS_2, "out1"
-#define ASM_CLOBBERS_2	ASM_CLOBBERS_3, "out2"
-#define ASM_CLOBBERS_3	ASM_CLOBBERS_4, "out3"
-#define ASM_CLOBBERS_4	ASM_CLOBBERS_5, "out4"
-#define ASM_CLOBBERS_5	ASM_CLOBBERS_6, "out5"
 #define ASM_CLOBBERS_6	, "out6", "out7",				\
   /* Non-stacked integer registers, minus r8, r10, r15.  */		\
   "r2", "r3", "r9", "r11", "r12", "r13", "r14", "r16", "r17", "r18",	\
Index: sysdeps/unix/sysv/linux/ia64/vfork.S
===================================================================
RCS file: /cvs/glibc/libc/sysdeps/unix/sysv/linux/ia64/vfork.S,v
retrieving revision 1.4
diff -u -r1.4 vfork.S
--- sysdeps/unix/sysv/linux/ia64/vfork.S	31 Dec 2002 20:37:30 -0000	1.4
+++ sysdeps/unix/sysv/linux/ia64/vfork.S	3 Nov 2003 21:26:53 -0000
@@ -34,9 +34,8 @@
 	mov out0=CLONE_VM+CLONE_VFORK+SIGCHLD
 	mov out1=0		/* Standard sp value.			*/
 	;;
-	DO_CALL (SYS_ify (clone))
+	DO_CALL_VIA_BREAK (SYS_ify (clone))
 	cmp.eq p6,p0=-1,r10
-	;;
 (p6)	br.cond.spnt.few __syscall_error
 	ret
 PSEUDO_END(__vfork)
Index: nptl/sysdeps/unix/sysv/linux/ia64/dl-sysdep.h
===================================================================
--- /dev/null	2003-08-25 16:34:40.000000000 -0700
+++ nptl/sysdeps/unix/sysv/linux/ia64/dl-sysdep.h	2003-10-30 14:50:53.000000000 -0800
@@ -0,0 +1,64 @@
+/* System-specific settings for dynamic linker code.  IA-64 version.
+   Copyright (C) 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
+   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.  */
+
+#ifndef _DL_SYSDEP_H
+#define _DL_SYSDEP_H	1
+
+/* This macro must be defined to either 0 or 1.
+
+   If 1, then an errno global variable hidden in ld.so will work right with
+   all the errno-using libc code compiled for ld.so, and there is never a
+   need to share the errno location with libc.  This is appropriate only if
+   all the libc functions that ld.so uses are called without PLT and always
+   get the versions linked into ld.so rather than the libc ones.  */
+
+#ifdef IS_IN_rtld
+# define RTLD_PRIVATE_ERRNO 1
+#else
+# define RTLD_PRIVATE_ERRNO 0
+#endif
+
+/* Traditionally system calls have been made using break 0x100000.  A
+   second method was introduced which, if possible, will use the EPC
+   instruction.  To signal the presence and where to find the code the
+   kernel passes an AT_SYSINFO_EHDR pointer in the auxiliary vector to
+   the application.  */
+#define NEED_DL_SYSINFO	1
+#define USE_DL_SYSINFO	1
+
+#if defined NEED_DL_SYSINFO && !defined __ASSEMBLER__
+/* Don't declare this as a function---we want it's entry-point, not
+   it's function descriptor... */
+extern int _dl_sysinfo_break attribute_hidden;
+# define DL_SYSINFO_DEFAULT ((uintptr_t) &_dl_sysinfo_break)
+# define DL_SYSINFO_IMPLEMENTATION		\
+  asm (".text\n\t"				\
+       ".hidden _dl_sysinfo_break\n\t"		\
+       ".proc _dl_sysinfo_break\n\t"		\
+       "_dl_sysinfo_break:\n\t"			\
+       ".prologue\n\t"				\
+       ".altrp b6\n\t"				\
+       ".body\n\t"				\
+       "break 0x100000;\n\t"			\
+       "br.ret.sptk.many b6;\n\t"		\
+       ".endp _dl_sysinfo_break"		\
+       ".previous");
+#endif
+
+#endif	/* dl-sysdep.h */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]