SMP - CPU local cycles accounting

- tsc_ctr_switch is made cpu local

- although an x86 specific variable it must be declared globaly as the
  cpulocal implementation does not allow otherwise
This commit is contained in:
Tomas Hruby 2010-09-15 14:10:27 +00:00
parent 67f039540c
commit d37b7ebc0b
3 changed files with 16 additions and 9 deletions

View File

@ -27,9 +27,6 @@
#define TIMER_FREQ 1193182 /* clock frequency for timer in PC and AT */ #define TIMER_FREQ 1193182 /* clock frequency for timer in PC and AT */
#define TIMER_COUNT(freq) (TIMER_FREQ/(freq)) /* initial value for counter*/ #define TIMER_COUNT(freq) (TIMER_FREQ/(freq)) /* initial value for counter*/
/* FIXME make it cpu local! */
PRIVATE u64_t tsc_ctr_switch; /* when did we switched time accounting */
PRIVATE irq_hook_t pic_timer_hook; /* interrupt handler hook */ PRIVATE irq_hook_t pic_timer_hook; /* interrupt handler hook */
PRIVATE unsigned probe_ticks; PRIVATE unsigned probe_ticks;
@ -175,17 +172,17 @@ PUBLIC int arch_register_local_timer_handler(const irq_handler_t handler)
PUBLIC void cycles_accounting_init(void) PUBLIC void cycles_accounting_init(void)
{ {
read_tsc_64(&tsc_ctr_switch); read_tsc_64(get_cpulocal_var_ptr(tsc_ctr_switch));
} }
PUBLIC void context_stop(struct proc * p) PUBLIC void context_stop(struct proc * p)
{ {
u64_t tsc, tsc_delta; u64_t tsc, tsc_delta;
u64_t * __tsc_ctr_switch = get_cpulocal_var_ptr(tsc_ctr_switch);
read_tsc_64(&tsc); read_tsc_64(&tsc);
tsc_delta = sub64(tsc, tsc_ctr_switch); tsc_delta = sub64(tsc, *__tsc_ctr_switch);
p->p_cycles = add64(p->p_cycles, tsc_delta); p->p_cycles = add64(p->p_cycles, tsc_delta);
tsc_ctr_switch = tsc;
/* /*
* deduct the just consumed cpu cycles from the cpu time left for this * deduct the just consumed cpu cycles from the cpu time left for this
@ -215,10 +212,17 @@ PUBLIC void context_stop(struct proc * p)
* If we stop accounting for KERNEL we must unlock the BKL. If account * If we stop accounting for KERNEL we must unlock the BKL. If account
* for IDLE we must not hold the lock * for IDLE we must not hold the lock
*/ */
if (p == proc_addr(KERNEL)) if (p == proc_addr(KERNEL)) {
read_tsc_64(&tsc);
p->p_cycles = add64(p->p_cycles, sub64(tsc, *__tsc_ctr_switch));
BKL_UNLOCK(); BKL_UNLOCK();
else } else {
BKL_LOCK(); BKL_LOCK();
read_tsc_64(&tsc);
p->p_cycles = add64(p->p_cycles, sub64(tsc, *__tsc_ctr_switch));
}
*__tsc_ctr_switch = tsc;
} }
PUBLIC void context_stop_idle(void) PUBLIC void context_stop_idle(void)

View File

@ -211,7 +211,7 @@ PRIVATE void ap_finish_booting(void)
if (app_cpu_init_timer(system_hz)) { if (app_cpu_init_timer(system_hz)) {
panic("FATAL : failed to initialize timer interrupts CPU %d, " panic("FATAL : failed to initialize timer interrupts CPU %d, "
"cannot continue without any clock source!", cpuid); "cannot continue without any clock source!", cpu);
} }
printf("CPU %d local APIC timer is ticking\n", cpu); printf("CPU %d local APIC timer is ticking\n", cpu);

View File

@ -30,6 +30,7 @@
#define get_cpulocal_var(name) CPULOCAL_STRUCT.name #define get_cpulocal_var(name) CPULOCAL_STRUCT.name
#define get_cpulocal_var_ptr(name) &(get_cpulocal_var(name)) #define get_cpulocal_var_ptr(name) &(get_cpulocal_var(name))
#define get_cpu_var(cpu, name) get_cpulocal_var(name) #define get_cpu_var(cpu, name) get_cpulocal_var(name)
#define get_cpu_var_ptr(cpu, name) get_cpulocal_var_ptr(name)
#endif #endif
@ -74,6 +75,8 @@ DECLARE_CPULOCAL(struct proc *, ptproc);
DECLARE_CPULOCAL(struct proc *, run_q_head[NR_SCHED_QUEUES]); /* ptrs to ready list headers */ DECLARE_CPULOCAL(struct proc *, run_q_head[NR_SCHED_QUEUES]); /* ptrs to ready list headers */
DECLARE_CPULOCAL(struct proc *, run_q_tail[NR_SCHED_QUEUES]); /* ptrs to ready list tails */ DECLARE_CPULOCAL(struct proc *, run_q_tail[NR_SCHED_QUEUES]); /* ptrs to ready list tails */
DECLARE_CPULOCAL(u64_t ,tsc_ctr_switch); /* when did we switched time accounting */
DECLARE_CPULOCAL_END DECLARE_CPULOCAL_END
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */