svn commit: r246916 - head/sys/x86/isa

Alexander Motin mav at FreeBSD.org
Sun Feb 17 18:42:31 UTC 2013


Author: mav
Date: Sun Feb 17 18:42:30 2013
New Revision: 246916
URL: http://svnweb.freebsd.org/changeset/base/246916

Log:
  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.

Modified:
  head/sys/x86/isa/clock.c

Modified: head/sys/x86/isa/clock.c
==============================================================================
--- head/sys/x86/isa/clock.c	Sun Feb 17 14:27:04 2013	(r246915)
+++ head/sys/x86/isa/clock.c	Sun Feb 17 18:42:30 2013	(r246916)
@@ -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


More information about the svn-src-head mailing list