static inline void vperfctr_resume_with_overflow_check(struct vperfctr *perfctr) { #ifdef CONFIG_PERFCTR_INTERRUPT_SUPPORT if (perfctr_cpu_has_pending_interrupt(&perfctr->cpu_state)) { vperfctr_handle_overflow(current, perfctr); return; } #endif vperfctr_resume(perfctr); }
/* PREEMPT note: called in IRQ context with preemption disabled. */ static void vperfctr_ihandler(unsigned long pc) { struct task_struct *tsk = current; struct vperfctr *perfctr; perfctr = tsk->arch.thread.perfctr; if (!perfctr) { printk(KERN_ERR "%s: BUG! pid %d has no vperfctr\n", __FUNCTION__, tsk->id); return; } if (!perfctr_cstatus_has_ictrs(perfctr->cpu_state.user.cstatus)) { printk(KERN_ERR "%s: BUG! vperfctr has cstatus %#x (pid %d, comm %s)\n", __FUNCTION__, perfctr->cpu_state.user.cstatus, tsk->id, tsk->comm); return; } vperfctr_suspend(perfctr); vperfctr_handle_overflow(tsk, perfctr); }
// PREEMPT note: called in IRQ context with preemption disabled. static void vperfctr_ihandler(unsigned long pc) { struct task_struct *tsk = current; struct vperfctr *perfctr; unsigned int pmc, cstatus, now = 0; int i; perfctr = tsk->thread.perfctr; if (!perfctr) { return; } if (!perfctr_cstatus_has_ictrs(perfctr->cpu_state.cstatus)) { return; } // if someone has really overflown then continue else return // just read, don't freeze them cstatus = perfctr->cpu_state.cstatus; for (i = perfctr_cstatus_nractrs(cstatus); (i < perfctr_cstatus_nrctrs(cstatus)) && ((int)now >= 0); ++i) { pmc = perfctr->cpu_state.pmc[i].map; now = read_pmc(pmc); } if ((int)now >= 0) { return; } // Fine, we are suspending the counters and reading them. vperfctr_suspend() // in turn invokes _suspend() on i-mode ctrs (where they are frozen and read) // and a-mode counters (where they are just read) vperfctr_suspend(perfctr); // Ok, Signal to the userland is sent in the following routine. But before that // the following routine calls vperfctr_resume() if the TSC counting is on. // what happens in that resume is just the TSC value is read and stored in the // 'start' state of the TSC vperfctr_handle_overflow(tsk, perfctr); }