Add kernel option for separate {stat,prof}clock
This commit is contained in:
parent
10ebaa7036
commit
291d8cbf3a
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: locore.s,v 1.10 1995/11/30 00:57:36 jtc Exp $ */
|
/* $NetBSD: locore.s,v 1.11 1995/11/30 21:52:46 leo Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1988 University of Utah.
|
* Copyright (c) 1988 University of Utah.
|
||||||
|
@ -498,7 +498,6 @@ _spurintr:
|
||||||
jra rei
|
jra rei
|
||||||
|
|
||||||
/* MFP timer A handler --- System clock --- */
|
/* MFP timer A handler --- System clock --- */
|
||||||
/* Note: Reduce by factor 4 before handling */
|
|
||||||
mfp_tima:
|
mfp_tima:
|
||||||
moveml d0-d1/a0-a1,sp@- | save scratch registers
|
moveml d0-d1/a0-a1,sp@- | save scratch registers
|
||||||
lea sp@(16),a1 | get pointer to PS
|
lea sp@(16),a1 | get pointer to PS
|
||||||
|
@ -510,6 +509,20 @@ mfp_tima:
|
||||||
addql #1,_cnt+V_INTR | chalk up another interrupt
|
addql #1,_cnt+V_INTR | chalk up another interrupt
|
||||||
jra rei | all done
|
jra rei | all done
|
||||||
|
|
||||||
|
#ifdef STATCLOCK
|
||||||
|
/* MFP timer C handler --- Stat/Prof clock --- */
|
||||||
|
mfp_timc:
|
||||||
|
moveml d0-d1/a0-a1,sp@- | save scratch registers
|
||||||
|
lea sp@(16),a1 | get pointer to PS
|
||||||
|
movl a1,sp@- | push pointer to PS, PC
|
||||||
|
jbsr _statintr | call statistics clock handler
|
||||||
|
addql #4,sp | pop params
|
||||||
|
addql #1,_intrcnt+36 | add another stat clock interrupt
|
||||||
|
moveml sp@+,d0-d1/a0-a1 | restore scratch regs
|
||||||
|
addql #1,_cnt+V_INTR | chalk up another interrupt
|
||||||
|
jra rei | all done
|
||||||
|
#endif /* STATCLOCK */
|
||||||
|
|
||||||
/* MFP ACIA handler --- keyboard/midi --- */
|
/* MFP ACIA handler --- keyboard/midi --- */
|
||||||
mfp_kbd:
|
mfp_kbd:
|
||||||
addql #1,_intrcnt+8 | add another kbd/mouse interrupt
|
addql #1,_intrcnt+8 | add another kbd/mouse interrupt
|
||||||
|
@ -1947,8 +1960,9 @@ _intrnames:
|
||||||
.asciz "5380-DMA"
|
.asciz "5380-DMA"
|
||||||
.asciz "nmi"
|
.asciz "nmi"
|
||||||
.asciz "8530-SCC"
|
.asciz "8530-SCC"
|
||||||
|
.asciz "statclock"
|
||||||
_eintrnames:
|
_eintrnames:
|
||||||
.even
|
.even
|
||||||
_intrcnt:
|
_intrcnt:
|
||||||
.long 0,0,0,0,0,0,0,0,0
|
.long 0,0,0,0,0,0,0,0,0,0
|
||||||
_eintrcnt:
|
_eintrcnt:
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: vectors.s,v 1.2 1995/05/05 16:30:35 leo Exp $ */
|
/* $NetBSD: vectors.s,v 1.3 1995/11/30 21:52:50 leo Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1988 University of Utah
|
* Copyright (c) 1988 University of Utah
|
||||||
|
@ -133,7 +133,11 @@ Lvectab:
|
||||||
.long _badmfpint | 66: modem port 1 - CTS
|
.long _badmfpint | 66: modem port 1 - CTS
|
||||||
.long _badmfpint | 67: unassigned
|
.long _badmfpint | 67: unassigned
|
||||||
.long _badmfpint | 68: modem port 1 baudgen (Timer D)
|
.long _badmfpint | 68: modem port 1 baudgen (Timer D)
|
||||||
|
#ifdef STATCLOCK
|
||||||
|
.long mfp_timc | 69: Timer C {stat,prof}clock
|
||||||
|
#else
|
||||||
.long _badmfpint | 69: Timer C
|
.long _badmfpint | 69: Timer C
|
||||||
|
#endif /* STATCLOCK */
|
||||||
.long mfp_kbd | 70: KBD/MIDI IRQ
|
.long mfp_kbd | 70: KBD/MIDI IRQ
|
||||||
.long mfp_fd_acsi | 71: FDC/ACSI DMA
|
.long mfp_fd_acsi | 71: FDC/ACSI DMA
|
||||||
.long _badmfpint | 72: Display enable counter
|
.long _badmfpint | 72: Display enable counter
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#
|
#
|
||||||
# $NetBSD: GENERIC,v 1.8 1995/11/30 00:57:49 jtc Exp $
|
# $NetBSD: GENERIC,v 1.9 1995/11/30 21:53:07 leo Exp $
|
||||||
#
|
#
|
||||||
# Generic atari
|
# Generic atari
|
||||||
#
|
#
|
||||||
|
@ -90,6 +90,7 @@ options TT_SCSI # SCSI-support for TT
|
||||||
options FALCON_SCSI # SCSI-support for Falcon
|
options FALCON_SCSI # SCSI-support for Falcon
|
||||||
options TT_VIDEO # Graphics support for TT
|
options TT_VIDEO # Graphics support for TT
|
||||||
options FALCON_VIDEO # Graphics support for FALCON
|
options FALCON_VIDEO # Graphics support for FALCON
|
||||||
|
options STATCLOCK # Separate {stat,prof}clock
|
||||||
|
|
||||||
#
|
#
|
||||||
# Build one kernel that can boot from any disk.
|
# Build one kernel that can boot from any disk.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: clock.c,v 1.4 1995/09/23 20:23:28 leo Exp $ */
|
/* $NetBSD: clock.c,v 1.5 1995/11/30 21:53:17 leo Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1988 University of Utah.
|
* Copyright (c) 1988 University of Utah.
|
||||||
|
@ -55,21 +55,20 @@
|
||||||
#include <machine/profile.h>
|
#include <machine/profile.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The MFP clock runs at 2457600Hz. We use a {system,stat,prof}clock divider
|
||||||
|
* of 200. Therefore the timer runs at an effective rate of:
|
||||||
|
* 2457600/200 = 12288Hz.
|
||||||
|
*/
|
||||||
|
#define CLOCK_HZ 12288
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Machine-dependent clock routines.
|
* Machine-dependent clock routines.
|
||||||
*
|
*
|
||||||
* Startrtclock restarts the real-time clock, which provides
|
|
||||||
* hardclock interrupts to kern_clock.c.
|
|
||||||
*
|
|
||||||
* Inittodr initializes the time of day hardware which provides
|
* Inittodr initializes the time of day hardware which provides
|
||||||
* date functions.
|
* date functions.
|
||||||
*
|
*
|
||||||
* Resettodr restores the time of day hardware after a time change.
|
* Resettodr restores the time of day hardware after a time change.
|
||||||
*
|
|
||||||
* A note on the real-time clock:
|
|
||||||
* We actually load the clock with CLK_INTERVAL-1 instead of CLK_INTERVAL.
|
|
||||||
* This is because the counter decrements to zero after N+1 enabled clock
|
|
||||||
* periods where N is the value loaded into the counter.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int clockmatch __P((struct device *, struct cfdata *, void *));
|
int clockmatch __P((struct device *, struct cfdata *, void *));
|
||||||
|
@ -83,7 +82,22 @@ struct cfdriver clockcd = {
|
||||||
static u_long gettod __P((void));
|
static u_long gettod __P((void));
|
||||||
static int settod __P((u_long));
|
static int settod __P((u_long));
|
||||||
|
|
||||||
static int divisor;
|
static int divisor; /* Systemclock divisor */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Statistics and profile clock intervals and variances. Variance must
|
||||||
|
* be a power of 2. Since this gives us an even number, not an odd number,
|
||||||
|
* we discard one case and compensate. That is, a variance of 64 would
|
||||||
|
* give us offsets in [0..63]. Instead, we take offsets in [1..63].
|
||||||
|
* This is symetric around the point 32, or statvar/2, and thus averages
|
||||||
|
* to that value (assuming uniform random numbers).
|
||||||
|
*/
|
||||||
|
#ifdef STATCLOCK
|
||||||
|
static int statvar = 32; /* {stat,prof}clock variance */
|
||||||
|
static int statmin; /* statclock divisor - variance/2 */
|
||||||
|
static int profmin; /* profclock divisor - variance/2 */
|
||||||
|
static int clk2min; /* current, from above choises */
|
||||||
|
#endif
|
||||||
|
|
||||||
int
|
int
|
||||||
clockmatch(pdp, cfp, auxp)
|
clockmatch(pdp, cfp, auxp)
|
||||||
|
@ -109,13 +123,33 @@ void *auxp;
|
||||||
* at an effective rate of: 2457600/200 = 12288Hz. The
|
* at an effective rate of: 2457600/200 = 12288Hz. The
|
||||||
* following expression works for 48, 64 or 96 hz.
|
* following expression works for 48, 64 or 96 hz.
|
||||||
*/
|
*/
|
||||||
divisor = 12288/hz;
|
divisor = CLOCK_HZ/hz;
|
||||||
MFP->mf_tacr = 0; /* Stop timer */
|
MFP->mf_tacr = 0; /* Stop timer */
|
||||||
MFP->mf_iera &= ~IA_TIMA; /* Disable timer interrupts */
|
MFP->mf_iera &= ~IA_TIMA; /* Disable timer interrupts */
|
||||||
MFP->mf_tadr = divisor; /* Set divisor */
|
MFP->mf_tadr = divisor; /* Set divisor */
|
||||||
|
|
||||||
|
if (hz != 48 && hz != 64 && hz != 96) { /* XXX */
|
||||||
|
printf (": illegal value %d for systemclock, reset to %d\n\t",
|
||||||
|
hz, 64);
|
||||||
|
hz = 64;
|
||||||
|
}
|
||||||
printf(": system hz %d timer-A divisor 200/%d\n", hz, divisor);
|
printf(": system hz %d timer-A divisor 200/%d\n", hz, divisor);
|
||||||
|
|
||||||
|
#ifdef STATCLOCK
|
||||||
|
if ((stathz == 0) || (stathz > hz) || (CLOCK_HZ % stathz))
|
||||||
|
stathz = hz;
|
||||||
|
if ((profhz == 0) || (profhz > (hz << 1)) || (CLOCK_HZ % profhz))
|
||||||
|
profhz = hz << 1;
|
||||||
|
|
||||||
|
MFP->mf_tcdcr &= 0x7; /* Stop timer */
|
||||||
|
MFP->mf_ierb &= ~IB_TIMC; /* Disable timer inter. */
|
||||||
|
MFP->mf_tcdr = CLOCK_HZ/stathz; /* Set divisor */
|
||||||
|
|
||||||
|
statmin = (CLOCK_HZ/stathz) - (statvar >> 1);
|
||||||
|
profmin = (CLOCK_HZ/profhz) - (statvar >> 1);
|
||||||
|
clk2min = statmin;
|
||||||
|
#endif /* STATCLOCK */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize Timer-B in the ST-MFP. This timer is used by the 'delay'
|
* Initialize Timer-B in the ST-MFP. This timer is used by the 'delay'
|
||||||
* function below. This time is setup to be continueously counting from
|
* function below. This time is setup to be continueously counting from
|
||||||
|
@ -134,13 +168,50 @@ void cpu_initclocks()
|
||||||
MFP->mf_ipra &= ~IA_TIMA; /* Clear pending interrupts */
|
MFP->mf_ipra &= ~IA_TIMA; /* Clear pending interrupts */
|
||||||
MFP->mf_iera |= IA_TIMA; /* Enable timer interrupts */
|
MFP->mf_iera |= IA_TIMA; /* Enable timer interrupts */
|
||||||
MFP->mf_imra |= IA_TIMA; /* ..... */
|
MFP->mf_imra |= IA_TIMA; /* ..... */
|
||||||
|
|
||||||
|
#ifdef STATCLOCK
|
||||||
|
MFP->mf_tcdcr = (MFP->mf_tcdcr & 0x7) | (T_Q200<<4); /* Start */
|
||||||
|
MFP->mf_iprb &= ~IB_TIMC; /* Clear pending interrupts */
|
||||||
|
MFP->mf_ierb |= IB_TIMC; /* Enable timer interrupts */
|
||||||
|
MFP->mf_imrb |= IB_TIMC; /* ..... */
|
||||||
|
#endif /* STATCLOCK */
|
||||||
}
|
}
|
||||||
|
|
||||||
setstatclockrate(hz)
|
setstatclockrate(newhz)
|
||||||
int hz;
|
int newhz;
|
||||||
{
|
{
|
||||||
|
#ifdef STATCLOCK
|
||||||
|
if (newhz == stathz)
|
||||||
|
clk2min = statmin;
|
||||||
|
else clk2min = profmin;
|
||||||
|
#endif /* STATCLOCK */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef STATCLOCK
|
||||||
|
void
|
||||||
|
statintr(frame)
|
||||||
|
register struct clockframe *frame;
|
||||||
|
{
|
||||||
|
register int var, r;
|
||||||
|
|
||||||
|
var = statvar - 1;
|
||||||
|
do {
|
||||||
|
r = random() & var;
|
||||||
|
} while(r == 0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note that we are always lagging behind as the new divisor
|
||||||
|
* value will not be loaded until the next interrupt. This
|
||||||
|
* shouldn't disturb the median frequency (I think ;-) ) as
|
||||||
|
* only the value used when switching frequencies is used
|
||||||
|
* twice. This shouldn't happen very often.
|
||||||
|
*/
|
||||||
|
MFP->mf_tcdr = clk2min + r;
|
||||||
|
|
||||||
|
statclock(frame);
|
||||||
|
}
|
||||||
|
#endif /* STATCLOCK */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns number of usec since last recorded clock "tick"
|
* Returns number of usec since last recorded clock "tick"
|
||||||
* (i.e. clock interrupt).
|
* (i.e. clock interrupt).
|
||||||
|
@ -203,97 +274,6 @@ int n;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef PROFTIMER
|
|
||||||
/*
|
|
||||||
* This code allows the amiga kernel to use one of the extra timers on
|
|
||||||
* the clock chip for profiling, instead of the regular system timer.
|
|
||||||
* The advantage of this is that the profiling timer can be turned up to
|
|
||||||
* a higher interrupt rate, giving finer resolution timing. The profclock
|
|
||||||
* routine is called from the lev6intr in locore, and is a specialized
|
|
||||||
* routine that calls addupc. The overhead then is far less than if
|
|
||||||
* hardclock/softclock was called. Further, the context switch code in
|
|
||||||
* locore has been changed to turn the profile clock on/off when switching
|
|
||||||
* into/out of a process that is profiling (startprofclock/stopprofclock).
|
|
||||||
* This reduces the impact of the profiling clock on other users, and might
|
|
||||||
* possibly increase the accuracy of the profiling.
|
|
||||||
*/
|
|
||||||
int profint = PRF_INTERVAL; /* Clock ticks between interrupts */
|
|
||||||
int profscale = 0; /* Scale factor from sys clock to prof clock */
|
|
||||||
char profon = 0; /* Is profiling clock on? */
|
|
||||||
|
|
||||||
/* profon values - do not change, locore.s assumes these values */
|
|
||||||
#define PRF_NONE 0x00
|
|
||||||
#define PRF_USER 0x01
|
|
||||||
#define PRF_KERNEL 0x80
|
|
||||||
|
|
||||||
initprofclock()
|
|
||||||
{
|
|
||||||
#if NCLOCK > 0
|
|
||||||
struct proc *p = curproc; /* XXX */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the high-res timer is running, force profiling off.
|
|
||||||
* Unfortunately, this gets reflected back to the user not as
|
|
||||||
* an error but as a lack of results.
|
|
||||||
*/
|
|
||||||
if (clockon) {
|
|
||||||
p->p_stats->p_prof.pr_scale = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* Keep track of the number of user processes that are profiling
|
|
||||||
* by checking the scale value.
|
|
||||||
*
|
|
||||||
* XXX: this all assumes that the profiling code is well behaved;
|
|
||||||
* i.e. profil() is called once per process with pcscale non-zero
|
|
||||||
* to turn it on, and once with pcscale zero to turn it off.
|
|
||||||
* Also assumes you don't do any forks or execs. Oh well, there
|
|
||||||
* is always adb...
|
|
||||||
*/
|
|
||||||
if (p->p_stats->p_prof.pr_scale)
|
|
||||||
profprocs++;
|
|
||||||
else
|
|
||||||
profprocs--;
|
|
||||||
#endif
|
|
||||||
/*
|
|
||||||
* The profile interrupt interval must be an even divisor
|
|
||||||
* of the CLK_INTERVAL so that scaling from a system clock
|
|
||||||
* tick to a profile clock tick is possible using integer math.
|
|
||||||
*/
|
|
||||||
if (profint > CLK_INTERVAL || (CLK_INTERVAL % profint) != 0)
|
|
||||||
profint = CLK_INTERVAL;
|
|
||||||
profscale = CLK_INTERVAL / profint;
|
|
||||||
}
|
|
||||||
|
|
||||||
startprofclock()
|
|
||||||
{
|
|
||||||
unsigned short interval;
|
|
||||||
|
|
||||||
/* stop timer B */
|
|
||||||
ciab.crb = ciab.crb & 0xc0;
|
|
||||||
|
|
||||||
/* load interval into registers.
|
|
||||||
the clocks run at NTSC: 715.909kHz or PAL: 709.379kHz */
|
|
||||||
|
|
||||||
interval = profint - 1;
|
|
||||||
|
|
||||||
/* order of setting is important ! */
|
|
||||||
ciab.tblo = interval & 0xff;
|
|
||||||
ciab.tbhi = interval >> 8;
|
|
||||||
|
|
||||||
/* enable interrupts for timer B */
|
|
||||||
ciab.icr = (1<<7) | (1<<1);
|
|
||||||
|
|
||||||
/* start timer B in continuous shot mode */
|
|
||||||
ciab.crb = (ciab.crb & 0xc0) | 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
stopprofclock()
|
|
||||||
{
|
|
||||||
/* stop timer B */
|
|
||||||
ciab.crb = ciab.crb & 0xc0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef GPROF
|
#ifdef GPROF
|
||||||
/*
|
/*
|
||||||
* profclock() is expanded in line in lev6intr() unless profiling kernel.
|
* profclock() is expanded in line in lev6intr() unless profiling kernel.
|
||||||
|
|
Loading…
Reference in New Issue