From owner-p4-projects@FreeBSD.ORG Sun Jul 25 10:50:51 2004 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 43E3916A4D0; Sun, 25 Jul 2004 10:50:51 +0000 (GMT) Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 1FCA716A4CE for ; Sun, 25 Jul 2004 10:50:51 +0000 (GMT) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id 16EB243D2D for ; Sun, 25 Jul 2004 10:50:51 +0000 (GMT) (envelope-from dfr@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.12.11/8.12.11) with ESMTP id i6PAoprU033905 for ; Sun, 25 Jul 2004 10:50:51 GMT (envelope-from dfr@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.12.11/8.12.11/Submit) id i6PAooJ0033902 for perforce@freebsd.org; Sun, 25 Jul 2004 10:50:50 GMT (envelope-from dfr@freebsd.org) Date: Sun, 25 Jul 2004 10:50:50 GMT Message-Id: <200407251050.i6PAooJ0033902@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to dfr@freebsd.org using -f From: Doug Rabson To: Perforce Change Reviews Subject: PERFORCE change 58124 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 25 Jul 2004 10:50:51 -0000 http://perforce.freebsd.org/chv.cgi?CH=58124 Change 58124 by dfr@dfr_home on 2004/07/25 10:49:58 Add code to migrate values from the bootstrap TLS segment created by rtld to the main thread's TLS segment when the thread library initialises. While we are here, make sure we properly initialise the static TLS blocks for all modules, not just those in the initial exec group. Also fix a bug which mis-sized the static TLS block when there were non-TLS-using modules present in the initial exec group. Affected files ... .. //depot/projects/kse/lib/libpthread/arch/alpha/alpha/pthread_md.c#2 edit .. //depot/projects/kse/lib/libpthread/arch/alpha/include/pthread_md.h#3 edit .. //depot/projects/kse/lib/libpthread/arch/amd64/amd64/pthread_md.c#3 edit .. //depot/projects/kse/lib/libpthread/arch/amd64/include/pthread_md.h#4 edit .. //depot/projects/kse/lib/libpthread/arch/arm/arm/pthread_md.c#2 edit .. //depot/projects/kse/lib/libpthread/arch/arm/include/pthread_md.h#3 edit .. //depot/projects/kse/lib/libpthread/arch/i386/i386/pthread_md.c#3 edit .. //depot/projects/kse/lib/libpthread/arch/i386/include/pthread_md.h#4 edit .. //depot/projects/kse/lib/libpthread/arch/ia64/ia64/pthread_md.c#3 edit .. //depot/projects/kse/lib/libpthread/arch/ia64/include/pthread_md.h#4 edit .. //depot/projects/kse/lib/libpthread/arch/powerpc/include/pthread_md.h#2 edit .. //depot/projects/kse/lib/libpthread/arch/powerpc/powerpc/pthread_md.c#2 edit .. //depot/projects/kse/lib/libpthread/arch/sparc64/include/pthread_md.h#3 edit .. //depot/projects/kse/lib/libpthread/arch/sparc64/sparc64/pthread_md.c#2 edit .. //depot/projects/kse/lib/libpthread/thread/thr_kern.c#4 edit .. //depot/projects/kse/lib/libthr/arch/i386/i386/_setcurthread.c#3 edit .. //depot/projects/kse/libexec/rtld-elf/i386/reloc.c#8 edit .. //depot/projects/kse/libexec/rtld-elf/rtld.c#12 edit .. //depot/projects/kse/libexec/rtld-elf/rtld.h#7 edit .. //depot/projects/kse/libexec/rtld-elf/rtld_tls.h#2 edit Differences ... ==== //depot/projects/kse/lib/libpthread/arch/alpha/alpha/pthread_md.c#2 (text+ko) ==== @@ -35,7 +35,7 @@ * The constructors. */ struct tcb * -_tcb_ctor(struct pthread *thread) +_tcb_ctor(struct pthread *thread, int initial) { struct tcb *tcb; ==== //depot/projects/kse/lib/libpthread/arch/alpha/include/pthread_md.h#3 (text+ko) ==== @@ -80,7 +80,7 @@ /* * The kcb and tcb constructors. */ -struct tcb *_tcb_ctor(struct pthread *); +struct tcb *_tcb_ctor(struct pthread *, int); void _tcb_dtor(struct tcb *); struct kcb *_kcb_ctor(struct kse *kse); void _kcb_dtor(struct kcb *); ==== //depot/projects/kse/lib/libpthread/arch/amd64/amd64/pthread_md.c#3 (text+ko) ==== @@ -35,11 +35,18 @@ * The constructors. */ struct tcb * -_tcb_ctor(struct pthread *thread) +_tcb_ctor(struct pthread *thread, int initial) { struct tcb *tcb; + void *oldtls; - tcb = _rtld_allocate_tls(sizeof(struct tcb), 16); + if (initial) { + __asm __volatile("movq %%fs:0, %0" : "=r" (oldtls)); + } else { + oldtls = NULL; + } + + tcb = _rtld_allocate_tls(oldtls, sizeof(struct tcb), 16); if (tcb) { tcb->tcb_thread = thread; bzero(&tcb->tcb_tmbx, sizeof(tcb->tcb_tmbx)); ==== //depot/projects/kse/lib/libpthread/arch/amd64/include/pthread_md.h#4 (text+ko) ==== @@ -140,7 +140,7 @@ /* * The constructors. */ -struct tcb *_tcb_ctor(struct pthread *); +struct tcb *_tcb_ctor(struct pthread *, int); void _tcb_dtor(struct tcb *tcb); struct kcb *_kcb_ctor(struct kse *); void _kcb_dtor(struct kcb *); ==== //depot/projects/kse/lib/libpthread/arch/arm/arm/pthread_md.c#2 (text+ko) ==== @@ -40,7 +40,7 @@ #include "pthread_md.h" struct tcb * -_tcb_ctor(struct pthread *thread) +_tcb_ctor(struct pthread *thread, int initial) { struct tcb *tcb; void *addr; ==== //depot/projects/kse/lib/libpthread/arch/arm/include/pthread_md.h#3 (text+ko) ==== @@ -91,7 +91,7 @@ /* * The kcb and tcb constructors. */ -struct tcb *_tcb_ctor(struct pthread *); +struct tcb *_tcb_ctor(struct pthread *, int); void _tcb_dtor(struct tcb *); struct kcb *_kcb_ctor(struct kse *kse); void _kcb_dtor(struct kcb *); ==== //depot/projects/kse/lib/libpthread/arch/i386/i386/pthread_md.c#3 (text+ko) ==== @@ -43,11 +43,18 @@ #include "pthread_md.h" struct tcb * -_tcb_ctor(struct pthread *thread) +_tcb_ctor(struct pthread *thread, int initial) { struct tcb *tcb; + void *oldtls; - tcb = _rtld_allocate_tls(sizeof(struct tcb), 16); + if (initial) { + __asm __volatile("movl %%gs:0, %0" : "=r" (oldtls)); + } else { + oldtls = NULL; + } + + tcb = _rtld_allocate_tls(oldtls, sizeof(struct tcb), 16); if (tcb) { tcb->tcb_thread = thread; tcb->tcb_spare = 0; ==== //depot/projects/kse/lib/libpthread/arch/i386/include/pthread_md.h#4 (text+ko) ==== @@ -139,7 +139,7 @@ /* * The constructors. */ -struct tcb *_tcb_ctor(struct pthread *); +struct tcb *_tcb_ctor(struct pthread *, int); void _tcb_dtor(struct tcb *tcb); struct kcb *_kcb_ctor(struct kse *); void _kcb_dtor(struct kcb *); ==== //depot/projects/kse/lib/libpthread/arch/ia64/ia64/pthread_md.c#3 (text+ko) ==== @@ -35,11 +35,12 @@ * The constructors. */ struct tcb * -_tcb_ctor(struct pthread *thread) +_tcb_ctor(struct pthread *thread, int initial) { struct ia64_tp *tp; - tp = _rtld_allocate_tls(sizeof(struct ia64_tp), 16); + tp = _rtld_allocate_tls(initial ? _tp : NULL, + sizeof(struct ia64_tp), 16); if (tp == NULL) return (NULL); ==== //depot/projects/kse/lib/libpthread/arch/ia64/include/pthread_md.h#4 (text+ko) ==== @@ -75,7 +75,7 @@ /* * The kcb and tcb constructors. */ -struct tcb *_tcb_ctor(struct pthread *); +struct tcb *_tcb_ctor(struct pthread *, int); void _tcb_dtor(struct tcb *); struct kcb *_kcb_ctor(struct kse *kse); void _kcb_dtor(struct kcb *); ==== //depot/projects/kse/lib/libpthread/arch/powerpc/include/pthread_md.h#2 (text+ko) ==== @@ -92,7 +92,7 @@ /* * The kcb and tcb constructors. */ -struct tcb *_tcb_ctor(struct pthread *); +struct tcb *_tcb_ctor(struct pthread *, int); void _tcb_dtor(struct tcb *); struct kcb *_kcb_ctor(struct kse *kse); void _kcb_dtor(struct kcb *); ==== //depot/projects/kse/lib/libpthread/arch/powerpc/powerpc/pthread_md.c#2 (text+ko) ==== @@ -35,7 +35,7 @@ * The constructors. */ struct tcb * -_tcb_ctor(struct pthread *thread) +_tcb_ctor(struct pthread *thread, int initial) { struct tcb *tcb; ==== //depot/projects/kse/lib/libpthread/arch/sparc64/include/pthread_md.h#3 (text+ko) ==== @@ -91,7 +91,7 @@ /* * The kcb and tcb constructors. */ -struct tcb *_tcb_ctor(struct pthread *); +struct tcb *_tcb_ctor(struct pthread *, int); void _tcb_dtor(struct tcb *); struct kcb *_kcb_ctor(struct kse *kse); void _kcb_dtor(struct kcb *); ==== //depot/projects/kse/lib/libpthread/arch/sparc64/sparc64/pthread_md.c#2 (text+ko) ==== @@ -40,7 +40,7 @@ #include "pthread_md.h" struct tcb * -_tcb_ctor(struct pthread *thread) +_tcb_ctor(struct pthread *thread, int initial) { struct tcb *tcb; void *addr; ==== //depot/projects/kse/lib/libpthread/thread/thr_kern.c#4 (text+ko) ==== @@ -2384,7 +2384,7 @@ if ((thread == NULL) && ((thread = malloc(sizeof(struct pthread))) != NULL)) { bzero(thread, sizeof(struct pthread)); - if ((thread->tcb = _tcb_ctor(thread)) == NULL) { + if ((thread->tcb = _tcb_ctor(thread, curthread == NULL)) == NULL) { free(thread); thread = NULL; } else { ==== //depot/projects/kse/lib/libthr/arch/i386/i386/_setcurthread.c#3 (text+ko) ==== @@ -61,15 +61,22 @@ { union descriptor desc; struct tcb *tcb; + void *oldtls; int ldt_index; *err = 0; + if (uc == NULL) { + __asm __volatile("movl %%gs:0, %0" : "=r" (oldtls)); + } else { + oldtls = NULL; + } + /* * Allocate and initialise a new TLS block with enough extra * space for our self pointer. */ - tcb = _rtld_allocate_tls(sizeof(struct tcb), 16); + tcb = _rtld_allocate_tls(oldtls, sizeof(struct tcb), 16); /* * Cache the address of the thread structure here, after ==== //depot/projects/kse/libexec/rtld-elf/i386/reloc.c#8 (text+ko) ==== @@ -349,14 +349,14 @@ } void * -allocate_tls(Objlist* list, size_t tcbsize, size_t tcbalign) +allocate_tls(Obj_Entry *objs, void *oldtls, size_t tcbsize, size_t tcbalign) { - Objlist_Entry *entry; Obj_Entry *obj; size_t size; char *tls; - Elf_Addr *dtv; - Elf_Addr segbase, addr; + Elf_Addr *dtv, *olddtv; + Elf_Addr segbase, oldsegbase, addr; + int i; size = round(tls_static_space, tcbalign); @@ -370,17 +370,45 @@ dtv[0] = tls_dtv_generation; dtv[1] = tls_max_index; - STAILQ_FOREACH(entry, list, link) { - obj = entry->obj; - if (obj->tlsoffset) { - addr = segbase - obj->tlsoffset; - memset((void*) (addr + obj->tlsinitsize), - 0, obj->tlssize - obj->tlsinitsize); - if (obj->tlsinit) - memcpy((void*) addr, obj->tlsinit, obj->tlsinitsize); - dtv[obj->tlsindex + 1] = addr; - } else if (obj->tlsindex) { - dtv[obj->tlsindex + 1] = 0; + + if (oldtls) { + /* + * Copy the static TLS block over whole. + */ + oldsegbase = (Elf_Addr) oldtls; + memcpy((void *)(segbase - tls_static_space), + (const void *)(oldsegbase - tls_static_space), + tls_static_space); + + /* + * If any dynamic TLS blocks have been created tls_get_addr(), + * move them over. + */ + olddtv = ((Elf_Addr**)oldsegbase)[1]; + for (i = 0; i < olddtv[1]; i++) { + if (olddtv[i+2] < oldsegbase - size || olddtv[i+2] > oldsegbase) { + dtv[i+2] = olddtv[i+2]; + olddtv[i+2] = 0; + } + } + + /* + * We assume that this block was the one we created below with + * allocate_initial_tls(). + */ + free_tls(oldtls, 2*sizeof(Elf_Addr), 4); + } else { + for (obj = objs; obj; obj = obj->next) { + if (obj->tlsoffset) { + addr = segbase - obj->tlsoffset; + memset((void*) (addr + obj->tlsinitsize), + 0, obj->tlssize - obj->tlsinitsize); + if (obj->tlsinit) + memcpy((void*) addr, obj->tlsinit, obj->tlsinitsize); + dtv[obj->tlsindex + 1] = addr; + } else if (obj->tlsindex) { + dtv[obj->tlsindex + 1] = 0; + } } } @@ -388,7 +416,7 @@ } void -free_tls(Objlist *list, void *tls, size_t tcbsize, size_t tcbalign) +free_tls(void *tls, size_t tcbsize, size_t tcbalign) { size_t size; Elf_Addr* dtv; @@ -415,7 +443,7 @@ } void -allocate_initial_tls(Objlist *list) +allocate_initial_tls(Obj_Entry *objs) { void* tls; union descriptor ldt; @@ -427,7 +455,7 @@ * use. */ tls_static_space = tls_last_offset + 64; - tls = allocate_tls(list, 2*sizeof(Elf_Addr), 4); + tls = allocate_tls(objs, NULL, 2*sizeof(Elf_Addr), 4); memset(&ldt, 0, sizeof(ldt)); ldt.sd.sd_lolimit = 0xffff; /* 4G limit */ ==== //depot/projects/kse/libexec/rtld-elf/rtld.c#12 (text+ko) ==== @@ -419,7 +419,7 @@ */ allocate_tls_offset(entry->obj); } - allocate_initial_tls(&list_main); + allocate_initial_tls(obj_list); /* Make a list of init functions to call. */ objlist_init(&initlist); @@ -2538,6 +2538,14 @@ { size_t off; + if (obj->tls_done) + return true; + + if (obj->tlssize == 0) { + obj->tls_done = true; + return true; + } + if (obj->tlsindex == 1) off = calculate_first_tls_offset(obj->tlssize, obj->tlsalign); else @@ -2563,13 +2571,13 @@ } void * -_rtld_allocate_tls(size_t tcbsize, size_t tcbalign) +_rtld_allocate_tls(void *oldtls, size_t tcbsize, size_t tcbalign) { - return allocate_tls(&list_main, tcbsize, tcbalign); + return allocate_tls(obj_list, oldtls, tcbsize, tcbalign); } void _rtld_free_tls(void *tcb, size_t tcbsize, size_t tcbalign) { - free_tls(&list_main, tcb, tcbsize, tcbalign); + free_tls(tcb, tcbsize, tcbalign); } ==== //depot/projects/kse/libexec/rtld-elf/rtld.h#7 (text+ko) ==== @@ -242,8 +242,8 @@ int reloc_non_plt(Obj_Entry *, Obj_Entry *); int reloc_plt(Obj_Entry *); int reloc_jmpslots(Obj_Entry *); -void *allocate_tls(Objlist *, size_t, size_t); -void free_tls(Objlist *, void *, size_t, size_t); -void allocate_initial_tls(Objlist *); +void *allocate_tls(Obj_Entry *, void *, size_t, size_t); +void free_tls(void *, size_t, size_t); +void allocate_initial_tls(Obj_Entry *); #endif /* } */ ==== //depot/projects/kse/libexec/rtld-elf/rtld_tls.h#2 (text+ko) ==== @@ -42,14 +42,22 @@ * 'Variant I' TLS, the thread local storage follows the TCB, and for * 'Variant II', the thread local storage precedes it. For * architectures using the 'Variant II' model (e.g. i386, amd64, - * sparc64), the TCB begin with two pointer fields which are used by - * rtld for its TLS implementation. For the 'Variant I' model, the TCB - * must begin with a single pointer field for rtld's implementation. + * sparc64), the TCB must begin with two pointer fields which are used + * by rtld for its TLS implementation. For the 'Variant I' model, the + * TCB must begin with a single pointer field for rtld's + * implementation. + * + * If the value of 'oldtls' is non-NULL, the new TLS block will be + * initialised using the values contained in 'oldtls' and 'oldtls' + * will be freed. This is typically used when initialising a thread + * library to migrate from using the initial bootstrap TLS block + * created by rtld to one which contains suitable thread library + * private data. * * The value returned from this function is suitable for installing * directly into the thread pointer register. */ -extern void *_rtld_allocate_tls(size_t tcbsize, size_t tcbalign); +extern void *_rtld_allocate_tls(void* oldtls, size_t tcbsize, size_t tcbalign); /* * Free a TLS block allocated using _rtld_allocate_tls(). The tcbsize