kernel: scheduling fix for ARM

. make read_tsc_64 use the free-running clock, significantly
	  improving scheduling behaviour

Change-Id: Idf6a12f6e26be7fe3b3664c278cae846d8b2a442
This commit is contained in:
Ben Gras 2013-02-03 19:28:24 +01:00
parent af18db5668
commit 8ea66915f2
3 changed files with 37 additions and 23 deletions

View file

@ -52,13 +52,13 @@ void cycles_accounting_init(void)
void context_stop(struct proc * p)
{
u64_t tsc, tsc_delta;
u64_t tsc;
u32_t tsc_delta;
u64_t * __tsc_ctr_switch = get_cpulocal_var_ptr(tsc_ctr_switch);
read_tsc_64(&tsc);
p->p_cycles = add64(p->p_cycles, sub64(tsc, *__tsc_ctr_switch));
tsc_delta = sub64(tsc, *__tsc_ctr_switch);
tsc_delta = tsc - *__tsc_ctr_switch;
p->p_cycles += tsc_delta;
if(kbill_ipc) {
kbill_ipc->p_kipc_cycles =
@ -79,18 +79,11 @@ void context_stop(struct proc * p)
*/
if (p->p_endpoint >= 0) {
#if DEBUG_RACE
make_zero64(p->p_cpu_time_left);
p->p_cpu_time_left = 0;
#else
/* if (tsc_delta < p->p_cpu_time_left) in 64bit */
if (ex64hi(tsc_delta) < ex64hi(p->p_cpu_time_left) ||
(ex64hi(tsc_delta) == ex64hi(p->p_cpu_time_left) &&
ex64lo(tsc_delta) < ex64lo(p->p_cpu_time_left)))
{
p->p_cpu_time_left = sub64(p->p_cpu_time_left, tsc_delta);
}
else {
make_zero64(p->p_cpu_time_left);
}
if (tsc_delta < p->p_cpu_time_left) {
p->p_cpu_time_left -= tsc_delta;
} else p->p_cpu_time_left = 0;
#endif
}

View file

@ -29,6 +29,8 @@ static int freepdes[MAXFREEPDES];
static u32_t phys_get32(phys_bytes v);
extern vir_bytes omap3_gptimer10_base = OMAP3_GPTIMER10_BASE;
void mem_clear_mapcache(void)
{
int i;
@ -763,7 +765,7 @@ int arch_phys_map_reply(const int index, const vir_bytes addr)
return OK;
}
else if (index == frclock_index) {
minix_kerninfo.minix_frclock = addr;
omap3_gptimer10_base = minix_kerninfo.minix_frclock = addr;
return OK;
}

View file

@ -8,7 +8,9 @@
#include "omap_intr.h"
static irq_hook_t omap3_timer_hook; /* interrupt handler hook */
static u64_t tsc;
static u64_t high_frc;
vir_bytes omap3_gptimer10_base;
int omap3_register_timer_handler(const irq_handler_t handler)
{
@ -90,6 +92,23 @@ void omap3_timer_stop()
mmio_clear(OMAP3_GPTIMER1_TCLR, OMAP3_TCLR_ST);
}
static u32_t read_frc(void)
{
u32_t frc = *(u32_t *) ((char *) omap3_gptimer10_base + OMAP3_TCRR);
return frc;
}
static void frc_overflow_check(void)
{
static int prev_frc_valid;
static u32_t prev_frc;
u32_t cur_frc = read_frc();
if(prev_frc_valid && prev_frc > cur_frc)
high_frc++;
prev_frc = cur_frc;
prev_frc_valid = 1;
}
void omap3_timer_int_handler()
{
/* Clear all interrupts */
@ -98,15 +117,15 @@ void omap3_timer_int_handler()
tisr = OMAP3_TISR_MAT_IT_FLAG | OMAP3_TISR_OVF_IT_FLAG |
OMAP3_TISR_TCAR_IT_FLAG;
mmio_write(OMAP3_GPTIMER1_TISR, tisr);
tsc++;
frc_overflow_check();
}
/* Don't use libminlib's read_tsc_64, but our own version instead. We emulate
* the ARM Cycle Counter (CCNT) with 1 cycle per ms. We can't rely on the
* actual counter hardware to be working (i.e., qemu doesn't emulate it at all)
*/
/* Use the free running clock as TSC */
void read_tsc_64(u64_t *t)
{
*t = tsc;
u32_t now;
frc_overflow_check();
now = read_frc();
*t = (u64_t) now + (high_frc << 32);
}