Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 9 Dec 2010 05:16:20 +0000 (UTC)
From:      David Xu <davidxu@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r216314 - head/sys/kern
Message-ID:  <201012090516.oB95GKoY025035@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: davidxu
Date: Thu Dec  9 05:16:20 2010
New Revision: 216314
URL: http://svn.freebsd.org/changeset/base/216314

Log:
  MFp4:
  The unit number allocator reuses ID too fast, this may hide bugs in
  other code, add a ring buffer to delay freeing a thread ID.

Modified:
  head/sys/kern/kern_thread.c

Modified: head/sys/kern/kern_thread.c
==============================================================================
--- head/sys/kern/kern_thread.c	Thu Dec  9 02:42:02 2010	(r216313)
+++ head/sys/kern/kern_thread.c	Thu Dec  9 05:16:20 2010	(r216314)
@@ -81,15 +81,54 @@ MTX_SYSINIT(zombie_lock, &zombie_lock, "
 
 static void thread_zombie(struct thread *);
 
+#define TID_BUFFER_SIZE	1024
+
 struct mtx tid_lock;
 static struct unrhdr *tid_unrhdr;
-
+static lwpid_t tid_buffer[TID_BUFFER_SIZE];
+static int tid_head, tid_tail;
 static MALLOC_DEFINE(M_TIDHASH, "tidhash", "thread hash");
 
 struct	tidhashhead *tidhashtbl;
 u_long	tidhash;
 struct	rwlock tidhash_lock;
 
+static lwpid_t
+tid_alloc(void)
+{
+	lwpid_t	tid;
+
+	tid = alloc_unr(tid_unrhdr);
+	if (tid != -1)
+		return (tid);
+	mtx_lock(&tid_lock);
+	if (tid_head == tid_tail) {
+		mtx_unlock(&tid_lock);
+		return (-1);
+	}
+	tid = tid_buffer[tid_head++];
+	tid_head %= TID_BUFFER_SIZE;
+	mtx_unlock(&tid_lock);
+	return (tid);
+}
+
+static void
+tid_free(lwpid_t tid)
+{
+	lwpid_t tmp_tid = -1;
+
+	mtx_lock(&tid_lock);
+	if ((tid_tail + 1) % TID_BUFFER_SIZE == tid_head) {
+		tmp_tid = tid_buffer[tid_head++];
+		tid_head = (tid_head + 1) % TID_BUFFER_SIZE;
+	}
+	tid_buffer[tid_tail++] = tid;
+	tid_tail %= TID_BUFFER_SIZE;
+	mtx_unlock(&tid_lock);
+	if (tmp_tid != -1)
+		free_unr(tid_unrhdr, tmp_tid);
+}
+
 /*
  * Prepare a thread for use.
  */
@@ -102,7 +141,7 @@ thread_ctor(void *mem, int size, void *a
 	td->td_state = TDS_INACTIVE;
 	td->td_oncpu = NOCPU;
 
-	td->td_tid = alloc_unr(tid_unrhdr);
+	td->td_tid = tid_alloc();
 
 	/*
 	 * Note that td_critnest begins life as 1 because the thread is not
@@ -156,7 +195,7 @@ thread_dtor(void *mem, int size, void *a
 	osd_thread_exit(td);
 
 	EVENTHANDLER_INVOKE(thread_dtor, td);
-	free_unr(tid_unrhdr, td->td_tid);
+	tid_free(td->td_tid);
 }
 
 /*



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