PERFORCE change 129904 for review
Peter Wemm
peter at FreeBSD.org
Sat Dec 1 13:51:28 PST 2007
http://perforce.freebsd.org/chv.cgi?CH=129904
Change 129904 by peter at 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) <<<
More information about the p4-projects
mailing list