PERFORCE change 50408 for review
Doug Rabson
dfr at FreeBSD.org
Mon Apr 5 08:33:32 PDT 2004
http://perforce.freebsd.org/chv.cgi?CH=50408
Change 50408 by dfr at 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>
More information about the p4-projects
mailing list