glibc patch for fsyscall support
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
@@ -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
@@ -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 thatdoubles 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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 definedHAVE_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
@@ -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)