Re: [Linux-ia64] glibc patch for fsyscall support

From: David Mosberger <davidm_at_napali.hpl.hp.com>
Date: 2003-02-04 12:33:17
Hi Ian,

>>>>> On Tue, 4 Feb 2003 12:18:11 +1100, Ian Wienand <ianw@gelato.unsw.edu.au> said:

  Ian> Hi i'm having a few problems with this patch

  >> +#ifdef NEED_DL_SYSINFO

  Ian> isn't defined anywhere.  after putting a def in tls.h (though i don't
  Ian> think it belongs there) i continued on.

  Ian> then I get

  Ian> dl-support.c:129: `DL_SYSINFO_DEFAULT' undeclared here (not in a function)

  Ian> since this isn't defined anywhere but i386 dl-sysdep.h.  I'm not
  Ian> so sure about this one, so I thought I'd ask you.  I did grab libc cvs
  Ian> from the date you posted your message, but grepping shows I'll have
  Ian> the same problems.

It looks like I forgot to specify the -N flag when running "cvs diff",
which had the effect of completely omitting the file:

	linuxthreads/sysdeps/unix/sysv/linux/ia64/dl-sysdep.h

(why is it that source-code control systems always seem to default to
the least useful combination of flag settings...?)

An updated patch is below.  I think if you just grab the dl-sysdep.h
portion, you should be fine though.

	--david

Index: elf/dl-support.c
===================================================================
RCS file: /cvs/glibc/libc/elf/dl-support.c,v
retrieving revision 1.67
diff -u -r1.67 dl-support.c
--- elf/dl-support.c	7 Jan 2003 18:50:59 -0000	1.67
+++ elf/dl-support.c	4 Feb 2003 01:27:00 -0000
@@ -161,6 +161,11 @@
       case AT_PHNUM:
 	GL(dl_phnum) = av->a_un.a_val;
 	break;
+#ifdef NEED_DL_SYSINFO
+      case AT_SYSINFO:
+	GL(dl_sysinfo) = av->a_un.a_val;
+	break;
+#endif
       }
 }
 #endif
Index: linuxthreads/descr.h
===================================================================
RCS file: /cvs/glibc/libc/linuxthreads/descr.h,v
retrieving revision 1.8
diff -u -r1.8 descr.h
--- linuxthreads/descr.h	28 Dec 2002 10:14:16 -0000	1.8
+++ linuxthreads/descr.h	4 Feb 2003 01:27:00 -0000
@@ -109,6 +109,7 @@
 
 struct _pthread_descr_struct {
   /* XXX Remove this union for IA-64 style TLS module */
+#if TLS_TCB_AT_TP
   union {
     struct {
       void *tcb;		/* Pointer to the TCB.  This is not always
@@ -122,6 +123,9 @@
     } data;
     void *__padding[16];
   } p_header;
+#else
+  /* New elements must be added at the beginning.  */
+#endif
   pthread_descr p_nextlive, p_prevlive;
                                 /* Double chaining of active threads */
   pthread_descr p_nextwaiting;  /* Next element in the queue holding the thr */
@@ -180,7 +184,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/manager.c
===================================================================
RCS file: /cvs/glibc/libc/linuxthreads/manager.c,v
retrieving revision 1.90
diff -u -r1.90 manager.c
--- linuxthreads/manager.c	12 Jan 2003 08:42:38 -0000	1.90
+++ linuxthreads/manager.c	4 Feb 2003 01:27:00 -0000
@@ -645,6 +666,8 @@
 #endif
   new_thread->p_header.data.self = new_thread;
   new_thread->p_header.data.multiple_threads = 1;
+  /* XXX why isn't this done already??? */
+  new_thread->p_header.data.sysinfo = GL(dl_sysinfo);
   new_thread->p_tid = new_thread_id;
   new_thread->p_lock = &(__pthread_handles[sseg].h_lock);
   new_thread->p_cancelstate = PTHREAD_CANCEL_ENABLE;
Index: linuxthreads/pthread.c
===================================================================
RCS file: /cvs/glibc/libc/linuxthreads/pthread.c,v
retrieving revision 1.119
diff -u -r1.119 pthread.c
--- linuxthreads/pthread.c	16 Jan 2003 18:16:32 -0000	1.119
+++ linuxthreads/pthread.c	4 Feb 2003 01:27:00 -0000
@@ -353,6 +353,9 @@
 
   self = THREAD_SELF;
 
+  /* XXX why isn't this done already??? */
+  self->p_header.data.sysinfo = GL(dl_sysinfo);
+
   /* The memory for the thread descriptor was allocated elsewhere as
      part of the TLS allocation.  We have to initialize the data
      structure by hand.  This initialization must mirror the struct
@@ -614,6 +617,8 @@
   mgr->p_header.data.tcb = tcbp;
   mgr->p_header.data.self = mgr;
   mgr->p_header.data.multiple_threads = 1;
+  /* XXX why isn't this done already??? */
+  mgr->p_header.data.sysinfo = GL(dl_sysinfo);
   mgr->p_lock = &__pthread_handles[1].h_lock;
 # ifndef HAVE___THREAD
   mgr->p_errnop = &mgr->p_errno;
Index: linuxthreads/sysdeps/ia64/tcb-offsets.sym
===================================================================
RCS file: /cvs/glibc/libc/linuxthreads/sysdeps/ia64/tcb-offsets.sym,v
retrieving revision 1.3
diff -u -r1.3 tcb-offsets.sym
--- linuxthreads/sysdeps/ia64/tcb-offsets.sym	16 Jan 2003 18:21:40 -0000	1.3
+++ linuxthreads/sysdeps/ia64/tcb-offsets.sym	4 Feb 2003 01:27:01 -0000
@@ -4,6 +4,7 @@
 --
 #ifdef USE_TLS
 MULTIPLE_THREADS_OFFSET offsetof (struct _pthread_descr_struct, p_header.data.multiple_threads) - sizeof (struct _pthread_descr_struct)
+SYSINFO_OFFSET		offsetof (struct _pthread_descr_struct, p_header.data.sysinfo) - sizeof (struct _pthread_descr_struct)
 #else
 MULTIPLE_THREADS_OFFSET offsetof (tcbhead_t, multiple_threads)
 #endif
Index: linuxthreads/sysdeps/ia64/tls.h
===================================================================
RCS file: /cvs/glibc/libc/linuxthreads/sysdeps/ia64/tls.h,v
retrieving revision 1.4
diff -u -r1.4 tls.h
--- linuxthreads/sysdeps/ia64/tls.h	16 Jan 2003 18:20:44 -0000	1.4
+++ linuxthreads/sysdeps/ia64/tls.h	4 Feb 2003 01:27:01 -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 = (tcbp), NULL)
+#  define TLS_INIT_TP(tcbp, secondcall)			\
+  (__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/dl-sysdep.h
===================================================================
RCS file: linuxthreads/sysdeps/unix/sysv/linux/ia64/dl-sysdep.h
diff -N linuxthreads/sysdeps/unix/sysv/linux/ia64/dl-sysdep.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ linuxthreads/sysdeps/unix/sysv/linux/ia64/dl-sysdep.h	4 Feb 2003 01:27:01 -0000
@@ -0,0 +1,43 @@
+/* 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
+
+#define NEED_DL_SYSINFO
+
+#ifndef __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");
+#endif
+
+#endif	/* dl-sysdep.h */
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.2
diff -u -r1.2 vfork.S
--- linuxthreads/sysdeps/unix/sysv/linux/ia64/vfork.S	14 Jan 2003 01:23:24 -0000	1.2
+++ linuxthreads/sysdeps/unix/sysv/linux/ia64/vfork.S	4 Feb 2003 01:27:01 -0000
@@ -36,9 +36,13 @@
 	mov out0=CLONE_VM+CLONE_VFORK+SIGCHLD
 	mov out1=0		/* Standard sp value.			*/
 	;;
+#if 0
 	DO_CALL (SYS_ify (clone))
+#else
+	mov r15=SYS_ify(clone)
+	break __BREAK_SYSCALL
+#endif
 	cmp.eq p6,p0=-1,r10
-	;;
 (p6)	br.cond.spnt.few __syscall_error
 	ret
 PSEUDO_END(__vfork)
Index: sysdeps/generic/libc-start.c
===================================================================
RCS file: /cvs/glibc/libc/sysdeps/generic/libc-start.c,v
retrieving revision 1.35
diff -u -r1.35 libc-start.c
--- sysdeps/generic/libc-start.c	28 Dec 2002 09:14:52 -0000	1.35
+++ sysdeps/generic/libc-start.c	4 Feb 2003 01:27:01 -0000
@@ -83,14 +83,6 @@
   ++auxvec;
   _dl_aux_init ((ElfW(auxv_t) *) auxvec);
 # endif
-# ifdef DL_SYSDEP_OSCHECK
-  if (!__libc_multiple_libcs)
-    {
-      /* This needs to run to initiliaze _dl_osversion before TLS
-	 setup might check it.  */
-      DL_SYSDEP_OSCHECK (__libc_fatal);
-    }
-# endif
 
   /* Initialize the thread library at least a bit since the libgcc
      functions are using thread functions if these are available and
@@ -101,6 +93,15 @@
   if (__pthread_initialize_minimal)
 # endif
     __pthread_initialize_minimal ();
+
+# ifdef DL_SYSDEP_OSCHECK
+  if (!__libc_multiple_libcs)
+    {
+      /* This needs to run to initiliaze _dl_osversion before TLS
+	 setup might check it.  */
+      DL_SYSDEP_OSCHECK (__libc_fatal);
+    }
+# endif
 
   /* Some security at this point.  Prevent starting a SUID binary where
      the standard file descriptors are not opened.  We have to do this
Index: sysdeps/unix/sysv/linux/ia64/clone2.S
===================================================================
RCS file: /cvs/glibc/libc/sysdeps/unix/sysv/linux/ia64/clone2.S,v
retrieving revision 1.3
diff -u -r1.3 clone2.S
--- sysdeps/unix/sysv/linux/ia64/clone2.S	6 Jul 2001 04:56:17 -0000	1.3
+++ sysdeps/unix/sysv/linux/ia64/clone2.S	4 Feb 2003 01:27:03 -0000
@@ -24,31 +24,45 @@
 /* int  __clone2(int (*fn) (void *arg), void *child_stack_base, 	*/
 /* 	         size_t child_stack_size, int flags, void *arg) */
 
+#define CHILD	p8
+#define PARENT	p9
+
 ENTRY(__clone2)
-	alloc r2=ar.pfs,5,2,3,0
+	.prologue
+	alloc r2=ar.pfs,5,3,3,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.			*/
 	mov out2=in2		/* Stack size.				*/
-        DO_CALL (SYS_ify (clone2))
-        cmp.eq p6,p0=-1,r10
+	/*
+	 * 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".
+	 */
+	mov r15=SYS_ify (clone2)
+	/*
+	 * The child will start with an empty stack.  To avoid unwinding
+	 * past invalid memory, 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 b7=r0
+	.prologue
+	.altrp b7
+	.body
+	break __BREAK_SYSCALL
 	;;
-(p6)	br.cond.spnt.few __syscall_error
-
-#	define CHILD p6
-#	define PARENT p7
 	cmp.eq CHILD,PARENT=0,r8 /* Are we the child?	*/
+        cmp.eq p6,p0=-1,r10
+(p6)	br.cond.spnt.few __syscall_error
 	;;
 (CHILD)	ld8 out1=[loc0],8	/* Retrieve code pointer.	*/
 (CHILD)	mov out0=loc1		/* Pass proper argument	to fn */
@@ -56,7 +70,6 @@
 	;;
 	ld8 gp=[loc0]		/* Load function gp.		*/
 	mov b6=out1
-	;;
 	br.call.dptk.few rp=b6	/* Call fn(arg) in the child 	*/
 	;;
 	mov out0=r8		/* Argument to _exit		*/
Index: sysdeps/unix/sysv/linux/ia64/sysdep.h
===================================================================
RCS file: /cvs/glibc/libc/sysdeps/unix/sysv/linux/ia64/sysdep.h,v
retrieving revision 1.10
diff -u -r1.10 sysdep.h
--- sysdeps/unix/sysv/linux/ia64/sysdep.h	9 Jan 2003 04:09:25 -0000	1.10
+++ sysdeps/unix/sysv/linux/ia64/sysdep.h	4 Feb 2003 01:27:03 -0000
@@ -23,6 +23,7 @@
 
 #include <sysdeps/unix/sysdep.h>
 #include <sysdeps/ia64/sysdep.h>
+#include <tls.h>
 
 /* For Linux we can use the system call table in the header file
 	/usr/include/asm/unistd.h
@@ -89,9 +90,30 @@
 	cmp.eq p6,p0=-1,r10;			\
 (p6)	br.cond.spnt.few __syscall_error;
 
+#if defined HAVE_TLS_SUPPORT && (!defined NOT_IN_libc || defined IS_IN_libpthread)
+
+/* Use the lightweight stub only if (a) we have a suitably modern
+   thread-control block (HAVE_TLS_SUPPORT) and (b) we're not compiling
+   the runtime loader (which might do syscalls before being fully
+   relocated). */
+
+#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
 #define DO_CALL(num)				\
 	mov r15=num;				\
 	break __BREAK_SYSCALL;
+#endif
 
 #undef PSEUDO_END
 #define PSEUDO_END(name)	.endp C_SYMBOL_NAME(name);
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	4 Feb 2003 01:27:03 -0000
@@ -34,9 +34,13 @@
 	mov out0=CLONE_VM+CLONE_VFORK+SIGCHLD
 	mov out1=0		/* Standard sp value.			*/
 	;;
+#if 0
 	DO_CALL (SYS_ify (clone))
+#else
+	mov r15=SYS_ify(clone)
+	break __BREAK_SYSCALL
+#endif
 	cmp.eq p6,p0=-1,r10
-	;;
 (p6)	br.cond.spnt.few __syscall_error
 	ret
 PSEUDO_END(__vfork)
Received on Mon Feb 03 17:40:18 2003

This archive was generated by hypermail 2.1.8 : 2005-08-02 09:20:11 EST