static inline void vperfctr_handle_overflow(struct task_struct *tsk, struct vperfctr *perfctr) { unsigned int pmc_mask; siginfo_t si; sigset_t old_blocked; pmc_mask = perfctr_cpu_identify_overflow(&perfctr->cpu_state); if (!pmc_mask) { printk(KERN_ERR "%s: BUG! pid %d has unidentifiable overflow source\n", __FUNCTION__, tsk->pid); return; } /* suspend a-mode and i-mode PMCs, leaving only TSC on */ /* XXX: some people also want to suspend the TSC */ // we are storing 'cpu_state.cstatus' in 'iresume_cstatus' because // in vperfctr_resume, we only want to read the status of those // In the following TSC is resumed and continues to collect the // stats // if 'perfctr->iresume_cstatus' is not updated below, vperfctr_iresume() fails // as it thinks it was spuriously called inspite of absence of i-mode counters. // vperfctr_iresume() -> ... -> do_vperfctr_iresume() is a different thread of // execution from vperfctr_resume() -> ... -> vperfctr_iresume() -> __write_control() -> // ... perfctr->iresume_cstatus = perfctr->cpu_state.cstatus; if (perfctr_cstatus_has_tsc(perfctr->iresume_cstatus)) { perfctr->cpu_state.cstatus = perfctr_mk_cstatus(1, 0, 0); vperfctr_resume(perfctr); } else { perfctr->cpu_state.cstatus = 0; } // the following siginfo_t structure helps the kernel in invoking // the correct signal handler. Is that right ? // what's the deal with si_errno? what does it say ? si_code ? si.si_signo = perfctr->si_signo; si.si_errno = 0; si.si_code = SI_PMC_OVF; si.si_pmc_ovf_mask = pmc_mask; /* deliver signal without waking up the receiver */ spin_lock_irq(&tsk->sighand->siglock); old_blocked = tsk->blocked; sigaddset(&tsk->blocked, si.si_signo); spin_unlock_irq(&tsk->sighand->siglock); if (!send_sig_info(si.si_signo, &si, tsk)) { send_sig(si.si_signo, tsk, 1); } spin_lock_irq(&tsk->sighand->siglock); tsk->blocked = old_blocked; recalc_sigpending(); spin_unlock_irq(&tsk->sighand->siglock); }
static void vperfctr_handle_overflow(struct task_struct *tsk, struct vperfctr *perfctr) { unsigned int pmc_mask; siginfo_t si; sigset_t old_blocked; pmc_mask = perfctr_cpu_identify_overflow(&perfctr->cpu_state); if (!pmc_mask) { #ifdef CONFIG_PPC64 /* On some hardware (ppc64, in particular) it's * impossible to control interrupts finely enough to * eliminate overflows on counters we don't care * about. So in this case just restart the counters * and keep going. */ vperfctr_resume(perfctr); #else printk(KERN_ERR "%s: BUG! pid %d has unidentifiable overflow source\n", __FUNCTION__, tsk->id); #endif return; } perfctr->ireload_needed = 1; /* suspend a-mode and i-mode PMCs, leaving only TSC on */ /* XXX: some people also want to suspend the TSC */ perfctr->resume_cstatus = perfctr->cpu_state.user.cstatus; if (perfctr_cstatus_has_tsc(perfctr->resume_cstatus)) { perfctr->cpu_state.user.cstatus = perfctr_mk_cstatus(1, 0, 0); vperfctr_resume(perfctr); } else perfctr->cpu_state.user.cstatus = 0; si.si_signo = perfctr->si_signo; si.si_errno = 0; si.si_code = SI_PMC_OVF; si.si_pmc_ovf_mask = pmc_mask; /* deliver signal without waking up the receiver */ spin_lock_irq(&tsk->sighand->siglock); old_blocked = tsk->blocked; sigaddset(&tsk->blocked, si.si_signo); spin_unlock_irq(&tsk->sighand->siglock); if (!send_sig_info(si.si_signo, &si, tsk)) send_sig(si.si_signo, tsk, 1); spin_lock_irq(&tsk->sighand->siglock); tsk->blocked = old_blocked; recalc_sigpending(); spin_unlock_irq(&tsk->sighand->siglock); }
static void vperfctr_handle_overflow(struct task_struct *tsk, struct vperfctr *perfctr) { unsigned int pmc_mask; siginfo_t si; sigset_t old_blocked; pmc_mask = perfctr_cpu_identify_overflow(&perfctr->cpu_state); if (!pmc_mask) { printk(KERN_ERR "%s: BUG! pid %d has unidentifiable overflow source\n", __FUNCTION__, tsk->pid); return; } /* suspend a-mode and i-mode PMCs, leaving only TSC on */ /* XXX: some people also want to suspend the TSC */ perfctr->iresume_cstatus = perfctr->cpu_state.cstatus; if (perfctr_cstatus_has_tsc(perfctr->iresume_cstatus)) { perfctr->cpu_state.cstatus = perfctr_mk_cstatus(1, 0, 0); vperfctr_resume(perfctr); } else perfctr->cpu_state.cstatus = 0; si.si_signo = perfctr->si_signo; si.si_errno = 0; si.si_code = SI_PMC_OVF; si.si_pmc_ovf_mask = pmc_mask; /* deliver signal without waking up the receiver */ spin_lock_irq(&task_siglock(tsk)); old_blocked = tsk->blocked; sigaddset(&tsk->blocked, si.si_signo); spin_unlock_irq(&task_siglock(tsk)); if (!send_sig_info(si.si_signo, &si, tsk)) send_sig(si.si_signo, tsk, 1); spin_lock_irq(&task_siglock(tsk)); tsk->blocked = old_blocked; recalc_sigpending(); spin_unlock_irq(&task_siglock(tsk)); }