Module Name:    src
Committed By:   pooka
Date:           Mon Nov 11 23:06:40 UTC 2013

Modified Files:
        src/sys/rump/librump/rumpkern: intr.c

Log Message:
Defer softint thread creation to first softint_establish() for that level.
Speeds up rump kernel bootstrap and saves memory -- very rarely are all
softint levels in a rump kernel used.


To generate a diff of this commit:
cvs rdiff -u -r1.40 -r1.41 src/sys/rump/librump/rumpkern/intr.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/rump/librump/rumpkern/intr.c
diff -u src/sys/rump/librump/rumpkern/intr.c:1.40 src/sys/rump/librump/rumpkern/intr.c:1.41
--- src/sys/rump/librump/rumpkern/intr.c:1.40	Thu May  2 21:45:28 2013
+++ src/sys/rump/librump/rumpkern/intr.c	Mon Nov 11 23:06:40 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: intr.c,v 1.40 2013/05/02 21:45:28 pooka Exp $	*/
+/*	$NetBSD: intr.c,v 1.41 2013/11/11 23:06:40 pooka Exp $	*/
 
 /*
  * Copyright (c) 2008-2010 Antti Kantee.  All Rights Reserved.
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.40 2013/05/02 21:45:28 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.41 2013/11/11 23:06:40 pooka Exp $");
 
 #include <sys/param.h>
 #include <sys/atomic.h>
@@ -188,11 +188,52 @@ sithread(void *arg)
 	panic("sithread unreachable");
 }
 
+static kmutex_t sithr_emtx;
+static unsigned int sithr_est;
+static int sithr_canest;
+
+/*
+ * Create softint handler threads when the softint for each respective
+ * level is established for the first time.  Most rump kernels don't
+ * need at least half of the softint levels, so on-demand saves bootstrap
+ * time and memory resources.  Note, though, that this routine may be
+ * called before it's possible to call kthread_create().  Creation of
+ * those softints (SOFTINT_CLOCK, as of writing this) will be deferred
+ * to until softint_init() is called for the main CPU.
+ */
+static void
+sithread_establish(int level)
+{
+	int docreate, rv;
+	int lvlbit = 1<<level;
+	int i;
+
+	KASSERT((level & ~SOFTINT_LVLMASK) == 0);
+	if (__predict_true(sithr_est & lvlbit))
+		return;
+
+	mutex_enter(&sithr_emtx);
+	docreate = (sithr_est & lvlbit) == 0 && sithr_canest;
+	sithr_est |= lvlbit;
+	mutex_exit(&sithr_emtx);
+
+	if (docreate) {
+		for (i = 0; i < ncpu_final; i++) {
+			if ((rv = kthread_create(PRI_NONE,
+			    KTHREAD_MPSAFE | KTHREAD_INTR,
+			    cpu_lookup(i), sithread, (void *)(uintptr_t)level,
+			    NULL, "rsi%d/%d", i, level)) != 0)
+				panic("softint thread create failed: %d", rv);
+		}
+	}
+}
+
 void
 rump_intr_init(int numcpu)
 {
 
 	cv_init(&lbolt, "oh kath ra");
+	mutex_init(&sithr_emtx, MUTEX_DEFAULT, IPL_NONE);
 	ncpu_final = numcpu;
 }
 
@@ -206,10 +247,23 @@ softint_init(struct cpu_info *ci)
 	if (!rump_threads)
 		return;
 
-	/* XXX */
+	/* overloaded global init ... */
 	if (ci->ci_index == 0) {
+		int sithr_swap;
+
 		rumptc.tc_frequency = hz;
 		tc_init(&rumptc);
+
+		/* create deferred softint threads */
+		mutex_enter(&sithr_emtx);
+		sithr_swap = sithr_est;
+		sithr_est = 0;
+		sithr_canest = 1;
+		mutex_exit(&sithr_emtx);
+		for (i = 0; i < SOFTINT_COUNT; i++) {
+			if (sithr_swap & (1<<i))
+				sithread_establish(i);
+		}
 	}
 
 	slev = kmem_alloc(sizeof(struct softint_lev) * SOFTINT_COUNT, KM_SLEEP);
@@ -219,19 +273,9 @@ softint_init(struct cpu_info *ci)
 	}
 	cd->cpu_softcpu = slev;
 
-	/* softint might run on different physical CPU */
-	membar_sync();
-
-	for (i = 0; i < SOFTINT_COUNT; i++) {
-		rv = kthread_create(PRI_NONE,
-		    KTHREAD_MPSAFE | KTHREAD_INTR, ci,
-		    sithread, (void *)(uintptr_t)i,
-		    NULL, "rsi%d/%d", ci->ci_index, i);
-	}
-
-	rv = kthread_create(PRI_NONE, KTHREAD_MPSAFE,
-	    ci, doclock, NULL, NULL, "rumpclk%d", ci->ci_index);
-	if (rv)
+	/* well, not really a "soft" interrupt ... */
+	if ((rv = kthread_create(PRI_NONE, KTHREAD_MPSAFE,
+	    ci, doclock, NULL, NULL, "rumpclk%d", ci->ci_index)) != 0)
 		panic("clock thread creation failed: %d", rv);
 }
 
@@ -240,13 +284,14 @@ softint_establish(u_int flags, void (*fu
 {
 	struct softint *si;
 	struct softint_percpu *sip;
+	int level = flags & SOFTINT_LVLMASK;
 	int i;
 
 	si = malloc(sizeof(*si), M_TEMP, M_WAITOK);
 	si->si_func = func;
 	si->si_arg = arg;
 	si->si_flags = flags & SOFTINT_MPSAFE ? SI_MPSAFE : 0;
-	si->si_level = flags & SOFTINT_LVLMASK;
+	si->si_level = level;
 	KASSERT(si->si_level < SOFTINT_COUNT);
 	si->si_entry = malloc(sizeof(*si->si_entry) * ncpu_final,
 	    M_TEMP, M_WAITOK | M_ZERO);
@@ -254,6 +299,7 @@ softint_establish(u_int flags, void (*fu
 		sip = &si->si_entry[i];
 		sip->sip_parent = si;
 	}
+	sithread_establish(level);
 
 	return si;
 }

Reply via email to