Date: Tue, 5 Aug 2003 19:44:51 -0400 (EDT) From: Daniel Eischen <eischen@vigrid.com> To: Mike Makonnen <mtm@identd.net> Cc: Marcel Moolenaar <marcel@xcllnt.net> Subject: Re: cvs commit: src/sys/i386/i386 sys_machdep.c Message-ID: <Pine.GSO.4.10.10308051940540.6797-100000@pcnet5.pcnet.com> In-Reply-To: <20030805231633.GA24684@kokeb.ambesa.net>
next in thread | previous in thread | raw e-mail | index | archive | help
On Tue, 5 Aug 2003, Mike Makonnen wrote: > On Sat, Aug 02, 2003 at 02:03:39PM -0700, Marcel Moolenaar wrote: > > On Sat, Aug 02, 2003 at 03:52:44PM -0400, Mike Makonnen wrote: > > > > > > As I indicated to Julian, I don't have time to do this now. I will > > > be going off-line in a couple of weeks for I don't know how long. > > > In the mean time I have a bunch of other stuff I have to get to. > > > But, if someone else wants to do it I can tell you exactly > > > what you need to do. It's relatively simple. > > > > Can you post the description to threads@? > > I'll see if I can find a spare moment... > > When I went back over the code, to write this summary > I found it is going to be much easier than I thought > at first. Assuming, i386_set_ldt() returns the auto-allocated > LDT slot we just have to load that into %gs, instead of > the ldt_index (which points into the ldt_entries array). > > So, if someone can tell me what the magic number for > auto-allocation is I can take care of this tonight. But, > because I'll be offline soon I'll go ahead and post > the background on how that code works just in case someone > needs to mess with it. > > The pointers to pthread structures are kept in the array > ldt_entries[MAX_THR]. Currently, MAX_THR is set to 128, but > since we start at index NLDT the maximum number of simultaneous > threads in an application is MAX_THR - NLDT. The global variable > ldt_free is used to keep track of the next free index in the > array. To facilitate this, when libthr is first initialized > each entry in the array contains a pointer to the next free > index. The ldt_free variable is then set to point to the first > free entry in the array (ldt_entries[NLDT]) and the contents > of that index (as preveiously stated) will be a pointer to > the next free entry in the array (in this case > ldt_entries[NLDT + 1]). When a new pthread is created, ldt_free > is dereferenced to find the next empty entry. It is set to this > entry and the contents of the previous entry it pointed to > are overwritten with the address of the newly created pthread. > When a thread exits the array index it occupied is overwritten > by a pointer to ldt_free and ldt_free is pointed to the > array index that held the just freed pthread. > > Another thing that happens when a new pthread is created is that > we setup a segment descriptor structure which points into the > ldt_entries entry we just setup for our newly created pthread. > This segment descripter pointing into ldt_entries is what is > passed into i386_set_ldt(). If the call to i386_set_ldt() succeeds > we then load the LDT index into %gs. > > So, there should be no need to bump up any limits or anything > to accomodate this change. Code says it so much better than words. Here's a quick attempt to show you what is needed. I took the liberty of simplifying it a bit since with auto ldt allocation, I don't think there's any need to have a predetermined number of slots (it also eliminates the need to lock the entry array). Watch out for any line wraps... -- Dan Eischen Index: arch/i386/i386/_setcurthread.c =================================================================== RCS file: /opt/FreeBSD/cvs/src/lib/libthr/arch/i386/i386/_setcurthread.c,v retrieving revision 1.10 diff -u -r1.10 _setcurthread.c --- arch/i386/i386/_setcurthread.c 29 Jun 2003 00:12:39 -0000 1.10 +++ arch/i386/i386/_setcurthread.c 5 Aug 2003 23:36:10 -0000 @@ -39,105 +39,34 @@ #include "thr_private.h" -#define MAXTHR 128 - -#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; - - 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); + int ldt; + + ldt = (int)entry; + if (ldt >= 0) + i386_set_ldt(ldt, NULL, 1); } void * _set_curthread(ucontext_t *uc, struct pthread *thr, int *err) { union descriptor desc; - void **ldt_entry; int ldt_index; - int error; *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. - */ - if (thr != _thread_initial) - _SPINLOCK(&ldt_lock); - - if (ldt_inited == NULL) - 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. - */ - ldt_entry = ldt_free; - ldt_free = (void **)*ldt_entry; - - 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; - ldt_index = LDT_INDEX(ldt_entry); - bzero(&desc, sizeof(desc)); /* * Set up the descriptor to point into the ldt table which contains * only a pointer to the thread. */ - desc.sd.sd_lolimit = sizeof(*ldt_entry); - desc.sd.sd_lobase = (unsigned int)ldt_entry & 0xFFFFFF; + desc.sd.sd_lolimit = sizeof(*thr); + desc.sd.sd_lobase = (unsigned int)thr & 0xFFFFFF; desc.sd.sd_type = SDT_MEMRO; desc.sd.sd_dpl = SEL_UPL; desc.sd.sd_p = 1; @@ -145,19 +74,19 @@ 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_hibase = (unsigned int)thr >> 24; - error = i386_set_ldt(ldt_index, &desc, 1); - if (error == -1) - abort(); - - /* - * Set up our gs with the index into the ldt for this entry. - */ - if (uc != NULL) - uc->uc_mcontext.mc_gs = LSEL(ldt_index, SEL_UPL); - else - _set_gs(LSEL(ldt_index, SEL_UPL)); - - return (ldt_entry); + ldt_index = i386_set_ldt(LDT_AUTO_ALLOC, &desc, 1); + if (ldt_index < 0) + *err = EAGAIN; + else { + /* + * Set up our gs with the ldt index. + */ + if (uc != NULL) + uc->uc_mcontext.mc_gs = LSEL(ldt_index, SEL_UPL); + else + _set_gs(LSEL(ldt_index, SEL_UPL)); + } + return ((void *)ldt_index); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.GSO.4.10.10308051940540.6797-100000>