Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 1 Dec 2007 21:51:27 GMT
From:      Peter Wemm <peter@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 129904 for review
Message-ID:  <200712012151.lB1LpRUd077147@repoman.freebsd.org>

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

Change 129904 by peter@peter_daintree on 2007/12/01 21:50:42

	IFC

Affected files ...

.. //depot/projects/bike_sched/sys/dev/si/si_pci.c#3 integrate
.. //depot/projects/bike_sched/sys/i386/i386/intr_machdep.c#6 integrate
.. //depot/projects/bike_sched/sys/kern/init_sysent.c#6 integrate
.. //depot/projects/bike_sched/sys/kern/kern_clock.c#4 integrate
.. //depot/projects/bike_sched/sys/kern/kern_intr.c#5 integrate
.. //depot/projects/bike_sched/sys/kern/kern_switch.c#4 integrate

Differences ...

==== //depot/projects/bike_sched/sys/dev/si/si_pci.c#3 (text+ko) ====

@@ -19,7 +19,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/si/si_pci.c,v 1.9 2007/02/23 19:33:07 imp Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/si/si_pci.c,v 1.10 2007/12/01 20:39:47 peter Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -105,6 +105,29 @@
 		goto fail;
 	}
 
+	if (pci_get_devid(dev) == 0x200011cb) {
+		int rid;
+		struct resource *plx_res;
+		uint32_t *addr;
+		uint32_t oldvalue;
+
+		/* Perform a PLX control register fixup */
+		rid = PCIR_BAR(0);
+		plx_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+		    RF_ACTIVE);
+		if (plx_res == NULL) {
+			device_printf(dev, "couldn't map plx registers\n");
+		} else {
+			addr = rman_get_virtual(plx_res);
+			oldvalue = addr[0x50 / 4];
+			if (oldvalue != 0x18260000) {
+				device_printf(dev, "PLX register 0x50: 0x%08x changed to 0x%08x\n", oldvalue, 0x18260000);
+				addr[0x50 / 4] = 0x18260000;
+			}
+			bus_release_resource(dev, SYS_RES_MEMORY, rid, plx_res);
+		}
+	}
+
 	error = siattach(dev);
 	if (error)
 		goto fail;

==== //depot/projects/bike_sched/sys/i386/i386/intr_machdep.c#6 (text+ko) ====

@@ -26,7 +26,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/sys/i386/i386/intr_machdep.c,v 1.19 2006/07/12 21:22:43 jhb Exp $
+ * $FreeBSD: src/sys/i386/i386/intr_machdep.c,v 1.30 2007/11/21 04:03:50 scottl Exp $
  */
 
 /*
@@ -42,15 +42,17 @@
 #include <sys/param.h>
 #include <sys/bus.h>
 #include <sys/interrupt.h>
-#include <sys/lock.h>
 #include <sys/ktr.h>
 #include <sys/kernel.h>
+#include <sys/lock.h>
 #include <sys/mutex.h>
 #include <sys/proc.h>
 #include <sys/syslog.h>
 #include <sys/systm.h>
+#include <sys/sx.h>
 #include <machine/clock.h>
 #include <machine/intr_machdep.h>
+#include <machine/smp.h>
 #ifdef DDB
 #include <ddb/ddb.h>
 #endif
@@ -60,8 +62,15 @@
 typedef void (*mask_fn)(void *);
 
 static int intrcnt_index;
-static struct mtx intr_table_lock;
+static struct sx intr_table_lock;
+static struct mtx intrcnt_lock;
+static STAILQ_HEAD(, pic) pics;
 
+#ifdef INTR_FILTER
+static void intr_eoi_src(void *arg);
+static void intr_disab_eoi_src(void *arg);
+static void intr_event_stray(void *cookie);
+#endif
 struct intsrc *interrupt_sources[NUM_IO_INTS];
 
 #ifdef SMP
@@ -71,10 +80,45 @@
 #endif
 
 static void	intr_init(void *__dummy);
+static int	intr_pic_registered(struct pic *pic);
 static void	intrcnt_setname(const char *name, int index);
 static void	intrcnt_updatename(struct intsrc *is);
 static void	intrcnt_register(struct intsrc *is);
 
+static int
+intr_pic_registered(struct pic *pic)
+{
+	struct pic *p;
+
+	STAILQ_FOREACH(p, &pics, pics) {
+		if (p == pic)
+			return (1);
+	}
+	return (0);
+}
+
+/*
+ * Register a new interrupt controller (PIC).  This is to support suspend
+ * and resume where we suspend/resume controllers rather than individual
+ * sources.  This also allows controllers with no active sources (such as
+ * 8259As in a system using the APICs) to participate in suspend and resume.
+ */
+int
+intr_register_pic(struct pic *pic)
+{
+	int error;
+
+	sx_xlock(&intr_table_lock);
+	if (intr_pic_registered(pic))
+		error = EBUSY;
+	else {
+		STAILQ_INSERT_TAIL(&pics, pic, pics);
+		error = 0;
+	}
+	sx_xunlock(&intr_table_lock);
+	return (error);
+}
+
 /*
  * Register a new interrupt source with the global interrupt system.
  * The global interrupts need to be disabled when this function is
@@ -85,23 +129,30 @@
 {
 	int error, vector;
 
+	KASSERT(intr_pic_registered(isrc->is_pic), ("unregistered PIC"));
 	vector = isrc->is_pic->pic_vector(isrc);
 	if (interrupt_sources[vector] != NULL)
 		return (EEXIST);
+#ifdef INTR_FILTER
+	error = intr_event_create(&isrc->is_event, isrc, 0,
+	    (mask_fn)isrc->is_pic->pic_enable_source,
+	    intr_eoi_src, intr_disab_eoi_src, "irq%d:", vector);
+#else
 	error = intr_event_create(&isrc->is_event, isrc, 0,
 	    (mask_fn)isrc->is_pic->pic_enable_source, "irq%d:", vector);
+#endif
 	if (error)
 		return (error);
-	mtx_lock_spin(&intr_table_lock);
+	sx_xlock(&intr_table_lock);
 	if (interrupt_sources[vector] != NULL) {
-		mtx_unlock_spin(&intr_table_lock);
+		sx_xunlock(&intr_table_lock);
 		intr_event_destroy(isrc->is_event);
 		return (EEXIST);
 	}
 	intrcnt_register(isrc);
 	interrupt_sources[vector] = isrc;
-	isrc->is_enabled = 0;
-	mtx_unlock_spin(&intr_table_lock);
+	isrc->is_handlers = 0;
+	sx_xunlock(&intr_table_lock);
 	return (0);
 }
 
@@ -113,8 +164,8 @@
 }
 
 int
-intr_add_handler(const char *name, int vector, driver_intr_t handler,
-    void *arg, enum intr_type flags, void **cookiep)
+intr_add_handler(const char *name, int vector, driver_filter_t filter,
+    driver_intr_t handler, void *arg, enum intr_type flags, void **cookiep)
 {
 	struct intsrc *isrc;
 	int error;
@@ -122,22 +173,21 @@
 	isrc = intr_lookup_source(vector);
 	if (isrc == NULL)
 		return (EINVAL);
-	error = intr_event_add_handler(isrc->is_event, name, handler, arg,
-	    intr_priority(flags), flags, cookiep);
+	error = intr_event_add_handler(isrc->is_event, name, filter, handler,
+	    arg, intr_priority(flags), flags, cookiep);
 	if (error == 0) {
+		sx_xlock(&intr_table_lock);
 		intrcnt_updatename(isrc);
-		mtx_lock_spin(&intr_table_lock);
-		if (!isrc->is_enabled) {
-			isrc->is_enabled = 1;
+		isrc->is_handlers++;
+		if (isrc->is_handlers == 1) {
 #ifdef SMP
 			if (assign_cpu)
 				intr_assign_next_cpu(isrc);
 #endif
-			mtx_unlock_spin(&intr_table_lock);
 			isrc->is_pic->pic_enable_intr(isrc);
-		} else
-			mtx_unlock_spin(&intr_table_lock);
-		isrc->is_pic->pic_enable_source(isrc);
+			isrc->is_pic->pic_enable_source(isrc);
+		}
+		sx_xunlock(&intr_table_lock);
 	}
 	return (error);
 }
@@ -145,13 +195,21 @@
 int
 intr_remove_handler(void *cookie)
 {
+	struct intsrc *isrc;
 	int error;
 
+	isrc = intr_handler_source(cookie);
 	error = intr_event_remove_handler(cookie);
-#ifdef XXX
-	if (error == 0)
-		intrcnt_updatename(/* XXX */);
-#endif
+	if (error == 0) {
+		sx_xlock(&intr_table_lock);
+		isrc->is_handlers--;
+		if (isrc->is_handlers == 0) {
+			isrc->is_pic->pic_disable_source(isrc, PIC_NO_EOI);
+			isrc->is_pic->pic_disable_intr(isrc);
+		}
+		intrcnt_updatename(isrc);
+		sx_xunlock(&intr_table_lock);
+	}
 	return (error);
 }
 
@@ -166,13 +224,84 @@
 	return (isrc->is_pic->pic_config_intr(isrc, trig, pol));
 }
 
+#ifdef INTR_FILTER
 void
+intr_execute_handlers(struct intsrc *isrc, struct trapframe *frame)
+{
+	struct thread *td;
+	struct intr_event *ie;
+	int vector;
+
+	td = curthread;
+
+	/*
+	 * We count software interrupts when we process them.  The
+	 * code here follows previous practice, but there's an
+	 * argument for counting hardware interrupts when they're
+	 * processed too.
+	 */
+	(*isrc->is_count)++;
+	PCPU_INC(cnt.v_intr);
+
+	ie = isrc->is_event;
+
+	/*
+	 * XXX: We assume that IRQ 0 is only used for the ISA timer
+	 * device (clk).
+	 */
+	vector = isrc->is_pic->pic_vector(isrc);
+	if (vector == 0)
+		clkintr_pending = 1;
+
+	if (intr_event_handle(ie, frame) != 0)
+		intr_event_stray(isrc);		
+}
+
+static void
+intr_event_stray(void *cookie)
+{
+	struct intsrc *isrc;
+
+	isrc = cookie;
+	/*
+	 * For stray interrupts, mask and EOI the source, bump the
+	 * stray count, and log the condition.
+	 */
+	isrc->is_pic->pic_disable_source(isrc, PIC_EOI);
+	(*isrc->is_straycount)++;
+	if (*isrc->is_straycount < MAX_STRAY_LOG)
+		log(LOG_ERR, "stray irq%d\n", isrc->is_pic->pic_vector(isrc));
+	else if (*isrc->is_straycount == MAX_STRAY_LOG)
+		log(LOG_CRIT,
+		    "too many stray irq %d's: not logging anymore\n",
+		    isrc->is_pic->pic_vector(isrc));
+}
+
+static void
+intr_eoi_src(void *arg)
+{
+	struct intsrc *isrc;
+
+	isrc = arg;
+	isrc->is_pic->pic_eoi_source(isrc);
+}
+
+static void
+intr_disab_eoi_src(void *arg)
+{
+	struct intsrc *isrc;
+
+	isrc = arg;
+	isrc->is_pic->pic_disable_source(isrc, PIC_EOI);
+}
+#else
+void
 intr_execute_handlers(struct intsrc *isrc, u_int vector, struct trapframe *frame)
 {
 	struct thread *td;
 	struct intr_event *ie;
 	struct intr_handler *ih;
-	int error, thread;
+	int error, thread, ret;
 
 	td = curthread;
 
@@ -183,7 +312,7 @@
 	 * processed too.
 	 */
 	(*isrc->is_count)++;
-	PCPU_LAZY_INC(cnt.v_intr);
+	PCPU_INC(cnt.v_intr);
 
 	ie = isrc->is_event;
 
@@ -217,20 +346,39 @@
 	 * a trapframe as its argument.
 	 */
 	td->td_intr_nesting_level++;
+	ret = 0;
 	thread = 0;
 	critical_enter();
 	TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) {
-		if (!(ih->ih_flags & IH_FAST)) {
+		if (ih->ih_filter == NULL) {
 			thread = 1;
 			continue;
 		}
 		CTR4(KTR_INTR, "%s: exec %p(%p) for %s", __func__,
-		    ih->ih_handler, ih->ih_argument == NULL ? frame :
+		    ih->ih_filter, ih->ih_argument == NULL ? frame :
 		    ih->ih_argument, ih->ih_name);
 		if (ih->ih_argument == NULL)
-			ih->ih_handler(frame);
+			ret = ih->ih_filter(frame);
 		else
-			ih->ih_handler(ih->ih_argument);
+			ret = ih->ih_filter(ih->ih_argument);
+		/* 
+		 * Wrapper handler special handling:
+		 *
+		 * in some particular cases (like pccard and pccbb), 
+		 * the _real_ device handler is wrapped in a couple of
+		 * functions - a filter wrapper and an ithread wrapper.
+		 * In this case (and just in this case), the filter wrapper 
+		 * could ask the system to schedule the ithread and mask
+		 * the interrupt source if the wrapped handler is composed
+		 * of just an ithread handler.
+		 *
+		 * TODO: write a generic wrapper to avoid people rolling 
+		 * their own
+		 */
+		if (!thread) {
+			if (ret == FILTER_SCHEDULE_THREAD)
+				thread = 1;
+		}
 	}
 
 	/*
@@ -242,40 +390,41 @@
 		isrc->is_pic->pic_disable_source(isrc, PIC_EOI);
 	else
 		isrc->is_pic->pic_eoi_source(isrc);
-	critical_exit();
 
 	/* Schedule the ithread if needed. */
 	if (thread) {
 		error = intr_event_schedule_thread(ie);
 		KASSERT(error == 0, ("bad stray interrupt"));
 	}
+	critical_exit();
 	td->td_intr_nesting_level--;
 }
+#endif
 
 void
 intr_resume(void)
 {
-	struct intsrc **isrc;
-	int i;
+	struct pic *pic;
 
-	mtx_lock_spin(&intr_table_lock);
-	for (i = 0, isrc = interrupt_sources; i < NUM_IO_INTS; i++, isrc++)
-		if (*isrc != NULL && (*isrc)->is_pic->pic_resume != NULL)
-			(*isrc)->is_pic->pic_resume(*isrc);
-	mtx_unlock_spin(&intr_table_lock);
+	sx_xlock(&intr_table_lock);
+	STAILQ_FOREACH(pic, &pics, pics) {
+		if (pic->pic_resume != NULL)
+			pic->pic_resume(pic);
+	}
+	sx_xunlock(&intr_table_lock);
 }
 
 void
 intr_suspend(void)
 {
-	struct intsrc **isrc;
-	int i;
+	struct pic *pic;
 
-	mtx_lock_spin(&intr_table_lock);
-	for (i = 0, isrc = interrupt_sources; i < NUM_IO_INTS; i++, isrc++)
-		if (*isrc != NULL && (*isrc)->is_pic->pic_suspend != NULL)
-			(*isrc)->is_pic->pic_suspend(*isrc);
-	mtx_unlock_spin(&intr_table_lock);
+	sx_xlock(&intr_table_lock);
+	STAILQ_FOREACH(pic, &pics, pics) {
+		if (pic->pic_suspend != NULL)
+			pic->pic_suspend(pic);
+	}
+	sx_xunlock(&intr_table_lock);
 }
 
 static void
@@ -298,8 +447,8 @@
 {
 	char straystr[MAXCOMLEN + 1];
 
-	/* mtx_assert(&intr_table_lock, MA_OWNED); */
 	KASSERT(is->is_event != NULL, ("%s: isrc with no event", __func__));
+	mtx_lock_spin(&intrcnt_lock);
 	is->is_index = intrcnt_index;
 	intrcnt_index += 2;
 	snprintf(straystr, MAXCOMLEN + 1, "stray irq%d",
@@ -308,17 +457,18 @@
 	is->is_count = &intrcnt[is->is_index];
 	intrcnt_setname(straystr, is->is_index + 1);
 	is->is_straycount = &intrcnt[is->is_index + 1];
+	mtx_unlock_spin(&intrcnt_lock);
 }
 
 void
 intrcnt_add(const char *name, u_long **countp)
 {
 
-	mtx_lock_spin(&intr_table_lock);
+	mtx_lock_spin(&intrcnt_lock);
 	*countp = &intrcnt[intrcnt_index];
 	intrcnt_setname(name, intrcnt_index);
 	intrcnt_index++;
-	mtx_unlock_spin(&intr_table_lock);
+	mtx_unlock_spin(&intrcnt_lock);
 }
 
 static void
@@ -327,7 +477,9 @@
 
 	intrcnt_setname("???", 0);
 	intrcnt_index = 1;
-	mtx_init(&intr_table_lock, "intr table", NULL, MTX_SPIN);
+	STAILQ_INIT(&pics);
+	sx_init(&intr_table_lock, "intr sources");
+	mtx_init(&intrcnt_lock, "intrcnt", NULL, MTX_SPIN);
 }
 SYSINIT(intr_init, SI_SUB_INTR, SI_ORDER_FIRST, intr_init, NULL)
 
@@ -357,8 +509,9 @@
  * allocate CPUs round-robin.
  */
 
-static u_int cpu_apic_ids[MAXCPU];
-static int current_cpu, num_cpus;
+/* The BSP is always a valid target. */
+static cpumask_t intr_cpus = (1 << 0);
+static int current_cpu, num_cpus = 1;
 
 static void
 intr_assign_next_cpu(struct intsrc *isrc)
@@ -371,29 +524,29 @@
 	 */
 	pic = isrc->is_pic;
 	apic_id = cpu_apic_ids[current_cpu];
-	current_cpu++;
-	if (current_cpu >= num_cpus)
-		current_cpu = 0;
-	if (bootverbose) {
-		printf("INTR: Assigning IRQ %d", pic->pic_vector(isrc));
-		printf(" to local APIC %u\n", apic_id);
-	}
 	pic->pic_assign_cpu(isrc, apic_id);
+	do {
+		current_cpu++;
+		if (current_cpu >= num_cpus)
+			current_cpu = 0;
+	} while (!(intr_cpus & (1 << current_cpu)));
 }
 
 /*
- * Add a local APIC ID to our list of valid local APIC IDs that can
- * be destinations of interrupts.
+ * Add a CPU to our mask of valid CPUs that can be destinations of
+ * interrupts.
  */
 void
-intr_add_cpu(u_int apic_id)
+intr_add_cpu(u_int cpu)
 {
 
+	if (cpu >= MAXCPU)
+		panic("%s: Invalid CPU ID", __func__);
 	if (bootverbose)
-		printf("INTR: Adding local APIC %d as a target\n", apic_id);
-	if (num_cpus >= MAXCPU)
-		panic("WARNING: Local APIC IDs exhausted!");
-	cpu_apic_ids[num_cpus] = apic_id;
+		printf("INTR: Adding local APIC %d as a target\n",
+		    cpu_apic_ids[cpu]);
+
+	intr_cpus |= (1 << cpu);
 	num_cpus++;
 }
 
@@ -411,15 +564,15 @@
 	if (num_cpus <= 1)
 		return;
 
-	/* Round-robin assign each enabled source a CPU. */
-	mtx_lock_spin(&intr_table_lock);
+	/* Round-robin assign a CPU to each enabled source. */
+	sx_xlock(&intr_table_lock);
 	assign_cpu = 1;
 	for (i = 0; i < NUM_IO_INTS; i++) {
 		isrc = interrupt_sources[i];
-		if (isrc != NULL && isrc->is_enabled)
+		if (isrc != NULL && isrc->is_handlers > 0)
 			intr_assign_next_cpu(isrc);
 	}
-	mtx_unlock_spin(&intr_table_lock);
+	sx_xunlock(&intr_table_lock);
 }
 SYSINIT(intr_shuffle_irqs, SI_SUB_SMP, SI_ORDER_SECOND, intr_shuffle_irqs, NULL)
 #endif

==== //depot/projects/bike_sched/sys/kern/init_sysent.c#6 (text+ko) ====


==== //depot/projects/bike_sched/sys/kern/kern_clock.c#4 (text+ko) ====

@@ -35,8 +35,9 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/kern/kern_clock.c,v 1.190 2006/06/14 03:14:26 delphij Exp $");
+__FBSDID("$FreeBSD: src/sys/kern/kern_clock.c,v 1.205 2007/11/29 08:38:22 rwatson Exp $");
 
+#include "opt_kdb.h"
 #include "opt_device_polling.h"
 #include "opt_hwpmc_hooks.h"
 #include "opt_ntp.h"
@@ -80,17 +81,21 @@
 static void initclocks(void *dummy);
 SYSINIT(clocks, SI_SUB_CLOCKS, SI_ORDER_FIRST, initclocks, NULL)
 
-/* Some of these don't belong here, but it's easiest to concentrate them. */
-long cp_time[CPUSTATES];
+/* Spin-lock protecting profiling statistics. */
+static struct mtx time_lock;
 
 static int
 sysctl_kern_cp_time(SYSCTL_HANDLER_ARGS)
 {
 	int error;
+	long cp_time[CPUSTATES];
 #ifdef SCTL_MASK32
 	int i;
 	unsigned int cp_time32[CPUSTATES];
+#endif
 
+	read_cpu_time(cp_time);
+#ifdef SCTL_MASK32
 	if (req->flags & SCTL_MASK32) {
 		if (!req->oldptr)
 			return SYSCTL_OUT(req, 0, sizeof(cp_time32));
@@ -110,6 +115,67 @@
 SYSCTL_PROC(_kern, OID_AUTO, cp_time, CTLTYPE_LONG|CTLFLAG_RD,
     0,0, sysctl_kern_cp_time, "LU", "CPU time statistics");
 
+static long empty[CPUSTATES];
+
+static int
+sysctl_kern_cp_times(SYSCTL_HANDLER_ARGS)
+{
+	struct pcpu *pcpu;
+	int error;
+	int c;
+	long *cp_time;
+#ifdef SCTL_MASK32
+	unsigned int cp_time32[CPUSTATES];
+	int i;
+#endif
+
+	if (!req->oldptr) {
+#ifdef SCTL_MASK32
+		if (req->flags & SCTL_MASK32)
+			return SYSCTL_OUT(req, 0, sizeof(cp_time32) * (mp_maxid + 1));
+		else
+#endif
+			return SYSCTL_OUT(req, 0, sizeof(long) * CPUSTATES * (mp_maxid + 1));
+	}
+	for (error = 0, c = 0; error == 0 && c <= mp_maxid; c++) {
+		if (!CPU_ABSENT(c)) {
+			pcpu = pcpu_find(c);
+			cp_time = pcpu->pc_cp_time;
+		} else {
+			cp_time = empty;
+		}
+#ifdef SCTL_MASK32
+		if (req->flags & SCTL_MASK32) {
+			for (i = 0; i < CPUSTATES; i++)
+				cp_time32[i] = (unsigned int)cp_time[i];
+			error = SYSCTL_OUT(req, cp_time32, sizeof(cp_time32));
+		} else
+#endif
+			error = SYSCTL_OUT(req, cp_time, sizeof(long) * CPUSTATES);
+	}
+	return error;
+}
+
+SYSCTL_PROC(_kern, OID_AUTO, cp_times, CTLTYPE_LONG|CTLFLAG_RD,
+    0,0, sysctl_kern_cp_times, "LU", "per-CPU time statistics");
+
+void
+read_cpu_time(long *cp_time)
+{
+	struct pcpu *pc;
+	int i, j;
+
+	/* Sum up global cp_time[]. */
+	bzero(cp_time, sizeof(long) * CPUSTATES);
+	for (i = 0; i <= mp_maxid; i++) {
+		if (CPU_ABSENT(i))
+			continue;
+		pc = pcpu_find(i);
+		for (j = 0; j < CPUSTATES; j++)
+			cp_time[j] += pc->pc_cp_time[j];
+	}
+}
+
 #ifdef SW_WATCHDOG
 #include <sys/watchdog.h>
 
@@ -171,6 +237,7 @@
 	 * Set divisors to 1 (normal case) and let the machine-specific
 	 * code do its bit.
 	 */
+	mtx_init(&time_lock, "time lock", NULL, MTX_SPIN);
 	cpu_initclocks();
 
 	/*
@@ -196,25 +263,30 @@
 	struct pstats *pstats;
 	struct thread *td = curthread;
 	struct proc *p = td->td_proc;
+	int flags;
 
 	/*
 	 * Run current process's virtual and profile time, as needed.
 	 */
-	mtx_lock_spin_flags(&sched_lock, MTX_QUIET);
-	sched_tick();
 	pstats = p->p_stats;
+	flags = 0;
 	if (usermode &&
-	    timevalisset(&pstats->p_timer[ITIMER_VIRTUAL].it_value) &&
-	    itimerdecr(&pstats->p_timer[ITIMER_VIRTUAL], tick) == 0) {
-		p->p_sflag |= PS_ALRMPEND;
-		td->td_flags |= TDF_ASTPENDING;
+	    timevalisset(&pstats->p_timer[ITIMER_VIRTUAL].it_value)) {
+		PROC_SLOCK(p);
+		if (itimerdecr(&pstats->p_timer[ITIMER_VIRTUAL], tick) == 0)
+			flags |= TDF_ALRMPEND | TDF_ASTPENDING;
+		PROC_SUNLOCK(p);
 	}
-	if (timevalisset(&pstats->p_timer[ITIMER_PROF].it_value) &&
-	    itimerdecr(&pstats->p_timer[ITIMER_PROF], tick) == 0) {
-		p->p_sflag |= PS_PROFPEND;
-		td->td_flags |= TDF_ASTPENDING;
+	if (timevalisset(&pstats->p_timer[ITIMER_PROF].it_value)) {
+		PROC_SLOCK(p);
+		if (itimerdecr(&pstats->p_timer[ITIMER_PROF], tick) == 0)
+			flags |= TDF_PROFPEND | TDF_ASTPENDING;
+		PROC_SUNLOCK(p);
 	}
-	mtx_unlock_spin_flags(&sched_lock, MTX_QUIET);
+	thread_lock(td);
+	sched_tick();
+	td->td_flags |= flags;
+	thread_unlock(td);
 
 #ifdef	HWPMC_HOOKS
 	if (PMC_CPU_HAS_SAMPLES(PCPU_GET(cpuid)))
@@ -260,8 +332,8 @@
 	mtx_unlock_spin_flags(&callout_lock, MTX_QUIET);
 
 	/*
-	 * swi_sched acquires sched_lock, so we don't want to call it with
-	 * callout_lock held; incorrect locking order.
+	 * swi_sched acquires the thread lock, so we don't want to call it
+	 * with callout_lock held; incorrect locking order.
 	 */
 	if (need_softclock)
 		swi_sched(softclock_ih, 0);
@@ -342,20 +414,15 @@
 	register struct proc *p;
 {
 
-	/*
-	 * XXX; Right now sched_lock protects statclock(), but perhaps
-	 * it should be protected later on by a time_lock, which would
-	 * cover psdiv, etc. as well.
-	 */
 	PROC_LOCK_ASSERT(p, MA_OWNED);
 	if (p->p_flag & P_STOPPROF)
 		return;
 	if ((p->p_flag & P_PROFIL) == 0) {
-		mtx_lock_spin(&sched_lock);
 		p->p_flag |= P_PROFIL;
+		mtx_lock_spin(&time_lock);
 		if (++profprocs == 1)
 			cpu_startprofclock();
-		mtx_unlock_spin(&sched_lock);
+		mtx_unlock_spin(&time_lock);
 	}
 }
 
@@ -378,19 +445,18 @@
 		}
 		if ((p->p_flag & P_PROFIL) == 0)
 			return;
-		mtx_lock_spin(&sched_lock);
 		p->p_flag &= ~P_PROFIL;
+		mtx_lock_spin(&time_lock);
 		if (--profprocs == 0)
 			cpu_stopprofclock();
-		mtx_unlock_spin(&sched_lock);
+		mtx_unlock_spin(&time_lock);
 	}
 }
 
 /*
- * Statistics clock.  Grab profile sample, and if divider reaches 0,
- * do process and kernel statistics.  Most of the statistics are only
- * used by user-level statistics programs.  The main exceptions are
- * ke->ke_uticks, p->p_rux.rux_sticks, p->p_rux.rux_iticks, and p->p_estcpu.
+ * Statistics clock.  Updates rusage information and calls the scheduler
+ * to adjust priorities of the active thread.
+ *
  * This should be called by all active processors.
  */
 void
@@ -401,11 +467,12 @@
 	struct thread *td;
 	struct proc *p;
 	long rss;
+	long *cp_time;
 
 	td = curthread;
 	p = td->td_proc;
 
-	mtx_lock_spin_flags(&sched_lock, MTX_QUIET);
+	cp_time = (long *)PCPU_PTR(cp_time);
 	if (usermode) {
 		/*
 		 * Charge the time as appropriate.
@@ -435,29 +502,28 @@
 		} else {
 			td->td_pticks++;
 			td->td_sticks++;
-			if (td != PCPU_GET(idlethread))
+			if (!TD_IS_IDLETHREAD(td))
 				cp_time[CP_SYS]++;
 			else
 				cp_time[CP_IDLE]++;
 		}
 	}
-	CTR4(KTR_SCHED, "statclock: %p(%s) prio %d stathz %d",
-	    td, td->td_proc->p_comm, td->td_priority, (stathz)?stathz:hz);
 
-	sched_clock(td);
-
 	/* Update resource usage integrals and maximums. */
-	MPASS(p->p_stats != NULL);
 	MPASS(p->p_vmspace != NULL);
 	vm = p->p_vmspace;
-	ru = &p->p_stats->p_ru;
+	ru = &td->td_ru;
 	ru->ru_ixrss += pgtok(vm->vm_tsize);
 	ru->ru_idrss += pgtok(vm->vm_dsize);
 	ru->ru_isrss += pgtok(vm->vm_ssize);
 	rss = pgtok(vmspace_resident_count(vm));
 	if (ru->ru_maxrss < rss)
 		ru->ru_maxrss = rss;
-	mtx_unlock_spin_flags(&sched_lock, MTX_QUIET);
+	CTR4(KTR_SCHED, "statclock: %p(%s) prio %d stathz %d",
+	    td, td->td_name, td->td_priority, (stathz)?stathz:hz);
+	thread_lock_flags(td, MTX_QUIET);
+	sched_clock(td);
+	thread_unlock(td);
 }
 
 void
@@ -521,15 +587,15 @@
 #ifdef SW_WATCHDOG
 
 static void
-watchdog_config(void *unused __unused, u_int cmd, int *err)
+watchdog_config(void *unused __unused, u_int cmd, int *error)
 {
 	u_int u;
 
 	u = cmd & WD_INTERVAL;
-	if ((cmd & WD_ACTIVE) && u >= WD_TO_1SEC) {
+	if (u >= WD_TO_1SEC) {
 		watchdog_ticks = (1 << (u - WD_TO_1SEC)) * hz;
 		watchdog_enabled = 1;
-		*err = 0;
+		*error = 0;
 	} else {
 		watchdog_enabled = 0;
 	}
@@ -537,7 +603,7 @@
 
 /*
  * Handle a watchdog timeout by dumping interrupt information and
- * then either dropping to DDB or panicing.
+ * then either dropping to DDB or panicking.
  */
 static void
 watchdog_fire(void)
@@ -561,12 +627,12 @@
 	}
 	printf("Total        %20ju\n", (uintmax_t)inttotal);
 
-#ifdef KDB
+#if defined(KDB) && !defined(KDB_UNATTENDED)
 	kdb_backtrace();
 	kdb_enter("watchdog timeout");
 #else
 	panic("watchdog timeout");
-#endif /* KDB */
+#endif
 }
 
 #endif /* SW_WATCHDOG */

==== //depot/projects/bike_sched/sys/kern/kern_intr.c#5 (text+ko) ====

@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/kern/kern_intr.c,v 1.133 2006/07/12 21:22:44 jhb Exp $");
+__FBSDID("$FreeBSD: src/sys/kern/kern_intr.c,v 1.153 2007/10/29 20:45:31 julian Exp $");
 
 #include "opt_ddb.h"
 
@@ -80,10 +80,11 @@
 struct	intr_event *tty_intr_event;
 void	*softclock_ih;
 void	*vm_ih;
+struct proc *intrproc;
 
 static MALLOC_DEFINE(M_ITHREAD, "ithread", "Interrupt Threads");
 
-static int intr_storm_threshold = 500;
+static int intr_storm_threshold = 1000;
 TUNABLE_INT("hw.intr_storm_threshold", &intr_storm_threshold);
 SYSCTL_INT(_hw, OID_AUTO, intr_storm_threshold, CTLFLAG_RW,
     &intr_storm_threshold, 0,
@@ -92,13 +93,24 @@
     TAILQ_HEAD_INITIALIZER(event_list);
 
 static void	intr_event_update(struct intr_event *ie);
+#ifdef INTR_FILTER
+static struct intr_thread *ithread_create(const char *name,
+			      struct intr_handler *ih);
+#else
 static struct intr_thread *ithread_create(const char *name);
+#endif
 static void	ithread_destroy(struct intr_thread *ithread);
-static void	ithread_execute_handlers(struct proc *p, struct intr_event *ie);
+static void	ithread_execute_handlers(struct proc *p, 
+		    struct intr_event *ie);
+#ifdef INTR_FILTER
+static void	priv_ithread_execute_handler(struct proc *p, 
+		    struct intr_handler *ih);
+#endif
 static void	ithread_loop(void *);
 static void	ithread_update(struct intr_thread *ithd);
 static void	start_softintr(void *);
 
+/* Map an interrupt type to an ithread priority. */
 u_char
 intr_priority(enum intr_type flags)
 {
@@ -160,11 +172,10 @@
 		pri = TAILQ_FIRST(&ie->ie_handlers)->ih_pri;
 
 	/* Update name and priority. */
-	strlcpy(td->td_proc->p_comm, ie->ie_fullname,
-	    sizeof(td->td_proc->p_comm));
-	mtx_lock_spin(&sched_lock);
+	strlcpy(td->td_name, ie->ie_fullname, sizeof(td->td_name));
+	thread_lock(td);
 	sched_prio(td, pri);
-	mtx_unlock_spin(&sched_lock);
+	thread_unlock(td);
 }
 
 /*
@@ -226,6 +237,7 @@
 	CTR2(KTR_INTR, "%s: updated %s", __func__, ie->ie_fullname);
 }
 
+#ifndef INTR_FILTER
 int
 intr_event_create(struct intr_event **event, void *source, int flags,
     void (*enable)(void *), const char *fmt, ...)
@@ -255,6 +267,40 @@
 	CTR2(KTR_INTR, "%s: created %s", __func__, ie->ie_name);
 	return (0);
 }
+#else
+int
+intr_event_create(struct intr_event **event, void *source, int flags,
+    void (*enable)(void *), void (*eoi)(void *), void (*disab)(void *), 
+    const char *fmt, ...)
+{
+	struct intr_event *ie;
+	va_list ap;
+
+	/* The only valid flag during creation is IE_SOFT. */
+	if ((flags & ~IE_SOFT) != 0)
+		return (EINVAL);
+	ie = malloc(sizeof(struct intr_event), M_ITHREAD, M_WAITOK | M_ZERO);
+	ie->ie_source = source;
+	ie->ie_enable = enable;
+	ie->ie_eoi = eoi;
+	ie->ie_disab = disab;
+	ie->ie_flags = flags;
+	TAILQ_INIT(&ie->ie_handlers);
+	mtx_init(&ie->ie_lock, "intr event", NULL, MTX_DEF);
+
+	va_start(ap, fmt);
+	vsnprintf(ie->ie_name, sizeof(ie->ie_name), fmt, ap);
+	va_end(ap);
+	strlcpy(ie->ie_fullname, ie->ie_name, sizeof(ie->ie_fullname));
+	mtx_pool_lock(mtxpool_sleep, &event_list);
+	TAILQ_INSERT_TAIL(&event_list, ie, ie_list);
+	mtx_pool_unlock(mtxpool_sleep, &event_list);
+	if (event != NULL)
+		*event = ie;
+	CTR2(KTR_INTR, "%s: created %s", __func__, ie->ie_name);
+	return (0);
+}
+#endif
 
 int
 intr_event_destroy(struct intr_event *ie)
@@ -280,30 +326,55 @@
 	return (0);
 }
 
+#ifndef INTR_FILTER
 static struct intr_thread *

>>> TRUNCATED FOR MAIL (1000 lines) <<<



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