PERFORCE change 50101 for review
Marcel Moolenaar
marcel at FreeBSD.org
Wed Mar 31 22:36:34 PST 2004
http://perforce.freebsd.org/chv.cgi?CH=50101
Change 50101 by marcel at marcel_nfs on 2004/03/31 22:35:42
Implement some thread ID allocator. The fundamental properties
if the allocator are (or are assumed to be):
o Allocation of thread IDs must be fast,
o Immediate reuse of TIDs is not a problem because the TIDs
are only used in corefiles and for kernel debugging.
The allocator maintains a list of bitmaps. Each bitmap tracks
1024 TIDs. When all bitmaps are "full", the allocator creates
a new bitmap. When threads are destroyed, TIDs are freed in
the bitmap. Empty bitmaps are currently not destroyed.
The allocator is not tuned or even perfect. It works (AFAICT),
so it should suffice.
Affected files ...
.. //depot/projects/gdb/sys/kern/kern_thread.c#7 edit
Differences ...
==== //depot/projects/gdb/sys/kern/kern_thread.c#7 (text+ko) ====
@@ -133,6 +133,32 @@
"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];
+ int 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);
+
+/*
* Prepare a thread for use.
*/
static void
@@ -141,6 +167,7 @@
struct thread *td;
td = (struct thread *)mem;
+ td->td_tid = 0;
td->td_state = TDS_INACTIVE;
td->td_oncpu = NOCPU;
td->td_critnest = 1;
@@ -152,10 +179,28 @@
static void
thread_dtor(void *mem, int size, void *arg)
{
- struct thread *td;
+ struct thread *td;
+ struct tid_bitmap_part *bmp;
+ int bit, idx, tid;
td = (struct thread *)mem;
+ if (td->td_tid > PID_MAX) {
+ 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);
+ }
+
#ifdef INVARIANTS
/* Verify that this thread is in a safe state to free. */
switch (td->td_state) {
@@ -861,6 +906,8 @@
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(),
NULL, NULL, ksegrp_init, NULL,
UMA_ALIGN_CACHE, 0);
@@ -1032,14 +1079,50 @@
}
/*
- * Assign a thread ID between 100000 and 999999.
+ * Assign a thread ID.
*/
int
thread_new_tid(void)
{
- static int next_tid = 100000;
+ struct tid_bitmap_part *bmp, *new;
+ int bit, idx, tid;
+
+ 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;
+ tid = bmp->bmp_base + idx * TID_IDS_PER_IDX + bit;
+ bmp->bmp_bitmap[idx] &= ~(1UL << bit);
+ bmp->bmp_free--;
+ mtx_unlock(&tid_lock);
- return (next_tid++);
+ if (new != NULL)
+ uma_zfree(tid_zone, new);
+ return (tid);
}
/*
More information about the p4-projects
mailing list