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>