Eric Saxe wrote:
>> [snip]
>> The problem is somewhat obvious. There's no guarantee that the next 
>> thread is the actual offender. It's very likely, but not guaranteed :(
>>
>> Any thoughts?
>>   
> I think the apprach is probably ok. Like you said, the trick is to 
> figure out what's causing the idle-state transition...and before I think 
> we figured either:
>     1 device interrupt
>     2 "poke" because something became runnable on the local queue
>     3 "poke" because something became runnable on a remote queue that 
> was already busy
>     4 xcall for some other reason
> 
> - You might want to use the "sched::on-cpu" probe to catch the first 
> thread that this CPU is now going to run (what if the next thread is a 
> kernel service thread)? If that's the next probe to fire, it's probably 
> scenario 2.
> - If the sched::dequeue probe fires before sched::on-cpu, it's probably 
> scenario 3.
> - If an interrupt probe fires before the idle-state transition probe 
> (which will happen since the CPU will awake to the interrupt handler), 
> then it's probbaly scenario 1.
> 
> Then I would be curious how much is left...which I assume would fall 
> into the scenario 4 bucket. :)

I think I may have found a better alternative. Instead of chasing the 
threads around, we could check the cpu_t->cpu_disp_flags field for the 
processor state and only report the events that happen when a cpu is idle.

Here's the default event.c script with those changes. The values are 
close to the number of calls to i86_mwait, so it seems to be working.

What do you think ?

thanks
Rafael



do_interrupt:entry
/`cpu[cpu]->cpu_disp_flags == 0x02/
{
        self->interrupt = 1;
}

interrupt-complete
/arg0 != NULL && arg3 != 0 && self->interrupt/
{
        this->devi = (struct dev_info *)arg0;
        @interrupts[stringof(`devnamesp[this->devi->devi_major].dn_name),
            this->devi->devi_instance] = count();
        self->interrupt = 0;
}

sdt:::callout-start
/`cpu[cpu]->cpu_disp_flags == 0x02/
{
        self->callout = 1;
}

sdt:::callout-start
/(caddr_t)((callout_t *)arg0)->c_func == (caddr_t)&`setrun && self->callout/
{
        this->thr = (kthread_t *)(((callout_t *)arg0)->c_arg);
        @events_u[stringof(this->thr->t_procp->p_user.u_comm)] = count();
        self->callout = 0;
}

sdt:::callout-start
/(caddr_t)((callout_t *)arg0)->c_func != (caddr_t)&`setrun && self->callout/
{
        @events_k[(caddr_t)((callout_t *)arg0)->c_func] = count();
        self->callout = 0;
}

cyclic_expire:entry
/((cpu_t *)((cyc_cpu_t *)arg0)->cyp_cpu)->cpu_disp_flags == 0x02 &&
  (caddr_t)((cyclic_t *)arg0)->cy_handler == (caddr_t)&`clock/
{
        @events_k[(caddr_t)((cyclic_t *)arg0)->cy_handler] = count();
}

send_dirint:entry
/`cpu[arg0]->cpu_disp_flags == 0x02/
{
        @events_x[execname] = count();
}

cpu_wakeup_mwait:entry
/((cpu_t *)arg0)->cpu_disp_flags == 0x02/
{
        @a[execname] = count();
}

Reply via email to