Split statclock into statclock and profclock, and made the method for driving

statclock based on profhz when profiling is enabled MD, since most platforms
don't use this anyway.  This removes the need for statclock_process, whose
only purpose was to subdivide profhz, and gets the profiling clock running
outside of sched_lock on platforms that implement suswintr.
Also changed the interface for starting and stopping the profiling clock to
do just that, instead of changing the rate of statclock, since they can now
be separate.

Reviewed by:	jhb, tmm
Tested on:	i386, sparc64
This commit is contained in:
Jake Burkholder 2003-02-03 17:53:15 +00:00
parent ca26842e2a
commit 238dd3209a
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=110296
34 changed files with 389 additions and 254 deletions

View File

@ -446,17 +446,18 @@ handleclock(void *arg)
hardclock(arg);
}
/*
* We assume newhz is either stathz or profhz, and that neither will
* change after being set up above. Could recalculate intervals here
* but that would be a drag.
*/
void
setstatclockrate(newhz)
int newhz;
cpu_startprofclock(void)
{
/* nothing we can do */
/* nothing to do */
}
void
cpu_stopprofclock(void)
{
/* nothing to do */
}
/*

View File

@ -472,16 +472,19 @@ alpha_clock_interrupt(struct trapframe *framep)
#endif
(*platform.clockintr)(framep);
/* divide hz (1024) by 8 to get stathz (128) */
if ((++schedclk2 & 0x7) == 0)
if ((++schedclk2 & 0x7) == 0) {
if (profprocs != 0)
profclock((struct clockframe *)framep);
statclock((struct clockframe *)framep);
}
#ifdef SMP
} else {
mtx_lock_spin(&sched_lock);
hardclock_process(curthread, TRAPF_USERMODE(framep));
if ((schedclk2 & 0x7) == 0)
statclock_process(curkse, TRAPF_PC(framep),
TRAPF_USERMODE(framep));
mtx_unlock_spin(&sched_lock);
hardclock_process((struct clockframe *)framep);
if ((schedclk2 & 0x7) == 0) {
if (profprocs != 0)
profclock((struct clockframe *)framep);
statclock((struct clockframe *)framep);
}
}
#endif
critical_exit();

View File

@ -365,7 +365,7 @@ Xinvlrng:
iret
/*
* Forward hardclock to another CPU. Pushes a trapframe and calls
* Forward hardclock to another CPU. Pushes a clockframe and calls
* forwarded_hardclock().
*/
.text
@ -389,14 +389,16 @@ Xhardclock:
jmp 10f
1:
incl TD_INTR_NESTING_LEVEL(%ebx)
pushl $0 /* XXX convert trapframe to clockframe */
call forwarded_hardclock
addl $4, %esp /* XXX convert clockframe to trapframe */
decl TD_INTR_NESTING_LEVEL(%ebx)
10:
MEXITCOUNT
jmp doreti
/*
* Forward statclock to another CPU. Pushes a trapframe and calls
* Forward statclock to another CPU. Pushes a clockframe and calls
* forwarded_statclock().
*/
.text
@ -422,7 +424,9 @@ Xstatclock:
jmp 10f
1:
incl TD_INTR_NESTING_LEVEL(%ebx)
pushl $0 /* XXX convert trapframe to clockframe */
call forwarded_statclock
addl $4, %esp /* XXX convert clockframe to trapframe */
decl TD_INTR_NESTING_LEVEL(%ebx)
10:
MEXITCOUNT

View File

@ -15,6 +15,7 @@
#include <sys/proc.h>
#include <sys/sysctl.h>
#include <sys/ucontext.h>
#include <machine/clock.h>
#include <machine/critical.h>
#ifdef SMP
@ -89,6 +90,10 @@ cpu_thread_link(struct thread *td)
void
i386_unpend(void)
{
struct clockframe frame;
frame.cf_cs = SEL_KPL;
frame.cf_eip = (register_t)i386_unpend;
KASSERT(curthread->td_critnest == 0, ("unpend critnest != 0"));
KASSERT((read_eflags() & PSL_I) == 0, ("unpend interrupts enabled1"));
curthread->td_critnest = 1;
@ -131,15 +136,13 @@ i386_unpend(void)
PCPU_SET(spending, mask & ~(1 << irq));
switch(irq) {
case 0: /* bit 0 - hardclock */
mtx_lock_spin(&sched_lock);
hardclock_process(curthread, 0);
mtx_unlock_spin(&sched_lock);
hardclock_process(&frame);
break;
case 1: /* bit 1 - statclock */
mtx_lock_spin(&sched_lock);
statclock_process(curthread->td_kse,
(register_t)i386_unpend, 0);
mtx_unlock_spin(&sched_lock);
if (profprocs != 0)
profclock(&frame);
if (pscnt == psdiv)
statclock(&frame);
break;
}
KASSERT((read_eflags() & PSL_I) == 0,

View File

@ -63,6 +63,7 @@
#include <machine/apic.h>
#include <machine/atomic.h>
#include <machine/clock.h>
#include <machine/cpu.h>
#include <machine/cpufunc.h>
#include <machine/mpapic.h>
@ -2603,17 +2604,17 @@ ap_init(void)
* For statclock, we send an IPI to all CPU's to have them call this
* function.
*
* WARNING! unpend() will call statclock_process() directly and skip this
* WARNING! unpend() will call statclock() directly and skip this
* routine.
*/
void
forwarded_statclock(struct trapframe frame)
forwarded_statclock(struct clockframe frame)
{
mtx_lock_spin(&sched_lock);
statclock_process(curthread->td_kse, TRAPF_PC(&frame),
TRAPF_USERMODE(&frame));
mtx_unlock_spin(&sched_lock);
if (profprocs != 0)
profclock(&frame);
if (pscnt == psdiv)
statclock(&frame);
}
void
@ -2642,12 +2643,10 @@ forward_statclock(void)
* routine.
*/
void
forwarded_hardclock(struct trapframe frame)
forwarded_hardclock(struct clockframe frame)
{
mtx_lock_spin(&sched_lock);
hardclock_process(curthread, TRAPF_USERMODE(&frame));
mtx_unlock_spin(&sched_lock);
hardclock_process(&frame);
}
void

View File

@ -63,6 +63,7 @@
#include <machine/apic.h>
#include <machine/atomic.h>
#include <machine/clock.h>
#include <machine/cpu.h>
#include <machine/cpufunc.h>
#include <machine/mpapic.h>
@ -2603,17 +2604,17 @@ ap_init(void)
* For statclock, we send an IPI to all CPU's to have them call this
* function.
*
* WARNING! unpend() will call statclock_process() directly and skip this
* WARNING! unpend() will call statclock() directly and skip this
* routine.
*/
void
forwarded_statclock(struct trapframe frame)
forwarded_statclock(struct clockframe frame)
{
mtx_lock_spin(&sched_lock);
statclock_process(curthread->td_kse, TRAPF_PC(&frame),
TRAPF_USERMODE(&frame));
mtx_unlock_spin(&sched_lock);
if (profprocs != 0)
profclock(&frame);
if (pscnt == psdiv)
statclock(&frame);
}
void
@ -2642,12 +2643,10 @@ forward_statclock(void)
* routine.
*/
void
forwarded_hardclock(struct trapframe frame)
forwarded_hardclock(struct clockframe frame)
{
mtx_lock_spin(&sched_lock);
hardclock_process(curthread, TRAPF_USERMODE(&frame));
mtx_unlock_spin(&sched_lock);
hardclock_process(&frame);
}
void

View File

@ -130,6 +130,8 @@ static void setup_8254_mixed_mode(void);
int adjkerntz; /* local offset from GMT in seconds */
int clkintr_pending;
int disable_rtc_set; /* disable resettodr() if != 0 */
int pscnt = 1;
int psdiv = 1;
int statclock_disable;
#ifndef TIMER_FREQ
#define TIMER_FREQ 1193182
@ -380,7 +382,13 @@ static void
rtcintr(struct clockframe frame)
{
while (rtcin(RTC_INTR) & RTCIR_PERIOD) {
statclock(&frame);
if (profprocs != 0) {
if (--pscnt == 0)
pscnt = psdiv;
profclock(&frame);
}
if (pscnt == psdiv)
statclock(&frame);
#ifdef SMP
forward_statclock();
#endif
@ -1169,13 +1177,21 @@ setup_8254_mixed_mode()
#endif
void
setstatclockrate(int newhz)
cpu_startprofclock(void)
{
if (newhz == RTC_PROFRATE)
rtc_statusa = RTCSA_DIVIDER | RTCSA_PROF;
else
rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF;
rtc_statusa = RTCSA_DIVIDER | RTCSA_PROF;
writertc(RTC_STATUSA, rtc_statusa);
psdiv = pscnt = psratio;
}
void
cpu_stopprofclock(void)
{
rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF;
writertc(RTC_STATUSA, rtc_statusa);
psdiv = pscnt = 1;
}
static int

View File

@ -16,6 +16,8 @@
*/
extern int adjkerntz;
extern int disable_rtc_set;
extern int pscnt;
extern int psdiv;
extern int statclock_disable;
extern u_int timer_freq;
extern int timer0_max_count;

View File

@ -63,6 +63,7 @@
#include <machine/apic.h>
#include <machine/atomic.h>
#include <machine/clock.h>
#include <machine/cpu.h>
#include <machine/cpufunc.h>
#include <machine/mpapic.h>
@ -2603,17 +2604,17 @@ ap_init(void)
* For statclock, we send an IPI to all CPU's to have them call this
* function.
*
* WARNING! unpend() will call statclock_process() directly and skip this
* WARNING! unpend() will call statclock() directly and skip this
* routine.
*/
void
forwarded_statclock(struct trapframe frame)
forwarded_statclock(struct clockframe frame)
{
mtx_lock_spin(&sched_lock);
statclock_process(curthread->td_kse, TRAPF_PC(&frame),
TRAPF_USERMODE(&frame));
mtx_unlock_spin(&sched_lock);
if (profprocs != 0)
profclock(&frame);
if (pscnt == psdiv)
statclock(&frame);
}
void
@ -2642,12 +2643,10 @@ forward_statclock(void)
* routine.
*/
void
forwarded_hardclock(struct trapframe frame)
forwarded_hardclock(struct clockframe frame)
{
mtx_lock_spin(&sched_lock);
hardclock_process(curthread, TRAPF_USERMODE(&frame));
mtx_unlock_spin(&sched_lock);
hardclock_process(&frame);
}
void

View File

@ -113,9 +113,9 @@ void revoke_apic_irq(int irq);
void bsp_apic_configure(void);
void init_secondary(void);
void forward_statclock(void);
void forwarded_statclock(struct trapframe frame);
void forwarded_statclock(struct clockframe frame);
void forward_hardclock(void);
void forwarded_hardclock(struct trapframe frame);
void forwarded_hardclock(struct clockframe frame);
void ipi_selected(u_int cpus, u_int ipi);
void ipi_all(u_int ipi);
void ipi_all_but_self(u_int ipi);

View File

@ -130,6 +130,8 @@ static void setup_8254_mixed_mode(void);
int adjkerntz; /* local offset from GMT in seconds */
int clkintr_pending;
int disable_rtc_set; /* disable resettodr() if != 0 */
int pscnt = 1;
int psdiv = 1;
int statclock_disable;
#ifndef TIMER_FREQ
#define TIMER_FREQ 1193182
@ -380,7 +382,13 @@ static void
rtcintr(struct clockframe frame)
{
while (rtcin(RTC_INTR) & RTCIR_PERIOD) {
statclock(&frame);
if (profprocs != 0) {
if (--pscnt == 0)
pscnt = psdiv;
profclock(&frame);
}
if (pscnt == psdiv)
statclock(&frame);
#ifdef SMP
forward_statclock();
#endif
@ -1169,13 +1177,21 @@ setup_8254_mixed_mode()
#endif
void
setstatclockrate(int newhz)
cpu_startprofclock(void)
{
if (newhz == RTC_PROFRATE)
rtc_statusa = RTCSA_DIVIDER | RTCSA_PROF;
else
rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF;
rtc_statusa = RTCSA_DIVIDER | RTCSA_PROF;
writertc(RTC_STATUSA, rtc_statusa);
psdiv = pscnt = psratio;
}
void
cpu_stopprofclock(void)
{
rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF;
writertc(RTC_STATUSA, rtc_statusa);
psdiv = pscnt = 1;
}
static int

View File

@ -365,7 +365,7 @@ Xinvlrng:
iret
/*
* Forward hardclock to another CPU. Pushes a trapframe and calls
* Forward hardclock to another CPU. Pushes a clockframe and calls
* forwarded_hardclock().
*/
.text
@ -389,14 +389,16 @@ Xhardclock:
jmp 10f
1:
incl TD_INTR_NESTING_LEVEL(%ebx)
pushl $0 /* XXX convert trapframe to clockframe */
call forwarded_hardclock
addl $4, %esp /* XXX convert clockframe to trapframe */
decl TD_INTR_NESTING_LEVEL(%ebx)
10:
MEXITCOUNT
jmp doreti
/*
* Forward statclock to another CPU. Pushes a trapframe and calls
* Forward statclock to another CPU. Pushes a clockframe and calls
* forwarded_statclock().
*/
.text
@ -422,7 +424,9 @@ Xstatclock:
jmp 10f
1:
incl TD_INTR_NESTING_LEVEL(%ebx)
pushl $0 /* XXX convert trapframe to clockframe */
call forwarded_statclock
addl $4, %esp /* XXX convert clockframe to trapframe */
decl TD_INTR_NESTING_LEVEL(%ebx)
10:
MEXITCOUNT

View File

@ -15,6 +15,7 @@
#include <sys/proc.h>
#include <sys/sysctl.h>
#include <sys/ucontext.h>
#include <machine/clock.h>
#include <machine/critical.h>
#ifdef SMP
@ -89,6 +90,10 @@ cpu_thread_link(struct thread *td)
void
i386_unpend(void)
{
struct clockframe frame;
frame.cf_cs = SEL_KPL;
frame.cf_eip = (register_t)i386_unpend;
KASSERT(curthread->td_critnest == 0, ("unpend critnest != 0"));
KASSERT((read_eflags() & PSL_I) == 0, ("unpend interrupts enabled1"));
curthread->td_critnest = 1;
@ -131,15 +136,13 @@ i386_unpend(void)
PCPU_SET(spending, mask & ~(1 << irq));
switch(irq) {
case 0: /* bit 0 - hardclock */
mtx_lock_spin(&sched_lock);
hardclock_process(curthread, 0);
mtx_unlock_spin(&sched_lock);
hardclock_process(&frame);
break;
case 1: /* bit 1 - statclock */
mtx_lock_spin(&sched_lock);
statclock_process(curthread->td_kse,
(register_t)i386_unpend, 0);
mtx_unlock_spin(&sched_lock);
if (profprocs != 0)
profclock(&frame);
if (pscnt == psdiv)
statclock(&frame);
break;
}
KASSERT((read_eflags() & PSL_I) == 0,

View File

@ -63,6 +63,7 @@
#include <machine/apic.h>
#include <machine/atomic.h>
#include <machine/clock.h>
#include <machine/cpu.h>
#include <machine/cpufunc.h>
#include <machine/mpapic.h>
@ -2603,17 +2604,17 @@ ap_init(void)
* For statclock, we send an IPI to all CPU's to have them call this
* function.
*
* WARNING! unpend() will call statclock_process() directly and skip this
* WARNING! unpend() will call statclock() directly and skip this
* routine.
*/
void
forwarded_statclock(struct trapframe frame)
forwarded_statclock(struct clockframe frame)
{
mtx_lock_spin(&sched_lock);
statclock_process(curthread->td_kse, TRAPF_PC(&frame),
TRAPF_USERMODE(&frame));
mtx_unlock_spin(&sched_lock);
if (profprocs != 0)
profclock(&frame);
if (pscnt == psdiv)
statclock(&frame);
}
void
@ -2642,12 +2643,10 @@ forward_statclock(void)
* routine.
*/
void
forwarded_hardclock(struct trapframe frame)
forwarded_hardclock(struct clockframe frame)
{
mtx_lock_spin(&sched_lock);
hardclock_process(curthread, TRAPF_USERMODE(&frame));
mtx_unlock_spin(&sched_lock);
hardclock_process(&frame);
}
void

View File

@ -63,6 +63,7 @@
#include <machine/apic.h>
#include <machine/atomic.h>
#include <machine/clock.h>
#include <machine/cpu.h>
#include <machine/cpufunc.h>
#include <machine/mpapic.h>
@ -2603,17 +2604,17 @@ ap_init(void)
* For statclock, we send an IPI to all CPU's to have them call this
* function.
*
* WARNING! unpend() will call statclock_process() directly and skip this
* WARNING! unpend() will call statclock() directly and skip this
* routine.
*/
void
forwarded_statclock(struct trapframe frame)
forwarded_statclock(struct clockframe frame)
{
mtx_lock_spin(&sched_lock);
statclock_process(curthread->td_kse, TRAPF_PC(&frame),
TRAPF_USERMODE(&frame));
mtx_unlock_spin(&sched_lock);
if (profprocs != 0)
profclock(&frame);
if (pscnt == psdiv)
statclock(&frame);
}
void
@ -2642,12 +2643,10 @@ forward_statclock(void)
* routine.
*/
void
forwarded_hardclock(struct trapframe frame)
forwarded_hardclock(struct clockframe frame)
{
mtx_lock_spin(&sched_lock);
hardclock_process(curthread, TRAPF_USERMODE(&frame));
mtx_unlock_spin(&sched_lock);
hardclock_process(&frame);
}
void

View File

@ -130,6 +130,8 @@ static void setup_8254_mixed_mode(void);
int adjkerntz; /* local offset from GMT in seconds */
int clkintr_pending;
int disable_rtc_set; /* disable resettodr() if != 0 */
int pscnt = 1;
int psdiv = 1;
int statclock_disable;
#ifndef TIMER_FREQ
#define TIMER_FREQ 1193182
@ -380,7 +382,13 @@ static void
rtcintr(struct clockframe frame)
{
while (rtcin(RTC_INTR) & RTCIR_PERIOD) {
statclock(&frame);
if (profprocs != 0) {
if (--pscnt == 0)
pscnt = psdiv;
profclock(&frame);
}
if (pscnt == psdiv)
statclock(&frame);
#ifdef SMP
forward_statclock();
#endif
@ -1169,13 +1177,21 @@ setup_8254_mixed_mode()
#endif
void
setstatclockrate(int newhz)
cpu_startprofclock(void)
{
if (newhz == RTC_PROFRATE)
rtc_statusa = RTCSA_DIVIDER | RTCSA_PROF;
else
rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF;
rtc_statusa = RTCSA_DIVIDER | RTCSA_PROF;
writertc(RTC_STATUSA, rtc_statusa);
psdiv = pscnt = psratio;
}
void
cpu_stopprofclock(void)
{
rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF;
writertc(RTC_STATUSA, rtc_statusa);
psdiv = pscnt = 1;
}
static int

View File

@ -16,6 +16,8 @@
*/
extern int adjkerntz;
extern int disable_rtc_set;
extern int pscnt;
extern int psdiv;
extern int statclock_disable;
extern u_int timer_freq;
extern int timer0_max_count;

View File

@ -63,6 +63,7 @@
#include <machine/apic.h>
#include <machine/atomic.h>
#include <machine/clock.h>
#include <machine/cpu.h>
#include <machine/cpufunc.h>
#include <machine/mpapic.h>
@ -2603,17 +2604,17 @@ ap_init(void)
* For statclock, we send an IPI to all CPU's to have them call this
* function.
*
* WARNING! unpend() will call statclock_process() directly and skip this
* WARNING! unpend() will call statclock() directly and skip this
* routine.
*/
void
forwarded_statclock(struct trapframe frame)
forwarded_statclock(struct clockframe frame)
{
mtx_lock_spin(&sched_lock);
statclock_process(curthread->td_kse, TRAPF_PC(&frame),
TRAPF_USERMODE(&frame));
mtx_unlock_spin(&sched_lock);
if (profprocs != 0)
profclock(&frame);
if (pscnt == psdiv)
statclock(&frame);
}
void
@ -2642,12 +2643,10 @@ forward_statclock(void)
* routine.
*/
void
forwarded_hardclock(struct trapframe frame)
forwarded_hardclock(struct clockframe frame)
{
mtx_lock_spin(&sched_lock);
hardclock_process(curthread, TRAPF_USERMODE(&frame));
mtx_unlock_spin(&sched_lock);
hardclock_process(&frame);
}
void

View File

@ -113,9 +113,9 @@ void revoke_apic_irq(int irq);
void bsp_apic_configure(void);
void init_secondary(void);
void forward_statclock(void);
void forwarded_statclock(struct trapframe frame);
void forwarded_statclock(struct clockframe frame);
void forward_hardclock(void);
void forwarded_hardclock(struct trapframe frame);
void forwarded_hardclock(struct clockframe frame);
void ipi_selected(u_int cpus, u_int ipi);
void ipi_all(u_int ipi);
void ipi_all_but_self(u_int ipi);

View File

@ -365,7 +365,7 @@ Xinvlrng:
iret
/*
* Forward hardclock to another CPU. Pushes a trapframe and calls
* Forward hardclock to another CPU. Pushes a clockframe and calls
* forwarded_hardclock().
*/
.text
@ -389,14 +389,16 @@ Xhardclock:
jmp 10f
1:
incl TD_INTR_NESTING_LEVEL(%ebx)
pushl $0 /* XXX convert trapframe to clockframe */
call forwarded_hardclock
addl $4, %esp /* XXX convert clockframe to trapframe */
decl TD_INTR_NESTING_LEVEL(%ebx)
10:
MEXITCOUNT
jmp doreti
/*
* Forward statclock to another CPU. Pushes a trapframe and calls
* Forward statclock to another CPU. Pushes a clockframe and calls
* forwarded_statclock().
*/
.text
@ -422,7 +424,9 @@ Xstatclock:
jmp 10f
1:
incl TD_INTR_NESTING_LEVEL(%ebx)
pushl $0 /* XXX convert trapframe to clockframe */
call forwarded_statclock
addl $4, %esp /* XXX convert clockframe to trapframe */
decl TD_INTR_NESTING_LEVEL(%ebx)
10:
MEXITCOUNT

View File

@ -130,6 +130,8 @@ static void setup_8254_mixed_mode(void);
int adjkerntz; /* local offset from GMT in seconds */
int clkintr_pending;
int disable_rtc_set; /* disable resettodr() if != 0 */
int pscnt = 1;
int psdiv = 1;
int statclock_disable;
#ifndef TIMER_FREQ
#define TIMER_FREQ 1193182
@ -380,7 +382,13 @@ static void
rtcintr(struct clockframe frame)
{
while (rtcin(RTC_INTR) & RTCIR_PERIOD) {
statclock(&frame);
if (profprocs != 0) {
if (--pscnt == 0)
pscnt = psdiv;
profclock(&frame);
}
if (pscnt == psdiv)
statclock(&frame);
#ifdef SMP
forward_statclock();
#endif
@ -1169,13 +1177,21 @@ setup_8254_mixed_mode()
#endif
void
setstatclockrate(int newhz)
cpu_startprofclock(void)
{
if (newhz == RTC_PROFRATE)
rtc_statusa = RTCSA_DIVIDER | RTCSA_PROF;
else
rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF;
rtc_statusa = RTCSA_DIVIDER | RTCSA_PROF;
writertc(RTC_STATUSA, rtc_statusa);
psdiv = pscnt = psratio;
}
void
cpu_stopprofclock(void)
{
rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF;
writertc(RTC_STATUSA, rtc_statusa);
psdiv = pscnt = 1;
}
static int

View File

@ -259,12 +259,19 @@ calibrate_clocks(u_int32_t firmware_freq)
* change after being set up above. Could recalculate intervals here
* but that would be a drag.
*/
void
setstatclockrate(newhz)
int newhz;
cpu_startprofclock(void)
{
/* nothing we can do */
/* nothing to do */
}
void
cpu_stopprofclock(void)
{
/* nothing to do */
}
/*

View File

@ -132,16 +132,19 @@ interrupt(u_int64_t vector, struct trapframe *framep)
#endif
hardclock((struct clockframe *)framep);
/* divide hz (1024) by 8 to get stathz (128) */
if ((++schedclk2 & 0x7) == 0)
if ((++schedclk2 & 0x7) == 0) {
if (profprocs != 0)
profclock((struct clockframe *)framep);
statclock((struct clockframe *)framep);
}
#ifdef SMP
} else {
mtx_lock_spin(&sched_lock);
hardclock_process(curthread, TRAPF_USERMODE(framep));
if ((schedclk2 & 0x7) == 0)
statclock_process(curkse, TRAPF_PC(framep),
TRAPF_USERMODE(framep));
mtx_unlock_spin(&sched_lock);
hardclock_process((struct clockframe *)framep);
if ((schedclk2 & 0x7) == 0) {
if (profprocs != 0)
profclock((struct clockframe *)framep);
statclock((struct clockframe *)framep);
}
}
#endif
critical_exit();

View File

@ -130,6 +130,8 @@ static void setup_8254_mixed_mode(void);
int adjkerntz; /* local offset from GMT in seconds */
int clkintr_pending;
int disable_rtc_set; /* disable resettodr() if != 0 */
int pscnt = 1;
int psdiv = 1;
int statclock_disable;
#ifndef TIMER_FREQ
#define TIMER_FREQ 1193182
@ -380,7 +382,13 @@ static void
rtcintr(struct clockframe frame)
{
while (rtcin(RTC_INTR) & RTCIR_PERIOD) {
statclock(&frame);
if (profprocs != 0) {
if (--pscnt == 0)
pscnt = psdiv;
profclock(&frame);
}
if (pscnt == psdiv)
statclock(&frame);
#ifdef SMP
forward_statclock();
#endif
@ -1169,13 +1177,21 @@ setup_8254_mixed_mode()
#endif
void
setstatclockrate(int newhz)
cpu_startprofclock(void)
{
if (newhz == RTC_PROFRATE)
rtc_statusa = RTCSA_DIVIDER | RTCSA_PROF;
else
rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF;
rtc_statusa = RTCSA_DIVIDER | RTCSA_PROF;
writertc(RTC_STATUSA, rtc_statusa);
psdiv = pscnt = psratio;
}
void
cpu_stopprofclock(void)
{
rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF;
writertc(RTC_STATUSA, rtc_statusa);
psdiv = pscnt = 1;
}
static int

View File

@ -122,10 +122,9 @@ long tk_rawcc;
int stathz;
int profhz;
static int profprocs;
int profprocs;
int ticks;
static int psdiv, pscnt; /* prof => stat divider */
int psratio; /* ratio: prof / stat */
int psratio;
/*
* Initialize clock frequencies and start both clocks running.
@ -141,7 +140,6 @@ initclocks(dummy)
* Set divisors to 1 (normal case) and let the machine-specific
* code do its bit.
*/
psdiv = pscnt = 1;
cpu_initclocks();
#ifdef DEVICE_POLLING
@ -157,32 +155,27 @@ initclocks(dummy)
}
/*
* Each time the real-time timer fires, this function is called on all CPUs
* with each CPU passing in its curthread as the first argument. If possible
* a nice optimization in the future would be to allow the CPU receiving the
* actual real-time timer interrupt to call this function on behalf of the
* other CPUs rather than sending an IPI to all other CPUs so that they
* can call this function. Note that hardclock() calls hardclock_process()
* for the CPU receiving the timer interrupt, so only the other CPUs in the
* system need to call this function (or have it called on their behalf.
* Each time the real-time timer fires, this function is called on all CPUs.
* Note that hardclock() calls hardclock_process() for the boot CPU, so only
* the other CPUs in the system need to call this function.
*/
void
hardclock_process(td, user)
struct thread *td;
int user;
hardclock_process(frame)
register struct clockframe *frame;
{
struct pstats *pstats;
struct thread *td = curthread;
struct proc *p = td->td_proc;
/*
* Run current process's virtual and profile time, as needed.
*/
mtx_assert(&sched_lock, MA_OWNED);
mtx_lock_spin_flags(&sched_lock, MTX_QUIET);
if (p->p_flag & P_KSES) {
/* XXXKSE What to do? */
} else {
pstats = p->p_stats;
if (user &&
if (CLKF_USERMODE(frame) &&
timevalisset(&pstats->p_timer[ITIMER_VIRTUAL].it_value) &&
itimerdecr(&pstats->p_timer[ITIMER_VIRTUAL], tick) == 0) {
p->p_sflag |= PS_ALRMPEND;
@ -194,6 +187,7 @@ hardclock_process(td, user)
td->td_kse->ke_flags |= KEF_ASTPENDING;
}
}
mtx_unlock_spin_flags(&sched_lock, MTX_QUIET);
}
/*
@ -206,9 +200,7 @@ hardclock(frame)
int need_softclock = 0;
CTR0(KTR_CLK, "hardclock fired");
mtx_lock_spin_flags(&sched_lock, MTX_QUIET);
hardclock_process(curthread, CLKF_USERMODE(frame));
mtx_unlock_spin_flags(&sched_lock, MTX_QUIET);
hardclock_process(frame);
tc_ticktock();
/*
@ -216,8 +208,10 @@ hardclock(frame)
*
* XXX: this only works for UP
*/
if (stathz == 0)
if (stathz == 0) {
profclock(frame);
statclock(frame);
}
#ifdef DEVICE_POLLING
hardclock_device_poll(); /* this is very short and quick */
@ -312,7 +306,6 @@ void
startprofclock(p)
register struct proc *p;
{
int s;
/*
* XXX; Right now sched_lock protects statclock(), but perhaps
@ -322,12 +315,8 @@ startprofclock(p)
mtx_lock_spin(&sched_lock);
if ((p->p_sflag & PS_PROFIL) == 0) {
p->p_sflag |= PS_PROFIL;
if (++profprocs == 1 && stathz != 0) {
s = splstatclock();
psdiv = pscnt = psratio;
setstatclockrate(profhz);
splx(s);
}
if (++profprocs == 1)
cpu_startprofclock();
}
mtx_unlock_spin(&sched_lock);
}
@ -339,57 +328,41 @@ void
stopprofclock(p)
register struct proc *p;
{
int s;
mtx_lock_spin(&sched_lock);
if (p->p_sflag & PS_PROFIL) {
p->p_sflag &= ~PS_PROFIL;
if (--profprocs == 0 && stathz != 0) {
s = splstatclock();
psdiv = pscnt = 1;
setstatclockrate(stathz);
splx(s);
}
if (--profprocs == 0)
cpu_stopprofclock();
}
mtx_unlock_spin(&sched_lock);
}
/*
* Do process and kernel statistics. Most of the statistics are only
* Statistics clock. Grab profile sample, and if divider reaches 0,
* do process and kernel statistics. Most of the statistics are only
* used by user-level statistics programs. The main exceptions are
* ke->ke_uticks, p->p_sticks, p->p_iticks, and p->p_estcpu. This function
* should be called by all CPUs in the system for each statistics clock
* interrupt. See the description of hardclock_process for more detail on
* this function's relationship to statclock.
* ke->ke_uticks, p->p_sticks, p->p_iticks, and p->p_estcpu.
* This should be called by all active processors.
*/
void
statclock_process(ke, pc, user)
struct kse *ke;
register_t pc;
int user;
statclock(frame)
register struct clockframe *frame;
{
#ifdef GPROF
struct gmonparam *g;
int i;
#endif
struct pstats *pstats;
long rss;
struct rusage *ru;
struct vmspace *vm;
struct proc *p = ke->ke_proc;
struct thread *td = ke->ke_thread; /* current thread */
struct thread *td;
struct kse *ke;
struct proc *p;
long rss;
KASSERT(ke == curthread->td_kse, ("statclock_process: td != curthread"));
mtx_assert(&sched_lock, MA_OWNED);
if (user) {
/*
* Came from user mode; CPU was in user state.
* If this process is being profiled, record the tick.
*/
if (p->p_sflag & PS_PROFIL)
addupc_intr(ke, pc, 1);
if (pscnt < psdiv)
return;
td = curthread;
p = td->td_proc;
mtx_lock_spin_flags(&sched_lock, MTX_QUIET);
ke = td->td_kse;
if (CLKF_USERMODE(frame)) {
/*
* Charge the time as appropriate.
*/
@ -401,21 +374,6 @@ statclock_process(ke, pc, user)
else
cp_time[CP_USER]++;
} else {
#ifdef GPROF
/*
* Kernel statistics are just like addupc_intr, only easier.
*/
g = &_gmonparam;
if (g->state == GMON_PROF_ON) {
i = pc - g->lowpc;
if (i < g->textsize) {
i /= HISTFRACTION * sizeof(*g->kcount);
g->kcount[i]++;
}
}
#endif
if (pscnt < psdiv)
return;
/*
* Came from kernel mode, so we were:
* - handling an interrupt,
@ -455,25 +413,43 @@ statclock_process(ke, pc, user)
if (ru->ru_maxrss < rss)
ru->ru_maxrss = rss;
}
mtx_unlock_spin_flags(&sched_lock, MTX_QUIET);
}
/*
* Statistics clock. Grab profile sample, and if divider reaches 0,
* do process and kernel statistics. Most of the statistics are only
* used by user-level statistics programs. The main exceptions are
* ke->ke_uticks, p->p_sticks, p->p_iticks, and p->p_estcpu.
*/
void
statclock(frame)
profclock(frame)
register struct clockframe *frame;
{
struct thread *td;
#ifdef GPROF
struct gmonparam *g;
int i;
#endif
CTR0(KTR_CLK, "statclock fired");
mtx_lock_spin_flags(&sched_lock, MTX_QUIET);
if (--pscnt == 0)
pscnt = psdiv;
statclock_process(curthread->td_kse, CLKF_PC(frame), CLKF_USERMODE(frame));
mtx_unlock_spin_flags(&sched_lock, MTX_QUIET);
if (CLKF_USERMODE(frame)) {
/*
* Came from user mode; CPU was in user state.
* If this process is being profiled, record the tick.
*/
td = curthread;
if (td->td_proc->p_sflag & PS_PROFIL)
addupc_intr(td->td_kse, CLKF_PC(frame), 1);
}
#ifdef GPROF
else {
/*
* Kernel statistics are just like addupc_intr, only easier.
*/
g = &_gmonparam;
if (g->state == GMON_PROF_ON) {
i = CLKF_PC(frame) - g->lowpc;
if (i < g->textsize) {
i /= HISTFRACTION * sizeof(*g->kcount);
g->kcount[i]++;
}
}
}
#endif
}
/*

View File

@ -140,6 +140,8 @@ static void setup_8254_mixed_mode(void);
int adjkerntz; /* local offset from GMT in seconds */
int clkintr_pending;
int disable_rtc_set; /* disable resettodr() if != 0 */
int pscnt = 1;
int psdiv = 1;
int statclock_disable;
#ifndef TIMER_FREQ
#ifdef PC98
@ -441,7 +443,13 @@ static void
rtcintr(struct clockframe frame)
{
while (rtcin(RTC_INTR) & RTCIR_PERIOD) {
statclock(&frame);
if (profprocs != 0) {
if (--pscnt == 0)
pscnt = psdiv;
profclock(&frame);
}
if (pscnt == psdiv)
statclock(&frame);
#ifdef SMP
forward_statclock();
#endif
@ -1518,7 +1526,7 @@ setup_8254_mixed_mode()
#endif
void
setstatclockrate(int newhz)
cpu_startprofclock(void)
{
#ifndef PC98
if (newhz == RTC_PROFRATE)
@ -1529,6 +1537,11 @@ setstatclockrate(int newhz)
#endif
}
void
cpu_stopprofclock(void)
{
}
static int
sysctl_machdep_i8254_freq(SYSCTL_HANDLER_ARGS)
{

View File

@ -140,6 +140,8 @@ static void setup_8254_mixed_mode(void);
int adjkerntz; /* local offset from GMT in seconds */
int clkintr_pending;
int disable_rtc_set; /* disable resettodr() if != 0 */
int pscnt = 1;
int psdiv = 1;
int statclock_disable;
#ifndef TIMER_FREQ
#ifdef PC98
@ -441,7 +443,13 @@ static void
rtcintr(struct clockframe frame)
{
while (rtcin(RTC_INTR) & RTCIR_PERIOD) {
statclock(&frame);
if (profprocs != 0) {
if (--pscnt == 0)
pscnt = psdiv;
profclock(&frame);
}
if (pscnt == psdiv)
statclock(&frame);
#ifdef SMP
forward_statclock();
#endif
@ -1518,7 +1526,7 @@ setup_8254_mixed_mode()
#endif
void
setstatclockrate(int newhz)
cpu_startprofclock(void)
{
#ifndef PC98
if (newhz == RTC_PROFRATE)
@ -1529,6 +1537,11 @@ setstatclockrate(int newhz)
#endif
}
void
cpu_stopprofclock(void)
{
}
static int
sysctl_machdep_i8254_freq(SYSCTL_HANDLER_ARGS)
{

View File

@ -140,6 +140,8 @@ static void setup_8254_mixed_mode(void);
int adjkerntz; /* local offset from GMT in seconds */
int clkintr_pending;
int disable_rtc_set; /* disable resettodr() if != 0 */
int pscnt = 1;
int psdiv = 1;
int statclock_disable;
#ifndef TIMER_FREQ
#ifdef PC98
@ -441,7 +443,13 @@ static void
rtcintr(struct clockframe frame)
{
while (rtcin(RTC_INTR) & RTCIR_PERIOD) {
statclock(&frame);
if (profprocs != 0) {
if (--pscnt == 0)
pscnt = psdiv;
profclock(&frame);
}
if (pscnt == psdiv)
statclock(&frame);
#ifdef SMP
forward_statclock();
#endif
@ -1518,7 +1526,7 @@ setup_8254_mixed_mode()
#endif
void
setstatclockrate(int newhz)
cpu_startprofclock(void)
{
#ifndef PC98
if (newhz == RTC_PROFRATE)
@ -1529,6 +1537,11 @@ setstatclockrate(int newhz)
#endif
}
void
cpu_stopprofclock(void)
{
}
static int
sysctl_machdep_i8254_freq(SYSCTL_HANDLER_ARGS)
{

View File

@ -319,8 +319,13 @@ delay(int n)
* Nothing to do.
*/
void
setstatclockrate(int arg)
cpu_startprofclock(void)
{
/* Do nothing */
}
void
cpu_stopprofclock(void)
{
}

View File

@ -319,8 +319,13 @@ delay(int n)
* Nothing to do.
*/
void
setstatclockrate(int arg)
cpu_startprofclock(void)
{
/* Do nothing */
}
void
cpu_stopprofclock(void)
{
}

View File

@ -48,9 +48,13 @@ DELAY(int n)
}
void
setstatclockrate(int newhz)
cpu_startprofclock(void)
{
}
void
cpu_stopprofclock(void)
{
/* TODO; */
}
int

View File

@ -57,6 +57,7 @@ int tick_missed; /* statistics */
void
cpu_initclocks(void)
{
stathz = hz;
tick_start(tick_hardclock);
}
@ -64,20 +65,13 @@ static __inline void
tick_process(struct clockframe *cf)
{
#ifdef SMP
if (PCPU_GET(cpuid) == 0)
hardclock(cf);
else {
CTR1(KTR_CLK, "tick_process: AP, cpuid=%d", PCPU_GET(cpuid));
mtx_lock_spin_flags(&sched_lock, MTX_QUIET);
hardclock_process(curthread, CLKF_USERMODE(cf));
statclock_process(curthread->td_kse, CLKF_PC(cf),
CLKF_USERMODE(cf));
mtx_unlock_spin_flags(&sched_lock, MTX_QUIET);
}
#else
hardclock(cf);
#endif
else
hardclock_process(cf);
if (profprocs != 0)
profclock(cf);
statclock(cf);
}
void

View File

@ -75,6 +75,7 @@ extern int hz; /* system clock's frequency */
extern int psratio; /* ratio: prof / stat */
extern int stathz; /* statistics clock's frequency */
extern int profhz; /* profiling clock's frequency */
extern int profprocs; /* number of process's profiling */
extern int ticks;
extern int lbolt; /* once a second sleep address */

View File

@ -199,14 +199,15 @@ int suword64(void *base, int64_t word);
void realitexpire(void *);
void hardclock(struct clockframe *frame);
void hardclock_process(struct thread *td, int user);
void hardclock_process(struct clockframe *frame);
void softclock(void *);
void statclock(struct clockframe *frame);
void statclock_process(struct kse *ke, register_t pc, int user);
void profclock(struct clockframe *frame);
void startprofclock(struct proc *);
void stopprofclock(struct proc *);
void setstatclockrate(int hzrate);
void cpu_startprofclock(void);
void cpu_stopprofclock(void);
/* flags for suser() and suser_cred() */
#define PRISON_ROOT 1