Skip to contentSkip to conversation

glibc patch for fsyscall support

Linux-ia64 David Mosberger 1 participant 1 message Jan 30, 2003

lore
Share & tools
lore
#0 lore raw

For those of you eager to "try out" (read: burn your fingers with) the fsyscall support, here is a quick & dirty patch for libc. It is relative to the CVS at sources.redhat.com. You'll need at least gcc-3.2 and should configure glibc with "--enable-add-ons --with-tls --without-__thread" as that's the only thing I tested. Also, I'd highly recommend to run "make check" to verify that things are reasonably sane before trying to install the result on a live system. As usual when messing with glibc, be prepared for having to recover your root filesystem (a spare second disk come in real handy here...).

I haven't done a huge amount of testing, but I did install the new libc on a dual-Itanium 2 zx6000 workstation and it booted fine and worked as expected. The "null" syscall reported by LMbench looks nice, too:

Processor, Processes - times in microseconds - smaller is better
----------------------------------------------------------------
Host OS Mhz null null open selct sig sig fork exec sh
call I/O stat clos TCP inst hndl proc proc proc
--------- ------------- ---- ---- ---- ---- ---- ----- ---- ---- ---- ---- ----

caldera.h  Linux 2.5.59 1000 0.38 0.54 2.76 4.09  16.8 0.61 2.43 223. 738. 2661
caldera.h  Linux 2.5.59 1000 0.07 0.55 2.66 4.03  16.8 0.60 2.85 235. 738. 2660
                             ^^^^
                              ;-)

(First one is with old glibc, second one with new one.)

On a related note, I just pushed my latest kernel changes into the lia64 bk repository. The latest changeset (see
http://lia64.bkbits.net:8080/to-linus-2.5/[email protected]) contains the dynamic Erratum 9 workaround patching and the getppid() light-weight system call.

Happy hacking,

	--david

Index: elf/dl-support.c
=================================RCS file: /cvs/glibc/libc/elf/dl-support.c,v retrieving revision 1.67

dl-support.c +5 -0
diff -u -r1.67 dl-support.c
@@ -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

descr.h +20 -0
diff -u -r1.8 descr.h
@@ -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

manager.c +2 -0
diff -u -r1.90 manager.c
@@ -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

pthread.c +5 -0
diff -u -r1.119 pthread.c
@@ -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

sysdeps/ia64/tcb-offsets.sym +1 -0
diff -u -r1.3 tcb-offsets.sym
@@ -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

sysdeps/ia64/tls.h +7 -2
diff -u -r1.4 tls.h
@@ -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/vfork.S =================================RCS file: /cvs/glibc/libc/linuxthreads/sysdeps/unix/sysv/linux/ia64/vfork.S,v retrieving revision 1.2

sysdeps/unix/sysv/linux/ia64/vfork.S +5 -1
diff -u -r1.2 vfork.S
@@ -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

generic/libc-start.c +9 -8
diff -u -r1.35 libc-start.c
@@ -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

unix/sysv/linux/ia64/clone2.S +27 -14

65 lines not on this page · raw message

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

unix/sysv/linux/ia64/sysdep.h +22 -0
diff -u -r1.10 sysdep.h
@@ -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

unix/sysv/linux/ia64/vfork.S +5 -1
diff -u -r1.4 vfork.S
@@ -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)