/* ARM-specific clock functions. */ #include "kernel/kernel.h" #include "kernel/clock.h" #include "kernel/proc.h" #include "kernel/interrupt.h" #include #include "glo.h" #include "profile.h" #include "spinlock.h" #ifdef CONFIG_SMP #include "kernel/smp.h" #endif #include "omap_timer.h" #include "omap_intr.h" static unsigned tsc_per_ms[CONFIG_MAX_CPUS]; int init_local_timer(unsigned freq) { omap3_timer_init(freq); /* always only 1 cpu in the system */ tsc_per_ms[0] = 1; return 0; } void stop_local_timer(void) { omap3_timer_stop(); } void arch_timer_int_handler(void) { omap3_timer_int_handler(); } void cycles_accounting_init(void) { read_tsc_64(get_cpu_var_ptr(cpu, tsc_ctr_switch)); make_zero64(get_cpu_var(cpu, cpu_last_tsc)); make_zero64(get_cpu_var(cpu, cpu_last_idle)); } void context_stop(struct proc * p) { u64_t tsc, 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); if(kbill_ipc) { kbill_ipc->p_kipc_cycles = add64(kbill_ipc->p_kipc_cycles, tsc_delta); kbill_ipc = NULL; } if(kbill_kcall) { kbill_kcall->p_kcall_cycles = add64(kbill_kcall->p_kcall_cycles, tsc_delta); kbill_kcall = NULL; } /* * deduct the just consumed cpu cycles from the cpu time left for this * process during its current quantum. Skip IDLE and other pseudo kernel * tasks */ if (p->p_endpoint >= 0) { #if DEBUG_RACE make_zero64(p->p_cpu_time_left); #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); } #endif } *__tsc_ctr_switch = tsc; } void context_stop_idle(void) { int is_idle; #ifdef CONFIG_SMP unsigned cpu = cpuid; #endif is_idle = get_cpu_var(cpu, cpu_is_idle); get_cpu_var(cpu, cpu_is_idle) = 0; context_stop(get_cpulocal_var_ptr(idle_proc)); if (is_idle) restart_local_timer(); #if SPROFILE if (sprofiling) get_cpulocal_var(idle_interrupted) = 1; #endif } void restart_local_timer(void) { } int register_local_timer_handler(const irq_handler_t handler) { return omap3_register_timer_handler(handler); } u64_t ms_2_cpu_time(unsigned ms) { return mul64u(tsc_per_ms[cpuid], ms); } unsigned cpu_time_2_ms(u64_t cpu_time) { return div64u(cpu_time, tsc_per_ms[cpuid]); } short cpu_load(void) { return 0; }