diff --git a/kernel/arch/i386/arch_clock.c b/kernel/arch/i386/arch_clock.c index b07dacf91..34faee56a 100644 --- a/kernel/arch/i386/arch_clock.c +++ b/kernel/arch/i386/arch_clock.c @@ -241,6 +241,18 @@ PUBLIC void context_stop(struct proc * p) 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 diff --git a/kernel/glo.h b/kernel/glo.h index 906fd5ffa..2446ca795 100644 --- a/kernel/glo.h +++ b/kernel/glo.h @@ -29,6 +29,8 @@ EXTERN struct loadinfo kloadinfo; /* status of load average */ EXTERN struct proc *vmrequest; /* first process on vmrequest queue */ EXTERN unsigned lost_ticks; /* clock ticks counted outside clock task */ EXTERN char *ipc_call_names[IPCNO_HIGHEST+1]; /* human-readable call names */ +EXTERN struct proc *kbill_kcall; /* process that made kernel call */ +EXTERN struct proc *kbill_ipc; /* process that invoked ipc */ /* Interrupt related variables. */ EXTERN irq_hook_t irq_hooks[NR_IRQ_HOOKS]; /* hooks for general use */ diff --git a/kernel/proc.c b/kernel/proc.c index ec85c9343..cb972bec1 100644 --- a/kernel/proc.c +++ b/kernel/proc.c @@ -539,6 +539,9 @@ PUBLIC int do_ipc(reg_t r1, reg_t r2, reg_t r3) assert(!RTS_ISSET(caller_ptr, RTS_SLOT_FREE)); + /* bill kernel time to this process. */ + kbill_ipc = caller_ptr; + /* If this process is subject to system call tracing, handle that first. */ if (caller_ptr->p_misc_flags & (MF_SC_TRACE | MF_SC_DEFER)) { /* Are we tracing this process, and is it the first sys_call entry? */ diff --git a/kernel/proc.h b/kernel/proc.h index dfc332698..d8f50d088 100644 --- a/kernel/proc.h +++ b/kernel/proc.h @@ -58,6 +58,8 @@ struct proc { clock_t p_prof_left; /* number of ticks left on profile timer */ u64_t p_cycles; /* how many cycles did the process use */ + u64_t p_kcall_cycles; /* kernel cycles caused by this proc (kcall) */ + u64_t p_kipc_cycles; /* cycles caused by this proc (ipc) */ struct proc *p_nextready; /* pointer to next ready process */ struct proc *p_caller_q; /* head of list of procs wishing to send */ diff --git a/kernel/system.c b/kernel/system.c index eeae82807..029738b7e 100644 --- a/kernel/system.c +++ b/kernel/system.c @@ -156,6 +156,10 @@ PUBLIC void kernel_call(message *m_user, struct proc * caller) result = EBADREQUEST; } + + /* remember who invoked the kcall so we can bill it its time */ + kbill_kcall = caller; + kernel_call_finish(caller, &msg, result); } diff --git a/kernel/system/do_fork.c b/kernel/system/do_fork.c index 631252a6b..eac87ea00 100644 --- a/kernel/system/do_fork.c +++ b/kernel/system/do_fork.c @@ -90,6 +90,8 @@ PUBLIC int do_fork(struct proc * caller, message * m_ptr) make_zero64(rpc->p_cpu_time_left); make_zero64(rpc->p_cycles); + make_zero64(rpc->p_kcall_cycles); + make_zero64(rpc->p_kipc_cycles); /* If the parent is a privileged process, take away the privileges from the * child process and inhibit it from running by setting the NO_PRIV flag.