Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 13 Aug 2004 22:07:44 GMT
From:      David Xu <davidxu@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 59595 for review
Message-ID:  <200408132207.i7DM7iHt006464@repoman.freebsd.org>

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

Change 59595 by davidxu@davidxu_alona on 2004/08/13 22:07:09

	Fix ldt entry leak bug, remember ldt index, so we can free idt entry in retire_thread.
	Allow a thread allocated a ltd entry to set its gs.

Affected files ...

.. //depot/projects/davidxu_ksedbg/src/lib/libthr/arch/i386/i386/_setcurthread.c#2 edit

Differences ...

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

@@ -41,12 +41,15 @@
 
 #define	MAXTHR	8192
 
-#define	LDT_INDEX(x)	(((long)(x) - (long)ldt_entries) / sizeof(ldt_entries[0]))
+struct ldt_entry {
+	void *ptr;
+	int   ldt;
+};
 
-void		**ldt_free = NULL;
-void		 *ldt_entries[MAXTHR];
-static int	  ldt_inited = 0;
-static spinlock_t ldt_lock = _SPINLOCK_INITIALIZER;
+struct ldt_entry	*ldt_free = NULL;
+struct ldt_entry	ldt_entries[MAXTHR];
+static int		ldt_inited = 0;
+static spinlock_t	ldt_lock = _SPINLOCK_INITIALIZER;
 
 static void ldt_init(void);
 
@@ -62,25 +65,28 @@
 {
 	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_free = &ldt_entries[0];
+	for (i = 0; i < MAXTHR - 1; i++) {
+		ldt_entries[i].ptr = &ldt_entries[i + 1];
+		ldt_entries[i].ldt = -1;
+	}
+	ldt_entries[MAXTHR - 1].ptr = NULL;
+	ldt_entries[MAXTHR - 1].ldt = -1;
 	ldt_inited = 1;
 }
 
 void
 _retire_thread(void *entry)
 {
+	struct ldt_entry *le = (struct ldt_entry *)entry;
+
 	_spinlock(&ldt_lock);
-	if (ldt_free == NULL)
-		*(void **)entry = NULL;
-	else
-		*(void **)entry = *ldt_free;
-	ldt_free = entry;
+	le->ptr = ldt_free;
+	ldt_free = le;
+	if (le->ldt != -1) {
+		i386_set_ldt(le->ldt, NULL, 1);
+		le->ldt = -1;
+	}
 	_spinunlock(&ldt_lock);
 }
 
@@ -88,11 +94,16 @@
 _set_curthread(ucontext_t *uc, struct pthread *thr, int *err)
 {
 	union descriptor desc;
-	void **ldt_entry;
+	struct ldt_entry *ldt_entry;
 	int ldt_index;
 
 	*err = 0;
 
+	if (thr->arch_id != NULL) {
+		ldt_entry = thr->arch_id;
+		ldt_index = ldt_entry->ldt;
+		goto set_seg;
+	}
 	/*
 	 * If we are setting up the initial thread, the gs register
 	 * won't be setup for the current thread. In any case, we
@@ -117,7 +128,7 @@
 	 * Pull one off of the free list and update the free list pointer.
 	 */
 	ldt_entry = ldt_free;
-	ldt_free = (void **)*ldt_entry;
+	ldt_free = ldt_entry->ptr;
 
 	if (thr != _thread_initial)
 		_SPINUNLOCK(&ldt_lock);
@@ -126,7 +137,7 @@
 	 * Cache the address of the thread structure here.  This is
 	 * what the gs register will point to.
 	 */
-	*ldt_entry = (void *)thr;
+	ldt_entry->ptr = (void *)thr;
 
 	bzero(&desc, sizeof(desc));
 
@@ -149,7 +160,9 @@
 	ldt_index = i386_set_ldt(LDT_AUTO_ALLOC, &desc, 1);
 	if (ldt_index == -1)
 		abort();
+	ldt_entry->ldt = ldt_index;
 
+set_seg:
 	/*
 	 * Set up our gs with the index into the ldt for this entry.
 	 */



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