kernel/arch/arm/arch_clock.c

/* ARM-specific clock functions. */

#include "kernel/kernel.h"

#include "kernel/clock.h"
#include "kernel/proc.h"
#include "kernel/interrupt.h"
#include <minix/u64.h>
#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;
}
