[TEST/REVIEW/PERF] kern_thread.c tid allocation patch

From: Poul-Henning Kamp <phk_at_phk.freebsd.dk>
Date: Thu, 17 Mar 2005 10:14:07 +0100
While investigating a Coverity report (false alarm btw) I noticed
that kern_thread has a lot of code for allocating thread id's.

This patch uses subr_unit instead.

I would expect thread create/destroy performance to increase on
systems where there are many threads, and would be interested
if anybody can measure any difference.

Poul-Henning


Index: kern/kern_thread.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_thread.c,v
retrieving revision 1.211
diff -u -r1.211 kern_thread.c
--- kern/kern_thread.c	5 Mar 2005 09:15:03 -0000	1.211
+++ kern/kern_thread.c	17 Mar 2005 09:07:45 -0000
_at__at_ -103,31 +103,8 _at__at_
 	0, sizeof(virtual_cpu), sysctl_kse_virtual_cpu, "I",
 	"debug virtual cpus");
 
-/*
- * Thread ID allocator. The allocator keeps track of assigned IDs by
- * using a bitmap. The bitmap is created in parts. The parts are linked
- * together.
- */
-typedef u_long tid_bitmap_word;
-
-#define	TID_IDS_PER_PART	1024
-#define	TID_IDS_PER_IDX		(sizeof(tid_bitmap_word) << 3)
-#define	TID_BITMAP_SIZE		(TID_IDS_PER_PART / TID_IDS_PER_IDX)
-#define	TID_MIN			(PID_MAX + 1)
-
-struct tid_bitmap_part {
-	STAILQ_ENTRY(tid_bitmap_part) bmp_next;
-	tid_bitmap_word	bmp_bitmap[TID_BITMAP_SIZE];
-	lwpid_t		bmp_base;
-	int		bmp_free;
-};
-
-static STAILQ_HEAD(, tid_bitmap_part) tid_bitmap =
-    STAILQ_HEAD_INITIALIZER(tid_bitmap);
-static uma_zone_t tid_zone;
-
 struct mtx tid_lock;
-MTX_SYSINIT(tid_lock, &tid_lock, "TID lock", MTX_DEF);
+static struct unrhdr *tid_unrhdr;
 
 /*
  * Prepare a thread for use.
_at__at_ -197,45 +174,10 _at__at_
 thread_init(void *mem, int size, int flags)
 {
 	struct thread *td;
-	struct tid_bitmap_part *bmp, *new;
-	int bit, idx;
 
 	td = (struct thread *)mem;
 
-	mtx_lock(&tid_lock);
-	STAILQ_FOREACH(bmp, &tid_bitmap, bmp_next) {
-		if (bmp->bmp_free)
-			break;
-	}
-	/* Create a new bitmap if we run out of free bits. */
-	if (bmp == NULL) {
-		mtx_unlock(&tid_lock);
-		new = uma_zalloc(tid_zone, M_WAITOK);
-		mtx_lock(&tid_lock);
-		bmp = STAILQ_LAST(&tid_bitmap, tid_bitmap_part, bmp_next);
-		if (bmp == NULL || bmp->bmp_free < TID_IDS_PER_PART/2) {
-			/* 1=free, 0=assigned. This way we can use ffsl(). */
-			memset(new->bmp_bitmap, ~0U, sizeof(new->bmp_bitmap));
-			new->bmp_base = (bmp == NULL) ? TID_MIN :
-			    bmp->bmp_base + TID_IDS_PER_PART;
-			new->bmp_free = TID_IDS_PER_PART;
-			STAILQ_INSERT_TAIL(&tid_bitmap, new, bmp_next);
-			bmp = new;
-			new = NULL;
-		}
-	} else
-		new = NULL;
-	/* We have a bitmap with available IDs. */
-	idx = 0;
-	while (idx < TID_BITMAP_SIZE && bmp->bmp_bitmap[idx] == 0UL)
-		idx++;
-	bit = ffsl(bmp->bmp_bitmap[idx]) - 1;
-	td->td_tid = bmp->bmp_base + idx * TID_IDS_PER_IDX + bit;
-	bmp->bmp_bitmap[idx] &= ~(1UL << bit);
-	bmp->bmp_free--;
-	mtx_unlock(&tid_lock);
-	if (new != NULL)
-		uma_zfree(tid_zone, new);
+	td->td_tid = alloc_unr(tid_unrhdr);
 
 	vm_thread_new(td, 0);
 	cpu_thread_setup(td);
_at__at_ -254,9 +196,6 _at__at_
 thread_fini(void *mem, int size)
 {
 	struct thread *td;
-	struct tid_bitmap_part *bmp;
-	lwpid_t tid;
-	int bit, idx;
 
 	td = (struct thread *)mem;
 	turnstile_free(td->td_turnstile);
_at__at_ -264,19 +203,7 _at__at_
 	umtxq_free(td->td_umtxq);
 	vm_thread_dispose(td);
 
-	STAILQ_FOREACH(bmp, &tid_bitmap, bmp_next) {
-		if (td->td_tid >= bmp->bmp_base &&
-		    td->td_tid < bmp->bmp_base + TID_IDS_PER_PART)
-			break;
-	}
-	KASSERT(bmp != NULL, ("No TID bitmap?"));
-	mtx_lock(&tid_lock);
-	tid = td->td_tid - bmp->bmp_base;
-	idx = tid / TID_IDS_PER_IDX;
-	bit = 1UL << (tid % TID_IDS_PER_IDX);
-	bmp->bmp_bitmap[idx] |= bit;
-	bmp->bmp_free++;
-	mtx_unlock(&tid_lock);
+	free_unr(tid_unrhdr, td->td_tid);
 }
 
 /*
_at__at_ -362,11 +289,12 _at__at_
 threadinit(void)
 {
 
+	mtx_init(&tid_lock, "TID lock", NULL, MTX_DEF);
+	tid_unrhdr = new_unrhdr(0, INT_MAX, &tid_lock);
+
 	thread_zone = uma_zcreate("THREAD", sched_sizeof_thread(),
 	    thread_ctor, thread_dtor, thread_init, thread_fini,
 	    UMA_ALIGN_CACHE, 0);
-	tid_zone = uma_zcreate("TID", sizeof(struct tid_bitmap_part),
-	    NULL, NULL, NULL, NULL, UMA_ALIGN_CACHE, 0);
 	ksegrp_zone = uma_zcreate("KSEGRP", sched_sizeof_ksegrp(),
 	    ksegrp_ctor, NULL, NULL, NULL,
 	    UMA_ALIGN_CACHE, 0);
-- 
Poul-Henning Kamp       | UNIX since Zilog Zeus 3.20
phk_at_FreeBSD.ORG         | TCP/IP since RFC 956
FreeBSD committer       | BSD since 4.3-tahoe
Never attribute to malice what can adequately be explained by incompetence.
Received on Thu Mar 17 2005 - 08:14:12 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:38:30 UTC