diff options
author | mav <mav@FreeBSD.org> | 2013-02-17 18:42:30 +0000 |
---|---|---|
committer | mav <mav@FreeBSD.org> | 2013-02-17 18:42:30 +0000 |
commit | a8b029c7cfe6220819618eb3e2041a771c97b83b (patch) | |
tree | 510b0e561b28364a36689b25592e08e597967514 /sys/x86 | |
parent | 711b357b3d2aab9c3be4ca2268541fcdf62b796f (diff) | |
download | FreeBSD-src-a8b029c7cfe6220819618eb3e2041a771c97b83b.zip FreeBSD-src-a8b029c7cfe6220819618eb3e2041a771c97b83b.tar.gz |
MFcalloutng:
Microoptimize i8254 one-shot operation mode (disabled by default to allow
timecounter functionality) by not writing to mode and MSB registers when
it is not required. This saves several microseconds of CPU time per call,
reducing minimal measured interrupts interval to 19.5us.
Diffstat (limited to 'sys/x86')
-rw-r--r-- | sys/x86/isa/clock.c | 25 |
1 files changed, 21 insertions, 4 deletions
diff --git a/sys/x86/isa/clock.c b/sys/x86/isa/clock.c index a74c11f..42cc448 100644 --- a/sys/x86/isa/clock.c +++ b/sys/x86/isa/clock.c @@ -125,6 +125,8 @@ struct attimer_softc { static struct attimer_softc *attimer_sc = NULL; static int timer0_period = -2; +static int timer0_mode = 0xffff; +static int timer0_last = 0xffff; /* Values for timerX_state: */ #define RELEASED 0 @@ -404,7 +406,7 @@ DELAY(int n) static void set_i8254_freq(int mode, uint32_t period) { - int new_count; + int new_count, new_mode; mtx_lock_spin(&clock_lock); if (mode == MODE_STOP) { @@ -423,21 +425,34 @@ set_i8254_freq(int mode, uint32_t period) timer0_period = (mode == MODE_PERIODIC) ? new_count : -1; switch (mode) { case MODE_STOP: - outb(TIMER_MODE, TIMER_SEL0 | TIMER_INTTC | TIMER_16BIT); + new_mode = TIMER_SEL0 | TIMER_INTTC | TIMER_16BIT; + outb(TIMER_MODE, new_mode); outb(TIMER_CNTR0, 0); outb(TIMER_CNTR0, 0); break; case MODE_PERIODIC: - outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); + new_mode = TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT; + outb(TIMER_MODE, new_mode); outb(TIMER_CNTR0, new_count & 0xff); outb(TIMER_CNTR0, new_count >> 8); break; case MODE_ONESHOT: - outb(TIMER_MODE, TIMER_SEL0 | TIMER_INTTC | TIMER_16BIT); + if (new_count < 256 && timer0_last < 256) { + new_mode = TIMER_SEL0 | TIMER_INTTC | TIMER_LSB; + if (new_mode != timer0_mode) + outb(TIMER_MODE, new_mode); + outb(TIMER_CNTR0, new_count & 0xff); + break; + } + new_mode = TIMER_SEL0 | TIMER_INTTC | TIMER_16BIT; + if (new_mode != timer0_mode) + outb(TIMER_MODE, new_mode); outb(TIMER_CNTR0, new_count & 0xff); outb(TIMER_CNTR0, new_count >> 8); break; } + timer0_mode = new_mode; + timer0_last = new_count; out: mtx_unlock_spin(&clock_lock); } @@ -447,6 +462,8 @@ i8254_restore(void) { timer0_period = -2; + timer0_mode = 0xffff; + timer0_last = 0xffff; if (attimer_sc != NULL) set_i8254_freq(attimer_sc->mode, attimer_sc->period); else |