static int sys_vperfctr_iresume(struct vperfctr *perfctr, const struct task_struct *tsk) { #ifdef CONFIG_PERFCTR_INTERRUPT_SUPPORT unsigned int iresume_cstatus; if (!tsk) return -ESRCH; /* attempt to update unlinked perfctr */ iresume_cstatus = perfctr->iresume_cstatus; if (!perfctr_cstatus_has_ictrs(iresume_cstatus)) return -EPERM; /* PREEMPT note: preemption is disabled over the entire region because we're updating an active perfctr. */ preempt_disable(); if (IS_RUNNING(perfctr) && tsk == current) vperfctr_suspend(perfctr); perfctr->cpu_state.cstatus = iresume_cstatus; perfctr->iresume_cstatus = 0; /* remote access note: perfctr_cpu_ireload() is ok */ perfctr_cpu_ireload(&perfctr->cpu_state); if (tsk == current) vperfctr_resume(perfctr); preempt_enable(); return 0; #else return -ENOSYS; #endif }
static inline void vperfctr_ireload(struct vperfctr *perfctr) { #ifdef CONFIG_PERFCTR_INTERRUPT_SUPPORT if (perfctr->ireload_needed) { perfctr->ireload_needed = 0; /* remote access note: perfctr_cpu_ireload() is ok */ perfctr_cpu_ireload(&perfctr->cpu_state); } #endif }
static int do_vperfctr_iresume(struct vperfctr *perfctr, const struct task_struct *tsk) { #ifdef CONFIG_PERFCTR_INTERRUPT_SUPPORT unsigned int iresume_cstatus; if (!tsk) return -ESRCH; /* attempt to update unlinked perfctr */ iresume_cstatus = perfctr->iresume_cstatus; if (!perfctr_cstatus_has_ictrs(iresume_cstatus)) { return -EPERM; } /* PREEMPT note: preemption is disabled over the entire region because we're updating an active perfctr. */ preempt_disable(); // this is for resuming a task whose signal was handled prior to this call // are the i-mode counters frozen before the overflow-signal is delivered // yes, they are. in the suspend call invoked in the handler // why exactly are we suspending the following? Makes sense ... if the // counters are already running, then one should not just resume the task // which will overwrite the PMC registers with old values. Nice. Under // what condition do counters continue to count after the signal is delivered // remember TSC was not suspend in the handler and continues to count if (IS_RUNNING(perfctr) && tsk == current) vperfctr_suspend(perfctr); // setting the cstatus of 'cpu_state' back to what it was prior to its // zeroing out in the interrupt handler perfctr->cpu_state.cstatus = iresume_cstatus; perfctr->iresume_cstatus = 0; /* remote access note: perfctr_cpu_ireload() is ok */ // the following forces the reload of control registers that // unfreezes the i-mode registers perfctr_cpu_ireload(&perfctr->cpu_state); if (tsk == current) vperfctr_resume(perfctr); preempt_enable(); return 0; #else return -ENOSYS; #endif }