Time accounting based on TSC

- as thre are still KERNEL and IDLE entries, time accounting for
  kernel and idle time works the same as for any other process

- everytime we stop accounting for the currently running process,
  kernel or idle, we read the TSC counter and increment the p_cycles
  entry.

- the process cycles inherently include some of the kernel cycles as
  we can stop accounting for the process only after we save its
  context and we start accounting just before we restore its context

- this assumes that the system does not scale the CPU frequency which
  will be true for ... long time ;-)
This commit is contained in:
Tomas Hruby
2010-02-10 15:36:54 +00:00
parent f08f2bd88c
commit 1b56fdb33c
14 changed files with 94 additions and 52 deletions

View File

@@ -36,12 +36,16 @@
TEST_INT_IN_KERNEL(4, 0f) ;\
\
SAVE_PROCESS_CTX(0) ;\
push %ebp ;\
call cycles_accounting_stop ;\
add $4, %esp ;\
movl $0, %ebp /* for stack trace */ ;\
APIC_IRQ_HANDLER(irq) ;\
jmp restart ;\
\
0: \
pusha ;\
call cycles_accounting_stop_idle ;\
APIC_IRQ_HANDLER(irq) ;\
popa ;\
iret ;
@@ -142,12 +146,16 @@ apic_hwint15:
TEST_INT_IN_KERNEL(4, 0f) ;\
\
SAVE_PROCESS_CTX(0) ;\
push %ebp ;\
call cycles_accounting_stop ;\
add $4, %esp ;\
movl $0, %ebp /* for stack trace */ ;\
LAPIC_INTR_HANDLER(func) ;\
jmp restart ;\
\
0: \
pusha ;\
call cycles_accounting_stop_idle ;\
LAPIC_INTR_HANDLER(func) ;\
popa ;\
iret ;

View File

@@ -7,6 +7,9 @@
#include "../../kernel.h"
#include "../../clock.h"
#include "../../proc.h"
#include <minix/u64.h>
#ifdef CONFIG_APIC
#include "apic.h"
@@ -22,6 +25,9 @@
#define TIMER_FREQ 1193182 /* clock frequency for timer in PC and AT */
#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 */
/*===========================================================================*
@@ -119,3 +125,22 @@ PUBLIC int arch_register_local_timer_handler(irq_handler_t handler)
return 0;
}
PUBLIC void cycles_accounting_init(void)
{
read_tsc_64(&tsc_ctr_switch);
}
PUBLIC void cycles_accounting_stop(struct proc * p)
{
u64_t tsc;
read_tsc_64(&tsc);
p->p_cycles = add64(p->p_cycles, sub64(tsc, tsc_ctr_switch));
tsc_ctr_switch = tsc;
}
PUBLIC void cycles_accounting_stop_idle(void)
{
cycles_accounting_stop(proc_addr(IDLE));
}

View File

@@ -253,6 +253,9 @@ csinit:
TEST_INT_IN_KERNEL(4, 0f) ;\
\
SAVE_PROCESS_CTX(0) ;\
push %ebp ;\
call cycles_accounting_stop ;\
add $4, %esp ;\
movl $0, %ebp /* for stack trace */ ;\
PIC_IRQ_HANDLER(irq) ;\
movb $END_OF_INT, %al ;\
@@ -261,6 +264,7 @@ csinit:
\
0: \
pusha ;\
call cycles_accounting_stop_idle ;\
PIC_IRQ_HANDLER(irq) ;\
movb $END_OF_INT, %al ;\
outb $INT_CTL /* reenable interrupts in master pic */ ;\
@@ -316,6 +320,9 @@ hwint07:
TEST_INT_IN_KERNEL(4, 0f) ;\
\
SAVE_PROCESS_CTX(0) ;\
push %ebp ;\
call cycles_accounting_stop ;\
add $4, %esp ;\
movl $0, %ebp /* for stack trace */ ;\
PIC_IRQ_HANDLER(irq) ;\
movb $END_OF_INT, %al ;\
@@ -325,6 +332,7 @@ hwint07:
\
0: \
pusha ;\
call cycles_accounting_stop_idle ;\
PIC_IRQ_HANDLER(irq) ;\
movb $END_OF_INT, %al ;\
outb $INT_CTL /* reenable interrupts in master pic */ ;\
@@ -395,6 +403,11 @@ ipc_entry:
push %eax
push %ecx
/* stop user process cycles */
push %ebp
call cycles_accounting_stop
add $4, %esp
/* for stack trace */
movl $0, %ebp
@@ -420,9 +433,6 @@ kernel_call_entry:
/* save the pointer to the current process */
push %ebp
/* for stack trace */
movl $0, %ebp
/*
* pass the syscall arguments from userspace to the handler.
* SAVE_PROCESS_CTX() does not clobber these registers, they are still
@@ -430,6 +440,14 @@ kernel_call_entry:
*/
push %eax
/* stop user process cycles */
push %ebp
call cycles_accounting_stop
add $4, %esp
/* for stack trace */
movl $0, %ebp
call kernel_call
/* restore the current process pointer and save the return value */
@@ -458,6 +476,11 @@ exception_entry_from_user:
SAVE_PROCESS_CTX(8)
/* stop user process cycles */
push %ebp
call cycles_accounting_stop
add $4, %esp
/* for stack trace clear %ebp */
movl $0, %ebp
@@ -604,6 +627,10 @@ copr_not_available:
jnz 0f /* jump if FPU is already initialized */
orw $MF_FPU_INITIALIZED, (%ebx)
fninit
/* stop user process cycles */
push %ebp
call cycles_accounting_stop
add $4, %esp
jmp copr_return
0: /* load FPU context for current process */
mov %ss:FP_SAVE_AREA_P(%ebp), %eax

View File

@@ -325,10 +325,10 @@ PRIVATE void printslot(struct proc *pp, int level)
COL
kprintf("%d: %s %d prio %d/%d time %d/%d cr3 0x%lx rts %s misc %s",
kprintf("%d: %s %d prio %d/%d time %d/%d cycles 0x%x%08x cr3 0x%lx rts %s misc %s",
proc_nr(pp), pp->p_name, pp->p_endpoint,
pp->p_priority, pp->p_max_priority, pp->p_user_time,
pp->p_sys_time, pp->p_seg.p_cr3,
pp->p_sys_time, pp->p_cycles.hi, pp->p_cycles.lo, pp->p_seg.p_cr3,
rtsflagstr(pp->p_rts_flags), miscflagstr(pp->p_misc_flags));
if(pp->p_rts_flags & RTS_SENDING) {