diff --git a/kernel/arch/i386/arch_clock.c b/kernel/arch/i386/arch_clock.c index 59d06652a..b9439cec6 100644 --- a/kernel/arch/i386/arch_clock.c +++ b/kernel/arch/i386/arch_clock.c @@ -11,6 +11,7 @@ #include "kernel/interrupt.h" #include #include "glo.h" +#include "profile.h" #ifdef CONFIG_APIC @@ -272,6 +273,9 @@ PUBLIC void context_stop_idle(void) if (is_idle) restart_local_timer(); + + if (sprofiling) + get_cpulocal_var(idle_interrupted) = 1; } PUBLIC u64_t ms_2_cpu_time(unsigned ms) diff --git a/kernel/arch/i386/klib.S b/kernel/arch/i386/klib.S index 515ea5ea1..6915501e1 100644 --- a/kernel/arch/i386/klib.S +++ b/kernel/arch/i386/klib.S @@ -1030,6 +1030,14 @@ ENTRY(read_ebp) mov %ebp, %eax ret +ENTRY(interrupts_enable) + sti + ret + +ENTRY(interrupts_disable) + cli + ret + /* * void switch_k_stack(void * esp, void (* continuation)(void)); diff --git a/kernel/cpulocals.h b/kernel/cpulocals.h index 0d3c0ade4..b12978a65 100644 --- a/kernel/cpulocals.h +++ b/kernel/cpulocals.h @@ -76,6 +76,9 @@ DECLARE_CPULOCAL(struct proc *, run_q_head[NR_SCHED_QUEUES]); /* ptrs to ready l DECLARE_CPULOCAL(struct proc *, run_q_tail[NR_SCHED_QUEUES]); /* ptrs to ready list tails */ DECLARE_CPULOCAL(int, cpu_is_idle); /* let the others know that you are idle */ +DECLARE_CPULOCAL(volatile int, idle_interrupted); /* to interrupt busy-idle + while profiling */ + DECLARE_CPULOCAL(u64_t ,tsc_ctr_switch); /* when did we switched time accounting */ /* last values read from cpu when sending ooq msg to scheduler */ diff --git a/kernel/proc.c b/kernel/proc.c index 3f541b479..3e416ae4d 100644 --- a/kernel/proc.c +++ b/kernel/proc.c @@ -43,6 +43,7 @@ #include "vm.h" #include "clock.h" #include "spinlock.h" +#include "profile.h" #include "arch_proto.h" @@ -214,7 +215,18 @@ PRIVATE void idle(void) /* start accounting for the idle time */ context_stop(proc_addr(KERNEL)); - halt_cpu(); + if (!sprofiling) + halt_cpu(); + else { + volatile int * v; + + v = get_cpulocal_var_ptr(idle_interrupted); + interrupts_enable(); + while (!*v) + arch_pause(); + interrupts_disable(); + *v = 0; + } /* * end of accounting for the idle task does not happen here, the kernel * is handling stuff for quite a while before it gets back here! diff --git a/kernel/proto.h b/kernel/proto.h index ba99268a1..b040c8a52 100644 --- a/kernel/proto.h +++ b/kernel/proto.h @@ -103,6 +103,9 @@ _PROTOTYPE( void rm_irq_handler, (const irq_hook_t *hook) ); _PROTOTYPE( void enable_irq, (const irq_hook_t *hook) ); _PROTOTYPE( int disable_irq, (const irq_hook_t *hook) ); +_PROTOTYPE(void interrupts_enable, (void)); +_PROTOTYPE(void interrupts_disable, (void)); + /* debug.c */ _PROTOTYPE( int runqueues_ok, (void) ); #ifndef CONFIG_SMP