svn commit: r208494 - in head/sys: amd64/amd64 amd64/include i386/i386 i386/include kern pc98/cbus sys x86/isa x86/x86

Andriy Gapon avg at freebsd.org
Mon May 24 14:37:28 UTC 2010


on 24/05/2010 14:40 Alexander Motin said the following:
> Author: mav
> Date: Mon May 24 11:40:49 2010
> New Revision: 208494
> URL: http://svn.freebsd.org/changeset/base/208494
> 
> Log:
>   - Implement MI helper functions, dividing one or two timer interrupts with
>   arbitrary frequencies into hardclock(), statclock() and profclock() calls.
>   Same code with minor variations duplicated several times over the tree for
>   different timer drivers and architectures.
>   - Switch all x86 archs to new functions, simplifying the code and removing
>   extra logic from timer drivers. Other archs are also welcome.


Alexander,

could you please describe the new code/KPI in greater detail, perhaps on a more
appropriate mailing list?
For me it is not immediately obvious why IPI_PROFCLOCK is gone now.  I haven't
spent much time reverse engineering this change and perhaps it's easier for you
to describe the change.

Thanks!

> Modified:
>   head/sys/amd64/amd64/mp_machdep.c
>   head/sys/amd64/include/apicvar.h
>   head/sys/amd64/include/clock.h
>   head/sys/i386/i386/mp_machdep.c
>   head/sys/i386/include/apicvar.h
>   head/sys/i386/include/clock.h
>   head/sys/kern/kern_clock.c
>   head/sys/pc98/cbus/clock.c
>   head/sys/sys/kernel.h
>   head/sys/sys/systm.h
>   head/sys/x86/isa/clock.c
>   head/sys/x86/x86/local_apic.c
> 
> Modified: head/sys/amd64/amd64/mp_machdep.c
> ==============================================================================
> --- head/sys/amd64/amd64/mp_machdep.c	Mon May 24 11:14:40 2010	(r208493)
> +++ head/sys/amd64/amd64/mp_machdep.c	Mon May 24 11:40:49 2010	(r208494)
> @@ -1112,9 +1112,6 @@ ipi_bitmap_handler(struct trapframe fram
>  
>  	if (ipi_bitmap & (1 << IPI_STATCLOCK))
>  		statclockintr(&frame);
> -
> -	if (ipi_bitmap & (1 << IPI_PROFCLOCK))
> -		profclockintr(&frame);
>  }
>  
>  /*
> 
> Modified: head/sys/amd64/include/apicvar.h
> ==============================================================================
> --- head/sys/amd64/include/apicvar.h	Mon May 24 11:14:40 2010	(r208493)
> +++ head/sys/amd64/include/apicvar.h	Mon May 24 11:40:49 2010	(r208494)
> @@ -123,8 +123,7 @@
>  #define IPI_PREEMPT     1
>  #define IPI_HARDCLOCK   2
>  #define IPI_STATCLOCK   3
> -#define IPI_PROFCLOCK   4
> -#define IPI_BITMAP_LAST IPI_PROFCLOCK
> +#define IPI_BITMAP_LAST IPI_STATCLOCK
>  #define IPI_IS_BITMAPED(x) ((x) <= IPI_BITMAP_LAST)
>  
>  #define	IPI_STOP	(APIC_IPI_INTS + 7)	/* Stop CPU until restarted. */
> 
> Modified: head/sys/amd64/include/clock.h
> ==============================================================================
> --- head/sys/amd64/include/clock.h	Mon May 24 11:14:40 2010	(r208493)
> +++ head/sys/amd64/include/clock.h	Mon May 24 11:40:49 2010	(r208494)
> @@ -27,7 +27,6 @@ struct trapframe;
>  
>  int	hardclockintr(struct trapframe *frame);
>  int	statclockintr(struct trapframe *frame);
> -int	profclockintr(struct trapframe *frame);
>  
>  /*
>   * Driver to clock driver interface.
> 
> Modified: head/sys/i386/i386/mp_machdep.c
> ==============================================================================
> --- head/sys/i386/i386/mp_machdep.c	Mon May 24 11:14:40 2010	(r208493)
> +++ head/sys/i386/i386/mp_machdep.c	Mon May 24 11:40:49 2010	(r208494)
> @@ -1279,9 +1279,6 @@ ipi_bitmap_handler(struct trapframe fram
>  
>  	if (ipi_bitmap & (1 << IPI_STATCLOCK))
>  		statclockintr(&frame); 
> -
> -	if (ipi_bitmap & (1 << IPI_PROFCLOCK))
> -		profclockintr(&frame);
>  }
>  
>  /*
> 
> Modified: head/sys/i386/include/apicvar.h
> ==============================================================================
> --- head/sys/i386/include/apicvar.h	Mon May 24 11:14:40 2010	(r208493)
> +++ head/sys/i386/include/apicvar.h	Mon May 24 11:40:49 2010	(r208494)
> @@ -124,8 +124,7 @@
>  #define IPI_PREEMPT     1
>  #define IPI_HARDCLOCK   2 
>  #define IPI_STATCLOCK   3 
> -#define IPI_PROFCLOCK   4 
> -#define IPI_BITMAP_LAST IPI_PROFCLOCK
> +#define IPI_BITMAP_LAST IPI_STATCLOCK
>  #define IPI_IS_BITMAPED(x) ((x) <= IPI_BITMAP_LAST)
>  
>  #define	IPI_STOP	(APIC_IPI_INTS + 7)	/* Stop CPU until restarted. */
> @@ -152,8 +151,7 @@
>  #define IPI_PREEMPT     1
>  #define IPI_HARDCLOCK   2 
>  #define IPI_STATCLOCK   3 
> -#define IPI_PROFCLOCK   4 
> -#define IPI_BITMAP_LAST IPI_PROFCLOCK
> +#define IPI_BITMAP_LAST IPI_STATCLOCK
>  #define IPI_IS_BITMAPED(x) ((x) <= IPI_BITMAP_LAST)
>  
>  #define	IPI_STOP	(APIC_IPI_INTS + 7)	/* Stop CPU until restarted. */
> 
> Modified: head/sys/i386/include/clock.h
> ==============================================================================
> --- head/sys/i386/include/clock.h	Mon May 24 11:14:40 2010	(r208493)
> +++ head/sys/i386/include/clock.h	Mon May 24 11:40:49 2010	(r208494)
> @@ -27,7 +27,6 @@ struct trapframe;
>   
>  int	hardclockintr(struct trapframe *frame);
>  int	statclockintr(struct trapframe *frame);
> -int	profclockintr(struct trapframe *frame);
>  
>  /*
>   * Driver to clock driver interface.
> 
> Modified: head/sys/kern/kern_clock.c
> ==============================================================================
> --- head/sys/kern/kern_clock.c	Mon May 24 11:14:40 2010	(r208493)
> +++ head/sys/kern/kern_clock.c	Mon May 24 11:40:49 2010	(r208494)
> @@ -374,6 +374,12 @@ int	profprocs;
>  int	ticks;
>  int	psratio;
>  
> +int	timer1hz;
> +int	timer2hz;
> +static DPCPU_DEFINE(u_int, hard_cnt);
> +static DPCPU_DEFINE(u_int, stat_cnt);
> +static DPCPU_DEFINE(u_int, prof_cnt);
> +
>  /*
>   * Initialize clock frequencies and start both clocks running.
>   */
> @@ -403,6 +409,52 @@ initclocks(dummy)
>  #endif
>  }
>  
> +void
> +timer1clock(int usermode, uintfptr_t pc)
> +{
> +	u_int *cnt;
> +
> +	cnt = DPCPU_PTR(hard_cnt);
> +	*cnt += hz;
> +	if (*cnt >= timer1hz) {
> +		*cnt -= timer1hz;
> +		if (*cnt >= timer1hz)
> +			*cnt = 0;
> +		if (PCPU_GET(cpuid) == 0)
> +			hardclock(usermode, pc);
> +		else
> +			hardclock_cpu(usermode);
> +	}
> +	if (timer2hz == 0)
> +		timer2clock(usermode, pc);
> +}
> +
> +void
> +timer2clock(int usermode, uintfptr_t pc)
> +{
> +	u_int *cnt;
> +	int t2hz = timer2hz ? timer2hz : timer1hz;
> +
> +	cnt = DPCPU_PTR(stat_cnt);
> +	*cnt += stathz;
> +	if (*cnt >= t2hz) {
> +		*cnt -= t2hz;
> +		if (*cnt >= t2hz)
> +			*cnt = 0;
> +		statclock(usermode);
> +	}
> +	if (profprocs == 0)
> +		return;
> +	cnt = DPCPU_PTR(prof_cnt);
> +	*cnt += profhz;
> +	if (*cnt >= t2hz) {
> +		*cnt -= t2hz;
> +		if (*cnt >= t2hz)
> +			*cnt = 0;
> +			profclock(usermode, pc);
> +	}
> +}
> +
>  /*
>   * Each time the real-time timer fires, this function is called on all CPUs.
>   * Note that hardclock() calls hardclock_cpu() for the boot CPU, so only
> 
> Modified: head/sys/pc98/cbus/clock.c
> ==============================================================================
> --- head/sys/pc98/cbus/clock.c	Mon May 24 11:14:40 2010	(r208493)
> +++ head/sys/pc98/cbus/clock.c	Mon May 24 11:40:49 2010	(r208494)
> @@ -129,10 +129,7 @@ int
>  hardclockintr(struct trapframe *frame)
>  {
>  
> -	if (PCPU_GET(cpuid) == 0)
> -		hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
> -	else
> -		hardclock_cpu(TRAPF_USERMODE(frame));
> +	timer1clock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
>  	return (FILTER_HANDLED);
>  }
>  
> @@ -143,13 +140,6 @@ statclockintr(struct trapframe *frame)
>  	return (FILTER_HANDLED);
>  }
>  
> -int
> -profclockintr(struct trapframe *frame)
> -{
> -
> -	return (FILTER_HANDLED);
> -}
> -
>  static int
>  clkintr(struct trapframe *frame)
>  {
> @@ -448,6 +438,7 @@ cpu_initclocks()
>  	 * timecounter to user a simpler algorithm.
>  	 */
>  	if (using_lapic_timer == LAPIC_CLOCK_NONE) {
> +		timer1hz = hz;
>  		intr_add_handler("clk", 0, (driver_filter_t *)clkintr, NULL,
>  		    NULL, INTR_TYPE_CLK, NULL);
>  		i8254_intsrc = intr_lookup_source(0);
> @@ -460,6 +451,14 @@ cpu_initclocks()
>  		i8254_timecounter.tc_counter_mask = 0xffff;
>  		set_i8254_freq(i8254_freq, hz);
>  	}
> +	if (using_lapic_timer != LAPIC_CLOCK_ALL) {
> +		profhz = hz;
> +		if (hz < 128)
> +			stathz = hz;
> +		else
> +			stathz = hz / (hz / 128);
> +	}
> +	timer2hz = 0;
>  
>  	init_TSC_tc();
>  }
> 
> Modified: head/sys/sys/kernel.h
> ==============================================================================
> --- head/sys/sys/kernel.h	Mon May 24 11:14:40 2010	(r208493)
> +++ head/sys/sys/kernel.h	Mon May 24 11:40:49 2010	(r208494)
> @@ -64,6 +64,8 @@ extern int stathz;			/* statistics clock
>  extern int profhz;			/* profiling clock's frequency */
>  extern int profprocs;			/* number of process's profiling */
>  extern int ticks;
> +extern int timer1hz;			/* timer 1 frequency */
> +extern int timer2hz;			/* timer 2 frequency */
>  
>  #endif /* _KERNEL */
>  
> 
> Modified: head/sys/sys/systm.h
> ==============================================================================
> --- head/sys/sys/systm.h	Mon May 24 11:14:40 2010	(r208493)
> +++ head/sys/sys/systm.h	Mon May 24 11:40:49 2010	(r208494)
> @@ -240,6 +240,8 @@ void	hardclock_cpu(int usermode);
>  void	softclock(void *);
>  void	statclock(int usermode);
>  void	profclock(int usermode, uintfptr_t pc);
> +void	timer1clock(int usermode, uintfptr_t pc);
> +void	timer2clock(int usermode, uintfptr_t pc);
>  
>  void	startprofclock(struct proc *);
>  void	stopprofclock(struct proc *);
> 
> Modified: head/sys/x86/isa/clock.c
> ==============================================================================
> --- head/sys/x86/isa/clock.c	Mon May 24 11:14:40 2010	(r208493)
> +++ head/sys/x86/isa/clock.c	Mon May 24 11:40:49 2010	(r208494)
> @@ -87,8 +87,6 @@ __FBSDID("$FreeBSD$");
>  #define	TIMER_DIV(x) ((i8254_freq + (x) / 2) / (x))
>  
>  int	clkintr_pending;
> -static int pscnt = 1;
> -static int psdiv = 1;
>  #ifndef TIMER_FREQ
>  #define TIMER_FREQ   1193182
>  #endif
> @@ -134,10 +132,7 @@ int
>  hardclockintr(struct trapframe *frame)
>  {
>  
> -	if (PCPU_GET(cpuid) == 0)
> -		hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
> -	else
> -		hardclock_cpu(TRAPF_USERMODE(frame));
> +	timer1clock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
>  	return (FILTER_HANDLED);
>  }
>  
> @@ -145,19 +140,7 @@ int
>  statclockintr(struct trapframe *frame)
>  {
>  
> -	profclockintr(frame);
> -	statclock(TRAPF_USERMODE(frame));
> -	return (FILTER_HANDLED);
> -}
> -
> -int
> -profclockintr(struct trapframe *frame)
> -{
> -
> -	if (!using_atrtc_timer)
> -		hardclockintr(frame);
> -	if (profprocs != 0)
> -		profclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
> +	timer2clock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
>  	return (FILTER_HANDLED);
>  }
>  
> @@ -190,28 +173,11 @@ clkintr(struct trapframe *frame)
>  		(*cyclic_clock_func[cpu])(frame);
>  #endif
>  
> -	if (using_atrtc_timer) {
> -#ifdef SMP
> -		if (smp_started)
> -			ipi_all_but_self(IPI_HARDCLOCK);
> -#endif
> -		hardclockintr(frame);
> -	} else {
> -		if (--pscnt <= 0) {
> -			pscnt = psratio;
>  #ifdef SMP
> -			if (smp_started)
> -				ipi_all_but_self(IPI_STATCLOCK);
> +	if (smp_started)
> +		ipi_all_but_self(IPI_HARDCLOCK);
>  #endif
> -			statclockintr(frame);
> -		} else {
> -#ifdef SMP
> -			if (smp_started)
> -				ipi_all_but_self(IPI_PROFCLOCK);
> -#endif
> -			profclockintr(frame);
> -		}
> -	}
> +	hardclockintr(frame);
>  
>  #ifdef DEV_MCA
>  	/* Reset clock interrupt by asserting bit 7 of port 0x61 */
> @@ -295,20 +261,11 @@ rtcintr(struct trapframe *frame)
>  
>  	while (rtcin(RTC_INTR) & RTCIR_PERIOD) {
>  		flag = 1;
> -		if (--pscnt <= 0) {
> -			pscnt = psdiv;
>  #ifdef SMP
> -			if (smp_started)
> -				ipi_all_but_self(IPI_STATCLOCK);
> -#endif
> -			statclockintr(frame);
> -		} else {
> -#ifdef SMP
> -			if (smp_started)
> -				ipi_all_but_self(IPI_PROFCLOCK);
> +		if (smp_started)
> +			ipi_all_but_self(IPI_STATCLOCK);
>  #endif
> -			profclockintr(frame);
> -		}
> +		statclockintr(frame);
>  	}
>  	return(flag ? FILTER_HANDLED : FILTER_STRAY);
>  }
> @@ -555,6 +512,7 @@ cpu_initclocks()
>  	 * timecounter to user a simpler algorithm.
>  	 */
>  	if (using_lapic_timer == LAPIC_CLOCK_NONE) {
> +		timer1hz = hz;
>  		intr_add_handler("clk", 0, (driver_filter_t *)clkintr, NULL,
>  		    NULL, INTR_TYPE_CLK, NULL);
>  		i8254_intsrc = intr_lookup_source(0);
> @@ -577,6 +535,7 @@ cpu_initclocks()
>  	if (using_lapic_timer != LAPIC_CLOCK_ALL) {
>  		using_atrtc_timer = tasc; 
>  		if (using_atrtc_timer) {
> +			timer2hz = RTC_NOPROFRATE;
>  			/* Enable periodic interrupts from the RTC. */
>  			intr_add_handler("rtc", 8,
>  			    (driver_filter_t *)rtcintr, NULL, NULL,
> @@ -588,6 +547,7 @@ cpu_initclocks()
>  				stathz = hz;
>  			else
>  				stathz = hz / (hz / 128);
> +			timer2hz = 0;
>  		}
>  	}
>  
> @@ -601,7 +561,7 @@ cpu_startprofclock(void)
>  	if (using_lapic_timer == LAPIC_CLOCK_ALL || !using_atrtc_timer)
>  		return;
>  	atrtc_rate(RTCSA_PROF);
> -	psdiv = pscnt = psratio;
> +	timer2hz = RTC_PROFRATE;
>  }
>  
>  void
> @@ -611,7 +571,7 @@ cpu_stopprofclock(void)
>  	if (using_lapic_timer == LAPIC_CLOCK_ALL || !using_atrtc_timer)
>  		return;
>  	atrtc_rate(RTCSA_NOPROF);
> -	psdiv = pscnt = 1;
> +	timer2hz = RTC_NOPROFRATE;
>  }
>  
>  static int
> 
> Modified: head/sys/x86/x86/local_apic.c
> ==============================================================================
> --- head/sys/x86/x86/local_apic.c	Mon May 24 11:14:40 2010	(r208493)
> +++ head/sys/x86/x86/local_apic.c	Mon May 24 11:40:49 2010	(r208494)
> @@ -118,9 +118,6 @@ struct lapic {
>  	u_int la_cluster_id:2;
>  	u_int la_present:1;
>  	u_long *la_timer_count;
> -	u_long la_hard_ticks;
> -	u_long la_stat_ticks;
> -	u_long la_prof_ticks;
>  	/* Include IDT_SYSCALL to make indexing easier. */
>  	int la_ioint_irqs[APIC_NUM_IOINTS + 1];
>  } static lapics[MAX_APIC_ID + 1];
> @@ -493,12 +490,14 @@ lapic_setup_clock(enum lapic_clock srcsd
>  	} else
>  		lapic_timer_hz = hz;
>  	lapic_timer_period = value / lapic_timer_hz;
> +	timer1hz = lapic_timer_hz;
>  	if (srcsdes == LAPIC_CLOCK_ALL) {
>  		if (lapic_timer_hz < 128)
>  			stathz = lapic_timer_hz;
>  		else
>  			stathz = lapic_timer_hz / (lapic_timer_hz / 128);
>  		profhz = lapic_timer_hz;
> +		timer2hz = 0;
>  	}
>  
>  	/*
> @@ -790,33 +789,7 @@ lapic_handle_timer(struct trapframe *fra
>  		(*cyclic_clock_func[cpu])(frame);
>  #endif
>  
> -	/* Fire hardclock at hz. */
> -	la->la_hard_ticks += hz;
> -	if (la->la_hard_ticks >= lapic_timer_hz) {
> -		la->la_hard_ticks -= lapic_timer_hz;
> -		if (PCPU_GET(cpuid) == 0)
> -			hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
> -		else
> -			hardclock_cpu(TRAPF_USERMODE(frame));
> -	}
> -	if (clockcoverage == LAPIC_CLOCK_ALL) {
> -
> -		/* Fire statclock at stathz. */
> -		la->la_stat_ticks += stathz;
> -		if (la->la_stat_ticks >= lapic_timer_hz) {
> -			la->la_stat_ticks -= lapic_timer_hz;
> -			statclock(TRAPF_USERMODE(frame));
> -		}
> -
> -		/* Fire profclock at profhz, but only when needed. */
> -		la->la_prof_ticks += profhz;
> -		if (la->la_prof_ticks >= lapic_timer_hz) {
> -			la->la_prof_ticks -= lapic_timer_hz;
> -			if (profprocs != 0)
> -				profclock(TRAPF_USERMODE(frame),
> -				    TRAPF_PC(frame));
> -		}
> -	}
> +	timer1clock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
>  	critical_exit();
>  }
>  


-- 
Andriy Gapon


More information about the svn-src-all mailing list