diff --git a/sys/amd64/amd64/mp_machdep.c b/sys/amd64/amd64/mp_machdep.c index 337c02805093..4a44aba696cc 100644 --- a/sys/amd64/amd64/mp_machdep.c +++ b/sys/amd64/amd64/mp_machdep.c @@ -1112,9 +1112,6 @@ ipi_bitmap_handler(struct trapframe frame) if (ipi_bitmap & (1 << IPI_STATCLOCK)) statclockintr(&frame); - - if (ipi_bitmap & (1 << IPI_PROFCLOCK)) - profclockintr(&frame); } /* diff --git a/sys/amd64/include/apicvar.h b/sys/amd64/include/apicvar.h index 91bba992d8bf..8dc04a960710 100644 --- a/sys/amd64/include/apicvar.h +++ b/sys/amd64/include/apicvar.h @@ -123,8 +123,7 @@ #define IPI_PREEMPT 1 #define IPI_HARDCLOCK 2 #define IPI_STATCLOCK 3 -#define IPI_PROFCLOCK 4 -#define IPI_BITMAP_LAST IPI_PROFCLOCK +#define IPI_BITMAP_LAST IPI_STATCLOCK #define IPI_IS_BITMAPED(x) ((x) <= IPI_BITMAP_LAST) #define IPI_STOP (APIC_IPI_INTS + 7) /* Stop CPU until restarted. */ diff --git a/sys/amd64/include/clock.h b/sys/amd64/include/clock.h index 8af699eae45a..d2d421ff322b 100644 --- a/sys/amd64/include/clock.h +++ b/sys/amd64/include/clock.h @@ -27,7 +27,6 @@ struct trapframe; int hardclockintr(struct trapframe *frame); int statclockintr(struct trapframe *frame); -int profclockintr(struct trapframe *frame); /* * Driver to clock driver interface. diff --git a/sys/i386/i386/mp_machdep.c b/sys/i386/i386/mp_machdep.c index 716c25e7e46d..0dfb3578e26b 100644 --- a/sys/i386/i386/mp_machdep.c +++ b/sys/i386/i386/mp_machdep.c @@ -1279,9 +1279,6 @@ ipi_bitmap_handler(struct trapframe frame) if (ipi_bitmap & (1 << IPI_STATCLOCK)) statclockintr(&frame); - - if (ipi_bitmap & (1 << IPI_PROFCLOCK)) - profclockintr(&frame); } /* diff --git a/sys/i386/include/apicvar.h b/sys/i386/include/apicvar.h index bcb84a0c49fc..adfc1e84c7d6 100644 --- a/sys/i386/include/apicvar.h +++ b/sys/i386/include/apicvar.h @@ -124,8 +124,7 @@ #define IPI_PREEMPT 1 #define IPI_HARDCLOCK 2 #define IPI_STATCLOCK 3 -#define IPI_PROFCLOCK 4 -#define IPI_BITMAP_LAST IPI_PROFCLOCK +#define IPI_BITMAP_LAST IPI_STATCLOCK #define IPI_IS_BITMAPED(x) ((x) <= IPI_BITMAP_LAST) #define IPI_STOP (APIC_IPI_INTS + 7) /* Stop CPU until restarted. */ @@ -152,8 +151,7 @@ #define IPI_PREEMPT 1 #define IPI_HARDCLOCK 2 #define IPI_STATCLOCK 3 -#define IPI_PROFCLOCK 4 -#define IPI_BITMAP_LAST IPI_PROFCLOCK +#define IPI_BITMAP_LAST IPI_STATCLOCK #define IPI_IS_BITMAPED(x) ((x) <= IPI_BITMAP_LAST) #define IPI_STOP (APIC_IPI_INTS + 7) /* Stop CPU until restarted. */ diff --git a/sys/i386/include/clock.h b/sys/i386/include/clock.h index c0c55edf5daa..7a4a081eba70 100644 --- a/sys/i386/include/clock.h +++ b/sys/i386/include/clock.h @@ -27,7 +27,6 @@ struct trapframe; int hardclockintr(struct trapframe *frame); int statclockintr(struct trapframe *frame); -int profclockintr(struct trapframe *frame); /* * Driver to clock driver interface. diff --git a/sys/kern/kern_clock.c b/sys/kern/kern_clock.c index da05cc16356c..a35e43bbfba4 100644 --- a/sys/kern/kern_clock.c +++ b/sys/kern/kern_clock.c @@ -374,6 +374,12 @@ int profprocs; int ticks; int psratio; +int timer1hz; +int timer2hz; +static DPCPU_DEFINE(u_int, hard_cnt); +static DPCPU_DEFINE(u_int, stat_cnt); +static DPCPU_DEFINE(u_int, prof_cnt); + /* * Initialize clock frequencies and start both clocks running. */ @@ -403,6 +409,52 @@ initclocks(dummy) #endif } +void +timer1clock(int usermode, uintfptr_t pc) +{ + u_int *cnt; + + cnt = DPCPU_PTR(hard_cnt); + *cnt += hz; + if (*cnt >= timer1hz) { + *cnt -= timer1hz; + if (*cnt >= timer1hz) + *cnt = 0; + if (PCPU_GET(cpuid) == 0) + hardclock(usermode, pc); + else + hardclock_cpu(usermode); + } + if (timer2hz == 0) + timer2clock(usermode, pc); +} + +void +timer2clock(int usermode, uintfptr_t pc) +{ + u_int *cnt; + int t2hz = timer2hz ? timer2hz : timer1hz; + + cnt = DPCPU_PTR(stat_cnt); + *cnt += stathz; + if (*cnt >= t2hz) { + *cnt -= t2hz; + if (*cnt >= t2hz) + *cnt = 0; + statclock(usermode); + } + if (profprocs == 0) + return; + cnt = DPCPU_PTR(prof_cnt); + *cnt += profhz; + if (*cnt >= t2hz) { + *cnt -= t2hz; + if (*cnt >= t2hz) + *cnt = 0; + profclock(usermode, pc); + } +} + /* * Each time the real-time timer fires, this function is called on all CPUs. * Note that hardclock() calls hardclock_cpu() for the boot CPU, so only diff --git a/sys/pc98/cbus/clock.c b/sys/pc98/cbus/clock.c index 8c5a7d2af759..2f2c08c7a012 100644 --- a/sys/pc98/cbus/clock.c +++ b/sys/pc98/cbus/clock.c @@ -129,10 +129,7 @@ int hardclockintr(struct trapframe *frame) { - if (PCPU_GET(cpuid) == 0) - hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame)); - else - hardclock_cpu(TRAPF_USERMODE(frame)); + timer1clock(TRAPF_USERMODE(frame), TRAPF_PC(frame)); return (FILTER_HANDLED); } @@ -143,13 +140,6 @@ statclockintr(struct trapframe *frame) return (FILTER_HANDLED); } -int -profclockintr(struct trapframe *frame) -{ - - return (FILTER_HANDLED); -} - static int clkintr(struct trapframe *frame) { @@ -448,6 +438,7 @@ cpu_initclocks() * timecounter to user a simpler algorithm. */ if (using_lapic_timer == LAPIC_CLOCK_NONE) { + timer1hz = hz; intr_add_handler("clk", 0, (driver_filter_t *)clkintr, NULL, NULL, INTR_TYPE_CLK, NULL); i8254_intsrc = intr_lookup_source(0); @@ -460,6 +451,14 @@ cpu_initclocks() i8254_timecounter.tc_counter_mask = 0xffff; set_i8254_freq(i8254_freq, hz); } + if (using_lapic_timer != LAPIC_CLOCK_ALL) { + profhz = hz; + if (hz < 128) + stathz = hz; + else + stathz = hz / (hz / 128); + } + timer2hz = 0; init_TSC_tc(); } diff --git a/sys/sys/kernel.h b/sys/sys/kernel.h index 1a9cb5cd003d..53cf0793ad3d 100644 --- a/sys/sys/kernel.h +++ b/sys/sys/kernel.h @@ -64,6 +64,8 @@ extern int stathz; /* statistics clock's frequency */ extern int profhz; /* profiling clock's frequency */ extern int profprocs; /* number of process's profiling */ extern int ticks; +extern int timer1hz; /* timer 1 frequency */ +extern int timer2hz; /* timer 2 frequency */ #endif /* _KERNEL */ diff --git a/sys/sys/systm.h b/sys/sys/systm.h index 1d861f0544ae..8d245a38778c 100644 --- a/sys/sys/systm.h +++ b/sys/sys/systm.h @@ -240,6 +240,8 @@ void hardclock_cpu(int usermode); void softclock(void *); void statclock(int usermode); void profclock(int usermode, uintfptr_t pc); +void timer1clock(int usermode, uintfptr_t pc); +void timer2clock(int usermode, uintfptr_t pc); void startprofclock(struct proc *); void stopprofclock(struct proc *); diff --git a/sys/x86/isa/clock.c b/sys/x86/isa/clock.c index 36dc36e68c0a..b0d49d579093 100644 --- a/sys/x86/isa/clock.c +++ b/sys/x86/isa/clock.c @@ -87,8 +87,6 @@ __FBSDID("$FreeBSD$"); #define TIMER_DIV(x) ((i8254_freq + (x) / 2) / (x)) int clkintr_pending; -static int pscnt = 1; -static int psdiv = 1; #ifndef TIMER_FREQ #define TIMER_FREQ 1193182 #endif @@ -134,10 +132,7 @@ int hardclockintr(struct trapframe *frame) { - if (PCPU_GET(cpuid) == 0) - hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame)); - else - hardclock_cpu(TRAPF_USERMODE(frame)); + timer1clock(TRAPF_USERMODE(frame), TRAPF_PC(frame)); return (FILTER_HANDLED); } @@ -145,19 +140,7 @@ int statclockintr(struct trapframe *frame) { - profclockintr(frame); - statclock(TRAPF_USERMODE(frame)); - return (FILTER_HANDLED); -} - -int -profclockintr(struct trapframe *frame) -{ - - if (!using_atrtc_timer) - hardclockintr(frame); - if (profprocs != 0) - profclock(TRAPF_USERMODE(frame), TRAPF_PC(frame)); + timer2clock(TRAPF_USERMODE(frame), TRAPF_PC(frame)); return (FILTER_HANDLED); } @@ -190,28 +173,11 @@ clkintr(struct trapframe *frame) (*cyclic_clock_func[cpu])(frame); #endif - if (using_atrtc_timer) { #ifdef SMP - if (smp_started) - ipi_all_but_self(IPI_HARDCLOCK); + if (smp_started) + ipi_all_but_self(IPI_HARDCLOCK); #endif - hardclockintr(frame); - } else { - if (--pscnt <= 0) { - pscnt = psratio; -#ifdef SMP - if (smp_started) - ipi_all_but_self(IPI_STATCLOCK); -#endif - statclockintr(frame); - } else { -#ifdef SMP - if (smp_started) - ipi_all_but_self(IPI_PROFCLOCK); -#endif - profclockintr(frame); - } - } + hardclockintr(frame); #ifdef DEV_MCA /* Reset clock interrupt by asserting bit 7 of port 0x61 */ @@ -295,20 +261,11 @@ rtcintr(struct trapframe *frame) while (rtcin(RTC_INTR) & RTCIR_PERIOD) { flag = 1; - if (--pscnt <= 0) { - pscnt = psdiv; #ifdef SMP - if (smp_started) - ipi_all_but_self(IPI_STATCLOCK); + if (smp_started) + ipi_all_but_self(IPI_STATCLOCK); #endif - statclockintr(frame); - } else { -#ifdef SMP - if (smp_started) - ipi_all_but_self(IPI_PROFCLOCK); -#endif - profclockintr(frame); - } + statclockintr(frame); } return(flag ? FILTER_HANDLED : FILTER_STRAY); } @@ -555,6 +512,7 @@ cpu_initclocks() * timecounter to user a simpler algorithm. */ if (using_lapic_timer == LAPIC_CLOCK_NONE) { + timer1hz = hz; intr_add_handler("clk", 0, (driver_filter_t *)clkintr, NULL, NULL, INTR_TYPE_CLK, NULL); i8254_intsrc = intr_lookup_source(0); @@ -577,6 +535,7 @@ cpu_initclocks() if (using_lapic_timer != LAPIC_CLOCK_ALL) { using_atrtc_timer = tasc; if (using_atrtc_timer) { + timer2hz = RTC_NOPROFRATE; /* Enable periodic interrupts from the RTC. */ intr_add_handler("rtc", 8, (driver_filter_t *)rtcintr, NULL, NULL, @@ -588,6 +547,7 @@ cpu_initclocks() stathz = hz; else stathz = hz / (hz / 128); + timer2hz = 0; } } @@ -601,7 +561,7 @@ cpu_startprofclock(void) if (using_lapic_timer == LAPIC_CLOCK_ALL || !using_atrtc_timer) return; atrtc_rate(RTCSA_PROF); - psdiv = pscnt = psratio; + timer2hz = RTC_PROFRATE; } void @@ -611,7 +571,7 @@ cpu_stopprofclock(void) if (using_lapic_timer == LAPIC_CLOCK_ALL || !using_atrtc_timer) return; atrtc_rate(RTCSA_NOPROF); - psdiv = pscnt = 1; + timer2hz = RTC_NOPROFRATE; } static int diff --git a/sys/x86/x86/local_apic.c b/sys/x86/x86/local_apic.c index 29b078eda999..f40026bb3037 100644 --- a/sys/x86/x86/local_apic.c +++ b/sys/x86/x86/local_apic.c @@ -118,9 +118,6 @@ struct lapic { u_int la_cluster_id:2; u_int la_present:1; u_long *la_timer_count; - u_long la_hard_ticks; - u_long la_stat_ticks; - u_long la_prof_ticks; /* Include IDT_SYSCALL to make indexing easier. */ int la_ioint_irqs[APIC_NUM_IOINTS + 1]; } static lapics[MAX_APIC_ID + 1]; @@ -493,12 +490,14 @@ lapic_setup_clock(enum lapic_clock srcsdes) } else lapic_timer_hz = hz; lapic_timer_period = value / lapic_timer_hz; + timer1hz = lapic_timer_hz; if (srcsdes == LAPIC_CLOCK_ALL) { if (lapic_timer_hz < 128) stathz = lapic_timer_hz; else stathz = lapic_timer_hz / (lapic_timer_hz / 128); profhz = lapic_timer_hz; + timer2hz = 0; } /* @@ -790,33 +789,7 @@ lapic_handle_timer(struct trapframe *frame) (*cyclic_clock_func[cpu])(frame); #endif - /* Fire hardclock at hz. */ - la->la_hard_ticks += hz; - if (la->la_hard_ticks >= lapic_timer_hz) { - la->la_hard_ticks -= lapic_timer_hz; - if (PCPU_GET(cpuid) == 0) - hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame)); - else - hardclock_cpu(TRAPF_USERMODE(frame)); - } - if (clockcoverage == LAPIC_CLOCK_ALL) { - - /* Fire statclock at stathz. */ - la->la_stat_ticks += stathz; - if (la->la_stat_ticks >= lapic_timer_hz) { - la->la_stat_ticks -= lapic_timer_hz; - statclock(TRAPF_USERMODE(frame)); - } - - /* Fire profclock at profhz, but only when needed. */ - la->la_prof_ticks += profhz; - if (la->la_prof_ticks >= lapic_timer_hz) { - la->la_prof_ticks -= lapic_timer_hz; - if (profprocs != 0) - profclock(TRAPF_USERMODE(frame), - TRAPF_PC(frame)); - } - } + timer1clock(TRAPF_USERMODE(frame), TRAPF_PC(frame)); critical_exit(); }