From 8ea66915f29c2b8abb1de57c34b0b857fb4af756 Mon Sep 17 00:00:00 2001 From: Ben Gras Date: Sun, 3 Feb 2013 19:28:24 +0100 Subject: [PATCH] kernel: scheduling fix for ARM . make read_tsc_64 use the free-running clock, significantly improving scheduling behaviour Change-Id: Idf6a12f6e26be7fe3b3664c278cae846d8b2a442 --- kernel/arch/earm/arch_clock.c | 23 ++++++++--------------- kernel/arch/earm/memory.c | 4 +++- kernel/arch/earm/omap_timer.c | 33 ++++++++++++++++++++++++++------- 3 files changed, 37 insertions(+), 23 deletions(-) diff --git a/kernel/arch/earm/arch_clock.c b/kernel/arch/earm/arch_clock.c index 96d8811b2..67fc0ed45 100644 --- a/kernel/arch/earm/arch_clock.c +++ b/kernel/arch/earm/arch_clock.c @@ -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 } diff --git a/kernel/arch/earm/memory.c b/kernel/arch/earm/memory.c index f422d43be..9608868a8 100644 --- a/kernel/arch/earm/memory.c +++ b/kernel/arch/earm/memory.c @@ -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; } diff --git a/kernel/arch/earm/omap_timer.c b/kernel/arch/earm/omap_timer.c index a5bac65a9..cc7dbb402 100644 --- a/kernel/arch/earm/omap_timer.c +++ b/kernel/arch/earm/omap_timer.c @@ -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); } -- 2.44.0