Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- From e5e403e2cc772dac3e0472f1d6d81f777d6df36f Mon Sep 17 00:00:00 2001
- From: OZAWA Tsuyoshi <ozawa+bsd@t-oza.net>
- Date: Tue, 4 May 2010 21:19:32 +0900
- Subject: [PATCH] add i386 & amd64 support
- Signed-off-by: OZAWA Tsuyoshi <ozawa+bsd@t-oza.net>
- ---
- sys/amd64/amd64/apic_vector.S | 2 +-
- sys/amd64/amd64/local_apic.c | 123 +++++++++++++++++++++++++++++++++++++++++
- sys/amd64/isa/clock.c | 13 ++++-
- sys/amd64/isa/dynticks.c | 81 +++++++++++++++++++++++++++
- sys/conf/files.amd64 | 1 +
- sys/conf/files.i386 | 1 +
- sys/i386/i386/apic_vector.s | 2 +-
- sys/i386/i386/local_apic.c | 120 ++++++++++++++++++++++++++++++++++++++++
- sys/i386/isa/clock.c | 18 +++++-
- sys/i386/isa/dynticks.c | 120 ++++++++++++++++++++++++++++++++++++++++
- sys/kern/kern_clock.c | 27 +++++++++
- sys/kern/kern_timeout.c | 28 +++++++++
- sys/kern/sched_4bsd.c | 3 +
- sys/kern/sched_ule.c | 3 +
- sys/sys/dynticks.h | 49 ++++++++++++++++
- sys/sys/systm.h | 1 +
- 16 files changed, 587 insertions(+), 5 deletions(-)
- create mode 100644 sys/amd64/isa/dynticks.c
- create mode 100644 sys/i386/isa/dynticks.c
- create mode 100644 sys/sys/dynticks.h
- diff --git a/sys/amd64/amd64/apic_vector.S b/sys/amd64/amd64/apic_vector.S
- index 7aa2891..7609ae4 100644
- --- a/sys/amd64/amd64/apic_vector.S
- +++ b/sys/amd64/amd64/apic_vector.S
- @@ -100,7 +100,7 @@ IDTVEC(timerint)
- PUSH_FRAME
- FAKE_MCOUNT(TF_RIP(%rsp))
- movq %rsp, %rdi
- - call lapic_handle_timer
- + call timer_intr_handler
- MEXITCOUNT
- jmp doreti
- diff --git a/sys/amd64/amd64/local_apic.c b/sys/amd64/amd64/local_apic.c
- index 79be51e..3ba823d 100644
- --- a/sys/amd64/amd64/local_apic.c
- +++ b/sys/amd64/amd64/local_apic.c
- @@ -66,6 +66,8 @@ __FBSDID("$FreeBSD: src/sys/amd64/amd64/local_apic.c,v 1.42.2.7.2.1 2010/02/10 0
- #include <ddb/ddb.h>
- #endif
- +#include <sys/dynticks.h>
- +
- #ifdef KDTRACE_HOOKS
- #include <sys/dtrace_bsd.h>
- cyclic_clock_func_t lapic_cyclic_clock_func[MAXCPU];
- @@ -109,6 +111,9 @@ struct lapic {
- u_long la_hard_ticks;
- u_long la_stat_ticks;
- u_long la_prof_ticks;
- + u_long la_last_tick;
- + u_long la_cur_skip;
- + u_long la_skip;
- } static lapics[MAX_APIC_ID + 1];
- /* XXX: should thermal be an NMI? */
- @@ -142,6 +147,7 @@ static u_int32_t lapic_timer_divisors[] = {
- APIC_TDCR_32, APIC_TDCR_64, APIC_TDCR_128
- };
- +
- extern inthand_t IDTVEC(rsvd);
- volatile lapic_t *lapic;
- @@ -156,6 +162,9 @@ static void lapic_timer_periodic(u_int count);
- static void lapic_timer_set_divisor(u_int divisor);
- static uint32_t lvt_mode(struct lapic *la, u_int pin, uint32_t value);
- +static struct timer_ops lapic_ops;
- +static void lapic_handle_timer_dynamically(struct trapframe *frame);
- +
- struct pic lapic_pic = { .pic_resume = lapic_resume };
- static uint32_t
- @@ -488,6 +497,8 @@ lapic_setup_clock(void)
- profhz = lapic_timer_hz;
- lapic_timer_period = value / lapic_timer_hz;
- + register_timer_intr_handlers(&lapic_ops);
- +
- /*
- * Start up the timer on the BSP. The APs will kick off their
- * timer during lapic_setup().
- @@ -799,6 +810,10 @@ lapic_handle_timer(struct trapframe *frame)
- if (profprocs != 0)
- profclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
- }
- +
- + la->la_cur_skip = 0;
- + la->la_skip = 1;
- +
- critical_exit();
- }
- @@ -1325,3 +1340,111 @@ lapic_ipi_vectored(u_int vector, int dest)
- #endif /* DETECT_DEADLOCK */
- }
- #endif /* SMP */
- +
- +
- +
- +static void lapic_set_next_timer_intr(void)
- +{
- + struct lapic *la;
- + int skip;
- + u_long cnt_to_skip;
- +
- + la = &lapics[PCPU_GET(apic_id)];
- + (*la->la_timer_count)++;
- +
- + skip = callout_get_next_event();
- + cnt_to_skip = lapic_timer_period * skip ;
- + lapic_timer_oneshot(cnt_to_skip);
- + la->la_skip = skip;
- + la->la_cur_skip = 0;
- +
- + return;
- +}
- +
- +static void lapic_set_timer_periodic(void)
- +{
- + lapic_timer_periodic(lapic_timer_period);
- +}
- +
- +static void
- +lapic_handle_timer_dynamically(struct trapframe *frame)
- +{
- + struct lapic *la;
- + int skip;
- + int i;
- +
- + /* Send EOI first thing. */
- + lapic_eoi();
- +
- +#if defined(SMP) && !defined(SCHED_ULE)
- + /*
- + * Don't do any accounting for the disabled HTT cores, since it
- + * will provide misleading numbers for the userland.
- + *
- + * No locking is necessary here, since even if we loose the race
- + * when hlt_cpus_mask changes it is not a big deal, really.
- + *
- + * Don't do that for ULE, since ULE doesn't consider hlt_cpus_mask
- + * and unlike other schedulers it actually schedules threads to
- + * those CPUs.
- + */
- + if ((hlt_cpus_mask & (1 << PCPU_GET(cpuid))) != 0)
- + return;
- +#endif
- +
- + /* Look up our local APIC structure for the tick counters. */
- + la = &lapics[PCPU_GET(apic_id)];
- + (*la->la_timer_count)++;
- + critical_enter();
- +
- +#ifdef KDTRACE_HOOKS
- + /*
- + * If the DTrace hooks are configured and a callback function
- + * has been registered, then call it to process the high speed
- + * timers.
- + */
- + int cpu = PCPU_GET(cpuid);
- + /* i dont know this works well? */
- + if (lapic_cyclic_clock_func[cpu] != NULL)
- + (*lapic_cyclic_clock_func[cpu])(frame);
- +#endif
- + /* Fire hardclock at hz. */
- + skip = la->la_skip;
- + for(i = 0; i < skip; i++){
- + 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));
- + }
- +
- + /* 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) {
- + if (profprocs != 0){
- + la->la_prof_ticks -= lapic_timer_hz;
- + profclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
- + }
- + }
- + }
- +
- + lapic_set_next_timer_intr();
- + critical_exit();
- +}
- +
- +
- +static struct timer_ops lapic_ops = {
- + .perticks_handler = lapic_handle_timer,
- + .dynticks_handler = lapic_handle_timer_dynamically,
- + .set_timer_periodic = lapic_set_timer_periodic,
- + .set_next_timer_intr = lapic_set_next_timer_intr,
- +};
- diff --git a/sys/amd64/isa/clock.c b/sys/amd64/isa/clock.c
- index d8b48d2..4aaf2c8 100644
- --- a/sys/amd64/isa/clock.c
- +++ b/sys/amd64/isa/clock.c
- @@ -69,6 +69,7 @@ __FBSDID("$FreeBSD: src/sys/amd64/isa/clock.c,v 1.234.2.2.6.1 2010/02/10 00:26:2
- #include <sys/sysctl.h>
- #include <sys/cons.h>
- #include <sys/power.h>
- +#include <sys/dynticks.h>
- #include <machine/clock.h>
- #include <machine/cpu.h>
- @@ -134,6 +135,8 @@ static unsigned i8254_get_timecount(struct timecounter *tc);
- static unsigned i8254_simple_get_timecount(struct timecounter *tc);
- static void set_timer_freq(u_int freq, int intr_freq);
- +static struct timer_ops clk_ops;
- +
- static struct timecounter i8254_timecounter = {
- i8254_get_timecount, /* get_timecount */
- 0, /* no poll_pps */
- @@ -765,7 +768,8 @@ cpu_initclocks()
- * timecounter to user a simpler algorithm.
- */
- if (!using_lapic_timer) {
- - intr_add_handler("clk", 0, (driver_filter_t *)clkintr, NULL, NULL,
- + register_timer_intr_handlers(&clk_ops);
- + intr_add_handler("clk", 0, (driver_filter_t *)timer_intr_handler, NULL, NULL,
- INTR_TYPE_CLK, NULL);
- i8254_intsrc = intr_lookup_source(0);
- if (i8254_intsrc != NULL)
- @@ -935,4 +939,11 @@ static devclass_t attimer_devclass;
- DRIVER_MODULE(attimer, isa, attimer_driver, attimer_devclass, 0, 0);
- DRIVER_MODULE(attimer, acpi, attimer_driver, attimer_devclass, 0, 0);
- +static struct timer_ops clk_ops = {
- + .ext_perticks_handler = clkintr,
- + .ext_dynticks_handler = NULL,
- + .set_next_timer_intr = NULL,
- + .set_timer_periodic = NULL,
- +};
- +
- #endif /* DEV_ISA */
- diff --git a/sys/amd64/isa/dynticks.c b/sys/amd64/isa/dynticks.c
- new file mode 100644
- index 0000000..7ae8f8b
- --- /dev/null
- +++ b/sys/amd64/isa/dynticks.c
- @@ -0,0 +1,81 @@
- +/*-
- + * Copyright (c) 2003 OZAWA Tsuyoshi <ozawa@t-oza.net>
- + * All rights reserved.
- + *
- + * Redistribution and use in source and binary forms, with or without
- + * modification, are permitted provided that the following conditions
- + * are met:
- + * 1. Redistributions of source code must retain the above copyright
- + * notice, this list of conditions and the following disclaimer.
- + * 2. Redistributions in binary form must reproduce the above copyright
- + * notice, this list of conditions and the following disclaimer in the
- + * documentation and/or other materials provided with the distribution.
- + * 3. Neither the name of the author nor the names of any co-contributors
- + * may be used to endorse or promote products derived from this software
- + * without specific prior written permission.
- + *
- + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- + * SUCH DAMAGE.
- + */
- +
- +#include <sys/cdefs.h>
- +__FBSDID("$FreeBSD: src/sys/amd64/isa/dynticks.c,v 0.1.0 2010/05/02 16:26:20 OZAWATsusyohi Exp $");
- +
- +#include <sys/dynticks.h>
- +#include <sys/systm.h>
- +
- +static int enable_dynticks = 0;
- +static void (*cur_handler)(struct trapframe *frame);
- +
- +static struct timer_ops *tops;
- +
- +void timer_intr_handler(struct trapframe *frame)
- +{
- + cur_handler(frame);
- +}
- +
- +void register_timer_intr_handlers(struct timer_ops *ops)
- +{
- + tops = ops;
- + cur_handler = ops->perticks_handler;
- +
- + if ( tops->perticks_handler && tops->dynticks_handler) {
- + enable_dynticks = 1;
- + }
- +}
- +
- +void switch_to_dynticks(void)
- +{
- + if(!enable_dynticks)
- + return;
- +
- + critical_enter();
- + cur_handler = tops->dynticks_handler;
- + tops->set_next_timer_intr();
- + critical_exit();
- +}
- +
- +void switch_to_perticks(void)
- +{
- + if(!enable_dynticks)
- + return;
- +
- + if(!tops->perticks_handler){
- + panic("NULL perticks handler!\n");
- + return;
- + }
- +
- + critical_enter();
- + cur_handler = tops->perticks_handler;
- + tops->set_timer_periodic();
- + critical_exit();
- +}
- diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64
- index 44732e8..d20dc77 100644
- --- a/sys/conf/files.amd64
- +++ b/sys/conf/files.amd64
- @@ -123,6 +123,7 @@ amd64/amd64/vm_machdep.c standard
- amd64/isa/atpic.c optional atpic isa
- #amd64/isa/atpic_vector.S optional atpic isa
- amd64/isa/clock.c standard
- +amd64/isa/dynticks.c standard
- amd64/isa/elcr.c standard
- amd64/isa/isa.c standard
- amd64/isa/isa_dma.c standard
- diff --git a/sys/conf/files.i386 b/sys/conf/files.i386
- index 033999c..ad3c916 100644
- --- a/sys/conf/files.i386
- +++ b/sys/conf/files.i386
- @@ -330,6 +330,7 @@ i386/ibcs2/imgact_coff.c optional ibcs2
- i386/isa/atpic.c standard
- #i386/isa/atpic_vector.s standard
- i386/isa/clock.c standard
- +i386/isa/dynticks.c standard
- i386/isa/dpms.c optional dpms
- i386/isa/elcr.c standard
- i386/isa/elink.c optional ep | ie
- diff --git a/sys/i386/i386/apic_vector.s b/sys/i386/i386/apic_vector.s
- index c2f5aca..722678c 100644
- --- a/sys/i386/i386/apic_vector.s
- +++ b/sys/i386/i386/apic_vector.s
- @@ -105,7 +105,7 @@ IDTVEC(timerint)
- SET_KERNEL_SREGS
- FAKE_MCOUNT(TF_EIP(%esp))
- pushl %esp
- - call lapic_handle_timer
- + call timer_intr_handler
- add $4, %esp
- MEXITCOUNT
- jmp doreti
- diff --git a/sys/i386/i386/local_apic.c b/sys/i386/i386/local_apic.c
- index 0151030..19f3853 100644
- --- a/sys/i386/i386/local_apic.c
- +++ b/sys/i386/i386/local_apic.c
- @@ -66,6 +66,8 @@ __FBSDID("$FreeBSD: src/sys/i386/i386/local_apic.c,v 1.44.2.6.2.1 2010/02/10 00:
- #include <ddb/ddb.h>
- #endif
- +#include <sys/dynticks.h>
- +
- #ifdef KDTRACE_HOOKS
- #include <sys/dtrace_bsd.h>
- cyclic_clock_func_t lapic_cyclic_clock_func[MAXCPU];
- @@ -109,6 +111,9 @@ struct lapic {
- u_long la_hard_ticks;
- u_long la_stat_ticks;
- u_long la_prof_ticks;
- + u_long la_last_tick;
- + u_long la_cur_skip;
- + u_long la_skip;
- } static lapics[MAX_APIC_ID + 1];
- /* XXX: should thermal be an NMI? */
- @@ -142,6 +147,7 @@ static u_int32_t lapic_timer_divisors[] = {
- APIC_TDCR_32, APIC_TDCR_64, APIC_TDCR_128
- };
- +
- extern inthand_t IDTVEC(rsvd);
- volatile lapic_t *lapic;
- @@ -156,6 +162,9 @@ static void lapic_timer_periodic(u_int count);
- static void lapic_timer_set_divisor(u_int divisor);
- static uint32_t lvt_mode(struct lapic *la, u_int pin, uint32_t value);
- +static struct timer_ops lapic_ops;
- +static void lapic_handle_timer_dynamically(struct trapframe *frame);
- +
- struct pic lapic_pic = { .pic_resume = lapic_resume };
- static uint32_t
- @@ -490,6 +499,8 @@ lapic_setup_clock(void)
- profhz = lapic_timer_hz;
- lapic_timer_period = value / lapic_timer_hz;
- + register_timer_intr_handlers(&lapic_ops);
- +
- /*
- * Start up the timer on the BSP. The APs will kick off their
- * timer during lapic_setup().
- @@ -801,6 +812,10 @@ lapic_handle_timer(struct trapframe *frame)
- if (profprocs != 0)
- profclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
- }
- +
- + la->la_cur_skip = 0;
- + la->la_skip = 1;
- +
- critical_exit();
- }
- @@ -1332,3 +1347,108 @@ lapic_ipi_vectored(u_int vector, int dest)
- #endif /* DETECT_DEADLOCK */
- }
- #endif /* SMP */
- +
- +static void lapic_set_next_timer_intr(void)
- +{
- + struct lapic *la;
- + int skip;
- + u_long cnt_to_skip;
- +
- + la = &lapics[PCPU_GET(apic_id)];
- + (*la->la_timer_count)++;
- +
- + skip = callout_get_next_event();
- + cnt_to_skip = lapic_timer_period * skip ;
- + lapic_timer_oneshot(cnt_to_skip);
- + la->la_skip = skip;
- + la->la_cur_skip = 0;
- +
- + return;
- +}
- +
- +static void lapic_set_timer_periodic(void)
- +{
- + lapic_timer_periodic(lapic_timer_period);
- +}
- +
- +static void
- +lapic_handle_timer_dynamically(struct trapframe *frame)
- +{
- + struct lapic *la;
- + int skip;
- + int i;
- +
- + /* Send EOI first thing. */
- + lapic_eoi();
- +
- +#if defined(SMP) && !defined(SCHED_ULE)
- + /*
- + * Don't do any accounting for the disabled HTT cores, since it
- + * will provide misleading numbers for the userland.
- + *
- + * No locking is necessary here, since even if we loose the race
- + * when hlt_cpus_mask changes it is not a big deal, really.
- + *
- + * Don't do that for ULE, since ULE doesn't consider hlt_cpus_mask
- + * and unlike other schedulers it actually schedules threads to
- + * those CPUs.
- + */
- + if ((hlt_cpus_mask & (1 << PCPU_GET(cpuid))) != 0)
- + return;
- +#endif
- +
- + /* Look up our local APIC structure for the tick counters. */
- + la = &lapics[PCPU_GET(apic_id)];
- + (*la->la_timer_count)++;
- + critical_enter();
- +
- +#ifdef KDTRACE_HOOKS
- + /*
- + * If the DTrace hooks are configured and a callback function
- + * has been registered, then call it to process the high speed
- + * timers.
- + */
- + int cpu = PCPU_GET(cpuid);
- + /* i dont know this works well? */
- + if (lapic_cyclic_clock_func[cpu] != NULL)
- + (*lapic_cyclic_clock_func[cpu])(frame);
- +#endif
- + /* Fire hardclock at hz. */
- + skip = la->la_skip;
- + for(i = 0; i < skip; i++){
- + 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));
- + }
- +
- + /* 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) {
- + if (profprocs != 0){
- + la->la_prof_ticks -= lapic_timer_hz;
- + profclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
- + }
- + }
- + }
- +
- + lapic_set_next_timer_intr();
- + critical_exit();
- +}
- +
- +static struct timer_ops lapic_ops = {
- + .perticks_handler = lapic_handle_timer,
- + .dynticks_handler = lapic_handle_timer_dynamically,
- + .set_timer_periodic = lapic_set_timer_periodic,
- + .set_next_timer_intr = lapic_set_next_timer_intr,
- +};
- diff --git a/sys/i386/isa/clock.c b/sys/i386/isa/clock.c
- index 0b6b42b..3d53dd5 100644
- --- a/sys/i386/isa/clock.c
- +++ b/sys/i386/isa/clock.c
- @@ -72,6 +72,7 @@ __FBSDID("$FreeBSD: src/sys/i386/isa/clock.c,v 1.239.2.2.6.1 2010/02/10 00:26:20
- #include <sys/sysctl.h>
- #include <sys/cons.h>
- #include <sys/power.h>
- +#include <sys/dynticks.h>
- #include <machine/clock.h>
- #include <machine/cpu.h>
- @@ -136,6 +137,8 @@ static unsigned i8254_get_timecount(struct timecounter *tc);
- static unsigned i8254_simple_get_timecount(struct timecounter *tc);
- static void set_timer_freq(u_int freq, int intr_freq);
- +static struct timer_ops clk_ops;
- +
- static struct timecounter i8254_timecounter = {
- i8254_get_timecount, /* get_timecount */
- 0, /* no poll_pps */
- @@ -769,8 +772,9 @@ cpu_initclocks()
- * timecounter to user a simpler algorithm.
- */
- if (!using_lapic_timer) {
- - intr_add_handler("clk", 0, (driver_filter_t *)clkintr, NULL,
- - NULL, INTR_TYPE_CLK, NULL);
- + register_ext_timer_intr_handlers(&clk_ops);
- + intr_add_handler("clk", 0, (driver_filter_t *)ext_timer_intr_handler, NULL,
- + NULL, INTR_TYPE_CLK, NULL);
- i8254_intsrc = intr_lookup_source(0);
- if (i8254_intsrc != NULL)
- i8254_pending =
- @@ -939,4 +943,14 @@ static devclass_t attimer_devclass;
- DRIVER_MODULE(attimer, isa, attimer_driver, attimer_devclass, 0, 0);
- DRIVER_MODULE(attimer, acpi, attimer_driver, attimer_devclass, 0, 0);
- +#if 1
- +static struct timer_ops clk_ops = {
- + .ext_perticks_handler = clkintr,
- + .ext_dynticks_handler = NULL,
- + .set_next_timer_intr = NULL,
- + .set_timer_periodic = NULL,
- +};
- +#endif
- +
- +
- #endif /* DEV_ISA */
- diff --git a/sys/i386/isa/dynticks.c b/sys/i386/isa/dynticks.c
- new file mode 100644
- index 0000000..bf5033f
- --- /dev/null
- +++ b/sys/i386/isa/dynticks.c
- @@ -0,0 +1,120 @@
- +/*-
- + * Copyright (c) 2003 OZAWA Tsuyoshi <ozawa@t-oza.net>
- + * All rights reserved.
- + *
- + * Redistribution and use in source and binary forms, with or without
- + * modification, are permitted provided that the following conditions
- + * are met:
- + * 1. Redistributions of source code must retain the above copyright
- + * notice, this list of conditions and the following disclaimer.
- + * 2. Redistributions in binary form must reproduce the above copyright
- + * notice, this list of conditions and the following disclaimer in the
- + * documentation and/or other materials provided with the distribution.
- + * 3. Neither the name of the author nor the names of any co-contributors
- + * may be used to endorse or promote products derived from this software
- + * without specific prior written permission.
- + *
- + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- + * SUCH DAMAGE.
- + */
- +
- +#include <sys/cdefs.h>
- +__FBSDID("$FreeBSD: src/sys/amd64/isa/dynticks.c,v 0.1.0 2010/05/02 16:26:20 OZAWATsusyohi Exp $");
- +
- +#include <sys/dynticks.h>
- +#include <sys/systm.h>
- +
- +static int enable_dynticks = 0;
- +static int use_ext_clksrc = 0;
- +static void (*cur_handler)(struct trapframe *frame);
- +static int (*cur_ext_handler)(struct trapframe *frame);
- +
- +static struct timer_ops *tops;
- +
- +void timer_intr_handler(struct trapframe *frame)
- +{
- + if(!cur_handler)
- + panic("cur_handler is NULL!\n");
- +
- + cur_handler(frame);
- +}
- +
- +int ext_timer_intr_handler(struct trapframe *frame)
- +{
- + if(!cur_ext_handler)
- + panic("cur_ext_handler is NULL!\n");
- +
- + return cur_ext_handler(frame);
- +}
- +
- +void register_timer_intr_handlers(struct timer_ops *ops)
- +{
- + tops = ops;
- +
- + if (ops->perticks_handler) {
- + cur_handler = ops->perticks_handler;
- + use_ext_clksrc = 0;
- + }
- +
- + if ( tops->perticks_handler && tops->dynticks_handler) {
- + enable_dynticks = 1;
- + }
- +}
- +
- +void register_ext_timer_intr_handlers(struct timer_ops *ops)
- +{
- + tops = ops;
- +
- + if (tops->ext_perticks_handler) {
- + cur_ext_handler = ops->ext_perticks_handler;
- + use_ext_clksrc = 1;
- + }
- +
- + if (tops->ext_perticks_handler && tops->ext_dynticks_handler) {
- + enable_dynticks = 1;
- + }
- +}
- +
- +void switch_to_dynticks(void)
- +{
- + if(!enable_dynticks)
- + return;
- +
- + /* TODO: swtich external clock handler */
- + if(use_ext_clksrc)
- + return;
- +
- + critical_enter();
- + cur_handler = tops->dynticks_handler;
- + tops->set_next_timer_intr();
- + critical_exit();
- +}
- +
- +void switch_to_perticks(void)
- +{
- + if(!enable_dynticks)
- + return;
- +
- + /* TODO: swtich external clock handler */
- + if(use_ext_clksrc)
- + return;
- +
- + if(!tops->perticks_handler){
- + panic("NULL perticks handler!\n");
- + return;
- + }
- +
- + critical_enter();
- + cur_handler = tops->perticks_handler;
- + tops->set_timer_periodic();
- + critical_exit();
- +}
- diff --git a/sys/kern/kern_clock.c b/sys/kern/kern_clock.c
- index d2faa52..82ab8eb 100644
- --- a/sys/kern/kern_clock.c
- +++ b/sys/kern/kern_clock.c
- @@ -344,6 +344,33 @@ hardclock(int usermode, uintfptr_t pc)
- #endif /* SW_WATCHDOG */
- }
- +void
- +hardclock_dynticks(int usermode, uintfptr_t pc,int skip)
- +{
- + //int i;
- +
- + //atomic_add_int((volatile int *)&ticks, skip); // FIXME
- + atomic_add_int((volatile int *)&ticks, 1);
- + hardclock_cpu(usermode);
- + tc_ticktock();
- + /*
- + * If no separate statistics clock is available, run it from here.
- + *
- + * XXX: this only works for UP
- + */
- + if (stathz == 0) {
- + profclock(usermode, pc);
- + statclock(usermode);
- + }
- +#ifdef DEVICE_POLLING
- + hardclock_device_poll(); /* this is very short and quick */
- +#endif /* DEVICE_POLLING */
- +#ifdef SW_WATCHDOG
- + if (watchdog_enabled > 0 && (watchdog_ticks -= skip ) <= 0)
- + watchdog_fire();
- +#endif /* SW_WATCHDOG */
- +}
- +
- /*
- * Compute number of ticks in the specified amount of time.
- */
- diff --git a/sys/kern/kern_timeout.c b/sys/kern/kern_timeout.c
- index 658dcc3..f982a77 100644
- --- a/sys/kern/kern_timeout.c
- +++ b/sys/kern/kern_timeout.c
- @@ -48,6 +48,7 @@ __FBSDID("$FreeBSD: src/sys/kern/kern_timeout.c,v 1.106.2.1.4.1 2010/02/10 00:26
- #include <sys/proc.h>
- #include <sys/sleepqueue.h>
- #include <sys/sysctl.h>
- +#include <sys/dynticks.h>
- static int avg_depth;
- SYSCTL_INT(_debug, OID_AUTO, to_avg_depth, CTLFLAG_RD, &avg_depth, 0,
- @@ -704,3 +705,30 @@ adjust_timeout_calltodo(time_change)
- return;
- }
- #endif /* APM_FIXUP_CALLTODO */
- +
- +int
- +callout_get_next_event(void)
- +{
- + struct callout *c;
- + struct callout_tailq *sc;
- + int curticks;
- + int skip = 1;
- +
- + curticks = softticks;
- +
- + while( skip < ncallout ) {
- + sc = &callwheel[ (curticks+skip) & callwheelmask ];
- + /* scan callout queue to get next timer event */
- + TAILQ_FOREACH( c, sc, c_links.tqe ){
- + if( c && c->c_time <= curticks + ncallout ){
- + if( c->c_time > 0 ){
- + goto out;
- + }
- + }
- + }
- + skip++;
- + }
- +
- +out:
- + return skip;
- +}
- diff --git a/sys/kern/sched_4bsd.c b/sys/kern/sched_4bsd.c
- index b9871b8..e12d45b 100644
- --- a/sys/kern/sched_4bsd.c
- +++ b/sys/kern/sched_4bsd.c
- @@ -54,6 +54,7 @@ __FBSDID("$FreeBSD: src/sys/kern/sched_4bsd.c,v 1.106.2.9.2.1 2010/02/10 00:26:2
- #include <sys/sx.h>
- #include <sys/turnstile.h>
- #include <sys/umtx.h>
- +#include <sys/dynticks.h>
- #include <machine/pcb.h>
- #include <machine/smp.h>
- @@ -1430,8 +1431,10 @@ sched_idletd(void *dummy)
- for (;;) {
- mtx_assert(&Giant, MA_NOTOWNED);
- + switch_to_dynticks();
- while (sched_runnable() == 0)
- cpu_idle();
- + switch_to_perticks();
- mtx_lock_spin(&sched_lock);
- mi_switch(SW_VOL, NULL);
- diff --git a/sys/kern/sched_ule.c b/sys/kern/sched_ule.c
- index 7943bb2..1bf9e31 100644
- --- a/sys/kern/sched_ule.c
- +++ b/sys/kern/sched_ule.c
- @@ -61,6 +61,7 @@ __FBSDID("$FreeBSD: src/sys/kern/sched_ule.c,v 1.214.2.12.2.1 2010/02/10 00:26:2
- #include <sys/umtx.h>
- #include <sys/vmmeter.h>
- #include <sys/cpuset.h>
- +#include <sys/dynticks.h>
- #ifdef KTRACE
- #include <sys/uio.h>
- #include <sys/ktrace.h>
- @@ -2670,12 +2671,14 @@ sched_idletd(void *dummy)
- mtx_assert(&Giant, MA_NOTOWNED);
- /* ULE relies on preemption for idle interruption. */
- for (;;) {
- + switch_to_dynticks();
- #ifdef SMP
- if (tdq_idled(tdq))
- cpu_idle();
- #else
- cpu_idle();
- #endif
- + switch_to_perticks();
- }
- }
- diff --git a/sys/sys/dynticks.h b/sys/sys/dynticks.h
- new file mode 100644
- index 0000000..5b268cd
- --- /dev/null
- +++ b/sys/sys/dynticks.h
- @@ -0,0 +1,49 @@
- +#ifndef _SYS_DYNTICKS_H_
- +#define _SYS_DYNTICKS_H_
- +
- +/*-
- + * Copyright (c) 2010 Tsuyoshi OZAWA
- + * All rights reserved.
- + *
- + * Redistribution and use in source and binary forms, with or without
- + * modification, are permitted provided that the following conditions
- + * are met:
- + * 1. Redistributions of source code must retain the above copyright
- + * notice, this list of conditions and the following disclaimer.
- + * 2. Redistributions in binary form must reproduce the above copyright
- + * notice, this list of conditions and the following disclaimer in the
- + * documentation and/or other materials provided with the distribution.
- + *
- + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- + * SUCH DAMAGE.
- + *
- + */
- +#include <sys/types.h>
- +#include <machine/frame.h>
- +
- +struct timer_ops {
- + void (*perticks_handler)(struct trapframe *frame);
- + int (*ext_perticks_handler)(struct trapframe *frame);
- + void (*dynticks_handler)(struct trapframe *frame);
- + int (*ext_dynticks_handler)(struct trapframe *frame);
- + void (*set_timer_periodic)(void);
- + void (*set_next_timer_intr)(void);
- +};
- +
- +void timer_intr_handler(struct trapframe *frame);
- +int ext_timer_intr_handler(struct trapframe *frame);
- +int callout_get_next_event(void);
- +void register_timer_intr_handlers(struct timer_ops *ops);
- +void register_ext_timer_intr_handlers(struct timer_ops *ops);
- +void switch_to_dynticks(void);
- +void switch_to_perticks(void);
- +#endif /* _SYS_DYNTICKS_H_ */
- diff --git a/sys/sys/systm.h b/sys/sys/systm.h
- index 45969b3..9d6525d 100644
- --- a/sys/sys/systm.h
- +++ b/sys/sys/systm.h
- @@ -232,6 +232,7 @@ u_long casuword(volatile u_long *p, u_long oldval, u_long newval);
- void realitexpire(void *);
- void hardclock(int usermode, uintfptr_t pc);
- +void hardclock_dynticks(int usermode, uintfptr_t pc,int skip);
- void hardclock_cpu(int usermode);
- void softclock(void *);
- void statclock(int usermode);
- --
- 1.7.0.1
Add Comment
Please, Sign In to add comment