Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 5 Apr 2004 08:33:30 -0700 (PDT)
From:      Doug Rabson <dfr@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 50408 for review
Message-ID:  <200404051533.i35FXUjd018384@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=50408

Change 50408 by dfr@dfr_home on 2004/04/05 08:33:17

	Wire up the TLS stuff to the thread libraries (i386 only).

Affected files ...

.. //depot/projects/kse/lib/libpthread/arch/i386/i386/pthread_md.c#2 edit
.. //depot/projects/kse/lib/libpthread/arch/i386/include/pthread_md.h#2 edit
.. //depot/projects/kse/lib/libthr/Makefile#2 edit
.. //depot/projects/kse/lib/libthr/arch/i386/i386/_curthread.S#2 edit
.. //depot/projects/kse/lib/libthr/arch/i386/i386/_setcurthread.c#2 edit
.. //depot/projects/kse/libexec/rtld-elf/i386/reloc.c#4 edit
.. //depot/projects/kse/libexec/rtld-elf/i386/rtld_machdep.h#5 edit
.. //depot/projects/kse/libexec/rtld-elf/rtld.c#6 edit
.. //depot/projects/kse/libexec/rtld-elf/rtld.h#4 edit
.. //depot/projects/kse/libexec/rtld-elf/rtld_tls.h#1 add
.. //depot/projects/kse/tools/regression/tls/Makefile#2 edit
.. //depot/projects/kse/tools/regression/tls/ttls2/Makefile#1 add
.. //depot/projects/kse/tools/regression/tls/ttls2/ttls2.c#1 add

Differences ...

==== //depot/projects/kse/lib/libpthread/arch/i386/i386/pthread_md.c#2 (text+ko) ====

@@ -39,35 +39,28 @@
 #include <string.h>
 #include <ucontext.h>
 
+#include "rtld_tls.h"
 #include "pthread_md.h"
 
 struct tcb *
 _tcb_ctor(struct pthread *thread)
 {
 	struct tcb *tcb;
-	void *addr;
 
-	addr = malloc(sizeof(struct tcb) + 15);
-	if (addr == NULL)
-		tcb = NULL;
-	else {
-		tcb = (struct tcb *)(((uintptr_t)(addr) + 15) & ~15);
-		bzero(tcb, sizeof(struct tcb));
-		tcb->tcb_addr = addr;
+	tcb = _rtld_allocate_tls(sizeof(struct tcb), 16);
+	if (tcb) {
 		tcb->tcb_thread = thread;
-		/* XXX - Allocate tdv/tls */
+		tcb->tcb_spare = 0;
+		bzero(&tcb->tcb_tmbx, sizeof(tcb->tcb_tmbx));
 	}
+
 	return (tcb);
 }
 
 void
 _tcb_dtor(struct tcb *tcb)
 {
-	void *addr;
-
-	addr = tcb->tcb_addr;
-	tcb->tcb_addr = NULL;
-	free(addr);
+	_rtld_free_tls(tcb, sizeof(struct tcb), 16);
 }
 
 /*

==== //depot/projects/kse/lib/libpthread/arch/i386/include/pthread_md.h#2 (text+ko) ====

@@ -47,7 +47,6 @@
 
 struct kse;
 struct pthread;
-struct tdv;
 
 /*
  * %gs points to a struct kcb.
@@ -61,9 +60,9 @@
 };
 
 struct tcb {
-	struct tdv		*tcb_tdv;
+	struct tcb		*tcb_self;	/* required by rtld */
+	void			*tcb_dtv;	/* required by rtld */
 	struct pthread		*tcb_thread;
-	void			*tcb_addr;	/* allocated tcb address */
 	void			*tcb_spare;	/* align tcb_tmbx to 16 bytes */
 	struct kse_thr_mailbox	tcb_tmbx;
 };

==== //depot/projects/kse/lib/libthr/Makefile#2 (text+ko) ====

@@ -13,6 +13,7 @@
 CFLAGS+=-DPTHREAD_KERNEL -D_THREAD_SAFE 
 CFLAGS+=-I${.CURDIR}/../libc/include -I${.CURDIR}/thread \
 	-I${.CURDIR}/../../include
+CFLAGS+=-I${.CURDIR}/../../libexec/rtld-elf
 
 # enable extra internal consistancy checks
 CFLAGS+=-D_PTHREADS_INVARIANTS

==== //depot/projects/kse/lib/libthr/arch/i386/i386/_curthread.S#2 (text+ko) ====

@@ -5,7 +5,7 @@
 ENTRY(_get_curthread)
 	cmpl	$0, _thread_initial
 	je	nothreads
-	movl	%gs:0, %eax
+	movl	%gs:8, %eax
 	ret
 nothreads:
 	xor	%eax, %eax

==== //depot/projects/kse/lib/libthr/arch/i386/i386/_setcurthread.c#2 (text+ko) ====

@@ -38,112 +38,60 @@
 #include <machine/segments.h>
 
 #include "thr_private.h"
-
-#define	MAXTHR	8192
+#include "rtld_tls.h"
 
-#define	LDT_INDEX(x)	(((long)(x) - (long)ldt_entries) / sizeof(ldt_entries[0]))
-
-void		**ldt_free = NULL;
-void		 *ldt_entries[MAXTHR];
-static int	  ldt_inited = 0;
-static spinlock_t ldt_lock = _SPINLOCK_INITIALIZER;
-
-static void ldt_init(void);
-
 /* in _curthread.S */
 extern void _set_gs(int);
 
-/*
- * Initialize the array of ldt_entries and the next free slot.
- * This routine must be called with the global ldt lock held.
- */
-static void
-ldt_init(void)
-{
-	int i;
+struct tcb {
+	struct tcb		*tcb_self;	/* required by rtld */
+	void			*tcb_dtv;	/* required by rtld */
+	struct pthread		*tcb_thread;
+};
 
-	ldt_free = &ldt_entries[NLDT];
-
-	for (i = 0; i < MAXTHR - 1; i++)
-		ldt_entries[i] = (void *)&ldt_entries[i + 1];
-
-	ldt_entries[MAXTHR - 1] = NULL;
-
-	ldt_inited = 1;
-}
-
 void
 _retire_thread(void *entry)
 {
-	_spinlock(&ldt_lock);
-	if (ldt_free == NULL)
-		*(void **)entry = NULL;
-	else
-		*(void **)entry = *ldt_free;
-	ldt_free = entry;
-	_spinunlock(&ldt_lock);
+	_rtld_free_tls(entry, sizeof(struct tcb), 16);
+	/* XXX free ldt descriptor here */
 }
 
 void *
 _set_curthread(ucontext_t *uc, struct pthread *thr, int *err)
 {
 	union descriptor desc;
-	void **ldt_entry;
+	struct tcb *tcb;
 	int ldt_index;
 
 	*err = 0;
 
 	/*
-	 * If we are setting up the initial thread, the gs register
-	 * won't be setup for the current thread. In any case, we
-	 * don't need protection from re-entrancy at this point in
-	 * the life of the program.
+	 * Allocate and initialise a new TLS block with enough extra
+	 * space for our self pointer.
 	 */
-	if (thr != _thread_initial)
-		_SPINLOCK(&ldt_lock);
+	tcb = _rtld_allocate_tls(sizeof(struct tcb), 16);
 
-	if (ldt_inited == 0)
-		ldt_init();
-
-	if (ldt_free == NULL) {
-		/* Concurrent thread limit reached */
-		*err = curthread->error = EAGAIN;
-		if (thr != _thread_initial)
-			_SPINUNLOCK(&ldt_lock);
-		return (NULL);
-	}
-
 	/*
-	 * Pull one off of the free list and update the free list pointer.
+	 * Cache the address of the thread structure here, after
+	 * rtld's two words of private space.
 	 */
-	ldt_entry = ldt_free;
-	ldt_free = (void **)*ldt_entry;
+	tcb->tcb_thread = thr;
 
-	if (thr != _thread_initial)
-		_SPINUNLOCK(&ldt_lock);
-
-	/*
-	 * Cache the address of the thread structure here.  This is
-	 * what the gs register will point to.
-	 */
-	*ldt_entry = (void *)thr;
-
 	bzero(&desc, sizeof(desc));
 
 	/*
-	 * Set up the descriptor to point into the ldt table which contains
-	 * only a pointer to the thread.
+	 * Set up the descriptor to point at the TLS block.
 	 */
-	desc.sd.sd_lolimit = sizeof(*ldt_entry);
-	desc.sd.sd_lobase = (unsigned int)ldt_entry & 0xFFFFFF;
-	desc.sd.sd_type = SDT_MEMRO;
+	desc.sd.sd_lolimit = 0xFFFF;
+	desc.sd.sd_lobase = (unsigned int)tcb & 0xFFFFFF;
+	desc.sd.sd_type = SDT_MEMRW;
 	desc.sd.sd_dpl = SEL_UPL;
 	desc.sd.sd_p = 1;
-	desc.sd.sd_hilimit = 0;
+	desc.sd.sd_hilimit = 0xF;
 	desc.sd.sd_xx = 0;
 	desc.sd.sd_def32 = 1;
-	desc.sd.sd_gran = 0;
-	desc.sd.sd_hibase = (unsigned int)ldt_entry >> 24;
+	desc.sd.sd_gran = 1;
+	desc.sd.sd_hibase = (unsigned int)tcb >> 24;
 
 	/* Get a slot from the process' LDT list */
 	ldt_index = i386_set_ldt(LDT_AUTO_ALLOC, &desc, 1);
@@ -158,5 +106,5 @@
 	else
 		_set_gs(LSEL(ldt_index, SEL_UPL));
 
-	return (ldt_entry);
+	return (tcb);
 }

==== //depot/projects/kse/libexec/rtld-elf/i386/reloc.c#4 (text+ko) ====

@@ -332,24 +332,26 @@
     return 0;
 }
 
-void
-allocate_initial_tls(Obj_Entry *list)
+void *
+allocate_tls(Objlist* list, size_t tcbsize, size_t tcbalign)
 {
+    Objlist_Entry *entry;
     Obj_Entry *obj;
     size_t size;
     char *tls;
     Elf_Addr *dtv;
-    union descriptor ldt;
     Elf_Addr segbase;
-    int sel;
 
     size = 0;
-    for (obj = list; obj; obj = obj->next) {
+    STAILQ_FOREACH(entry, list, link) {
+	obj = entry->obj;
         if (obj->tlsoffset > size)
             size = obj->tlsoffset;
     }
+    size = round(size, tcbalign);
 
-    tls = malloc(size + 2*sizeof(Elf_Addr));
+    assert(tcbsize >= 2*sizeof(Elf_Addr));
+    tls = malloc(size + tcbsize);
     dtv = malloc((tls_max_index + 2) * sizeof(Elf_Addr));
 
     segbase = (Elf_Addr)(tls + size);
@@ -358,7 +360,8 @@
 
     dtv[0] = tls_dtv_generation;
     dtv[1] = tls_max_index;
-    for (obj = list; obj; obj = obj->next) {
+    STAILQ_FOREACH(entry, list, link) {
+	obj = entry->obj;
 	Elf_Addr addr = segbase - obj->tlsoffset;
 	memset((void*) (addr + obj->tlsinitsize),
 	       0, obj->tlssize - obj->tlsinitsize);
@@ -367,16 +370,61 @@
 	dtv[obj->tlsindex] = addr;
     }
 
+    return (void*) segbase;
+}
+
+void
+free_tls(Objlist *list, void *tls, size_t tcbsize, size_t tcbalign)
+{
+    Objlist_Entry *entry;
+    Obj_Entry *obj;
+    size_t size;
+    Elf_Addr* dtv;
+    int dtvsize, i;
+    Elf_Addr tlsstart, tlsend;
+
+    /*
+     * Figure out the size of the initial TLS block so that we can
+     * find stuff which ___tls_get_addr() allocated dynamically.
+     */
+    size = 0;
+    STAILQ_FOREACH(entry, list, link) {
+	obj = entry->obj;
+        if (obj->tlsoffset > size)
+            size = obj->tlsoffset;
+    }
+    size = round(size, tcbalign);
+
+    dtv = ((Elf_Addr**)tls)[1];
+    dtvsize = dtv[1];
+    tlsend = (Elf_Addr) tls;
+    tlsstart = tlsend - size;
+    for (i = 0; i < dtvsize; i++) {
+	if (dtv[i+2] < tlsstart || dtv[i+2] > tlsend) {
+	    free((void*) dtv[i+2]);
+	}
+    }
+
+    free((void*) tlsstart);
+}
+
+void
+allocate_initial_tls(Objlist *list)
+{
+    void* tls = allocate_tls(list, 2*sizeof(Elf_Addr), 4);
+    union descriptor ldt;
+    int sel;
+
     memset(&ldt, 0, sizeof(ldt));
     ldt.sd.sd_lolimit = 0xffff;	/* 4G limit */
-    ldt.sd.sd_lobase = segbase & 0xffffff;
+    ldt.sd.sd_lobase = ((Elf_Addr)tls) & 0xffffff;
     ldt.sd.sd_type = SDT_MEMRWA;
     ldt.sd.sd_dpl = SEL_UPL;
     ldt.sd.sd_p = 1;		/* present */
     ldt.sd.sd_hilimit = 0xf;	/* 4G limit */
     ldt.sd.sd_def32 = 1;	/* 32 bit */
     ldt.sd.sd_gran = 1;		/* limit in pages */
-    ldt.sd.sd_hibase = (segbase >> 24) & 0xff;
+    ldt.sd.sd_hibase = (((Elf_Addr)tls) >> 24) & 0xff;
     sel = i386_set_ldt(LDT_AUTO_ALLOC, &ldt, 1);
     __asm __volatile("movl %0,%%gs" : : "rm" ((sel << 3) | 7));
 }

==== //depot/projects/kse/libexec/rtld-elf/i386/rtld_machdep.h#5 (text+ko) ====


==== //depot/projects/kse/libexec/rtld-elf/rtld.c#6 (text+ko) ====

@@ -53,6 +53,7 @@
 #include "debug.h"
 #include "rtld.h"
 #include "libmap.h"
+#include "rtld_tls.h"
 
 #ifndef COMPAT_32BIT
 #define PATH_RTLD	"/libexec/ld-elf.so.1"
@@ -182,6 +183,8 @@
     (func_ptr_type) &___tls_get_addr,
 #endif
     (func_ptr_type) &__tls_get_addr,
+    (func_ptr_type) &_rtld_allocate_tls,
+    (func_ptr_type) &_rtld_free_tls,
     NULL
 };
 
@@ -404,7 +407,7 @@
 
     /* setup TLS for main thread */
     dbg("initializing initial thread local storage");
-    allocate_initial_tls(obj_list);
+    allocate_initial_tls(&list_main);
 
     /* Make a list of init functions to call. */
     objlist_init(&initlist);
@@ -2486,7 +2489,7 @@
 
     /* Dynamically allocate module TLS if necessary */
     if (!dtv[index + 1])
-	dtv[index + 1] = (Elf_Addr)allocate_tls(index);
+	dtv[index + 1] = (Elf_Addr)allocate_module_tls(index);
 
     return (void*) (dtv[index + 1] + offset);
 }
@@ -2495,7 +2498,7 @@
  * Allocate TLS block for module with given index.
  */
 void *
-allocate_tls(int index)
+allocate_module_tls(int index)
 {
     Obj_Entry* obj;
     char* p;
@@ -2515,3 +2518,15 @@
 
     return p;
 }
+
+void *
+_rtld_allocate_tls(size_t tcbsize, size_t tcbalign)
+{
+    return allocate_tls(&list_main, tcbsize, tcbalign);
+}
+
+void
+_rtld_free_tls(void *tcb, size_t tcbsize, size_t tcbalign)
+{
+    free_tls(&list_main, tcb, tcbsize, tcbalign);
+}

==== //depot/projects/kse/libexec/rtld-elf/rtld.h#4 (text+ko) ====

@@ -229,7 +229,7 @@
 const Elf_Sym *symlook_obj(const char *, unsigned long,
   const Obj_Entry *, bool);
 void *tls_get_addr_common(Elf_Addr** dtvp, int index, size_t offset);
-void *allocate_tls(int index);
+void *allocate_module_tls(int index);
 
 /*
  * MD function declarations.
@@ -238,6 +238,8 @@
 int reloc_non_plt(Obj_Entry *, Obj_Entry *);
 int reloc_plt(Obj_Entry *);
 int reloc_jmpslots(Obj_Entry *);
-void allocate_initial_tls(Obj_Entry *);
+void *allocate_tls(Objlist *, size_t, size_t);
+void free_tls(Objlist *, void *, size_t, size_t);
+void allocate_initial_tls(Objlist *);
 
 #endif /* } */

==== //depot/projects/kse/tools/regression/tls/Makefile#2 (text+ko) ====

@@ -1,3 +1,3 @@
-SUBDIR=libxx libyy ttls1
+SUBDIR=libxx libyy ttls1 ttls2
 
 .include <bsd.subdir.mk>



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200404051533.i35FXUjd018384>