plan 9 kernel history: overview | file list | diff list

1994/1031/pc/clock.c (diff list | history)

1994/1029/sys/src/9/pc/clock.c:29,371994/1031/sys/src/9/pc/clock.c:29,36 (short | long | prev | next)
add x86type table to determine proper cycles multiplier for AAM loop. determine loops value dynamically to get long sample.
rsc Fri Mar 4 12:44:25 2005
1991/0705    
 
1994/0809    
static int cpufreq = 66000000; 
static int cpumhz = 66; 
1994/0716    
static int cputype = 486; 
static int loopconst = 100; 
1994/1029    
ulong cpuidax, cpuiddx; 
1994/1031    
static int cpuidax, cpuiddx; 
1992/0923    
 
1993/1124    
static void 
clock(Ureg *ur, void *arg) 
1994/1029/sys/src/9/pc/clock.c:72,771994/1031/sys/src/9/pc/clock.c:71,119
1994/0525    
	mouseclock(); 
1993/1124    
} 
 
1994/1031    
#define STEPPING(x)	((x)&0xf) 
#define MODEL(x)	(((x)>>4)&0xf) 
#define FAMILY(x)	(((x)>>8)&0xf) 
 
enum 
{ 
	/* flags */ 
	CpuidFPU	= 0x001,	/* on-chip floating point unit */ 
	CpuidMCE	= 0x080,	/* machine check exception */ 
	CpuidCX8	= 0x100,	/* CMPXCHG8B instruction */ 
}; 
 
typedef struct 
{ 
	int family; 
	int model; 
	int aalcycles; 
	char *name; 
} X86type; 
 
X86type x86type[] = 
{ 
	/* from the cpuid instruction */ 
	{ 4,	0,	22,	"Intel486DX", }, 
	{ 4,	1,	22,	"Intel486DX", }, 
	{ 4,	2,	22,	"Intel486SX", }, 
	{ 4,	4,	22,	"Intel486DX2", }, 
	{ 4,	5,	22,	"Intel486SL", }, 
	{ 4,	8,	22,	"IntelDX4", }, 
	{ 5,	1,	23,	"Pentium510", }, 
	{ 5,	2,	23,	"Pentium735", }, 
 
	/* family defaults */ 
	{ 3,	-1,	32,	"Intel386", }, 
	{ 4,	-1,	22,	"Intel486", }, 
	{ 5,	-1,	23,	"Pentium", }, 
 
	/* total default */ 
	{ -1,	-1,	23,	"unknown", }, 
}; 
 
static X86type	*cputype; 
 
1994/0302    
/* 
1994/0716    
 *  delay for l milliseconds more or less.  delayloop is set by 
 *  clockinit() to match the actual CPU speed. 
1994/1029/sys/src/9/pc/clock.c:89,1151994/1031/sys/src/9/pc/clock.c:131,149
1994/1029    
		cpufreq, cputype, cpuidax, cpuiddx); 
1994/0302    
} 
 
1994/1031    
int 
x86(void) 
{ 
	return cputype->family; 
} 
 
1991/0704    
void 
clockinit(void) 
{ 
1992/0923    
	ulong x, y;	/* change in counter */ 
1994/0716    
	ulong cycles, loops; 
1994/1031    
	int x, y;	/* change in counter */ 
	int family, model, loops; 
	X86type *t; 
1992/0922    
 
1994/0809    
	switch(cputype = x86()){ 
	case 386: 
		loops = 10000; 
		cycles = 32; 
		break; 
	case 486: 
		loops = 10000; 
		cycles = 22; 
		break; 
	default: 
		loops = 30000; 
		cycles = 23; 
		break; 
	} 
                 
1991/0709    
	/* 
	 *  set vector for clock interrupts 
	 */ 
1994/1029/sys/src/9/pc/clock.c:116,1211994/1031/sys/src/9/pc/clock.c:150,168
1993/1124    
	setvec(Clockvec, clock, 0); 
1991/0709    
 
	/* 
1994/1031    
	 *  figure out what we are 
	 */ 
	x86cpuid(&cpuidax, &cpuiddx); 
	family = FAMILY(cpuidax); 
	model = MODEL(cpuidax); 
	for(t = x86type; t->name; t++) 
		if((t->family == family && t->model == model) 
		|| (t->family == family && t->model == -1) 
		|| (t->family == -1)) 
			break; 
	cputype = t; 
 
	/* 
1994/0512    
	 *  set clock for 1/HZ seconds 
1991/0709    
	 */ 
1994/0603    
	outb(Tmode, Load0|Square); 
1994/1029/sys/src/9/pc/clock.c:122,1601994/1031/sys/src/9/pc/clock.c:169,214
1991/0709    
	outb(T0cntr, (Freq/HZ));	/* low byte */ 
	outb(T0cntr, (Freq/HZ)>>8);	/* high byte */ 
1992/0922    
 
1994/1031    
	/* use biggest loop that works */ 
	for(loops = 10000; ; loops += 5000) { 
		/* 
		 *  measure time for the loop 
		 * 
		 *			MOVL	loops,CX 
		 *	aaml1:	 	AAM 
		 *			LOOP	aaml1 
		 * 
		 *  the time for the loop should be independent of external 
		 *  cache and memory system since it fits in the execution 
		 *  prefetch buffer. 
		 * 
		 */ 
		outb(Tmode, Latch0); 
		x = inb(T0cntr); 
		x |= inb(T0cntr)<<8; 
		aamloop(loops); 
		outb(Tmode, Latch0); 
		y = inb(T0cntr); 
		y |= inb(T0cntr)<<8; 
		x -= y; 
1994/0809    
 
1992/0922    
	/* 
1994/0716    
	 *  measure time for the loop 
	 * 
	 *			MOVL	loops,CX 
	 *	aaml1:	 	AAM 
	 *			LOOP	aaml1 
	 * 
	 *  the time for the loop should be independent from external 
	 *  cache's and memory system since it fits in the execution 
	 *  prefetch buffer. 
	 * 
1992/0922    
	 */ 
	outb(Tmode, Latch0); 
1992/0923    
	x = inb(T0cntr); 
	x |= inb(T0cntr)<<8; 
1994/0716    
	aamloop(loops); 
1992/0923    
	outb(Tmode, Latch0); 
	y = inb(T0cntr); 
	y |= inb(T0cntr)<<8; 
	x -= y; 
1994/1031    
		if(x < 0) 
			x += 2^16; 
		if(x > (2^15)) 
			break; 
	 
		/* 
		 *  counter  goes at twice the frequency, once per transition, 
		 *  i.e., twice per square wave 
		 */ 
		x >>= 1; 
1992/0923    
 
	/* 
1994/0716    
	 *  counter  goes at twice the frequency, once per transition, 
1994/0809    
	 *  i.e., twice per square wave 
1992/0923    
	 */ 
1994/0716    
	x >>= 1; 
                 
	/* 
 	 *  figure out clock frequency and a loop multiplier for delay(). 
	 */ 
1994/0717    
	cpufreq = loops*((cycles*Freq)/x); 
1994/0716    
	loopconst = (cpufreq/1000)/cycles;	/* AAM+LOOP's for 1 ms */ 
1994/1031    
		/* 
	 	 *  figure out clock frequency and a loop multiplier for delay(). 
		 */ 
		cpufreq = loops*((t->aalcycles*Freq)/x); 
		loopconst = (cpufreq/1000)/t->aalcycles;	/* AAM+LOOP's for 1 ms */ 
	} while(x > 0); 
1994/0719    
 
1994/0809    
	/* 
	 *  add in possible .1% error and convert to MHz 


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)