]> git.hungrycats.org Git - linux/commitdiff
[IA64] perfmon.c: cleanup system-wide context when closed from another cpu
authorStéphane Eranian <eranian@hpl.hp.com>
Mon, 30 Aug 2004 22:20:37 +0000 (22:20 +0000)
committerTony Luck <tony.luck@intel.com>
Mon, 30 Aug 2004 22:20:37 +0000 (22:20 +0000)
- fix pfm_stop() and pfm_flush_pmds() to correctly cleanup
  in case of a system-wide context which is closed while running
  from another processor. This was leading to an assertion failure
  in pfm_loads_regs() for the next user of the PMU on the monitored
  CPU.

signed-off-by: stephane eranian <eranian@hpl.hp.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
arch/ia64/kernel/perfmon.c

index 3a6ebc7368b77d89d2919eafd534ac7d4d96248d..d5c057e9abbffb41ed6ad9b463f79f60d1e5c275 100644 (file)
@@ -3985,7 +3985,10 @@ pfm_stop(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
        state     = ctx->ctx_state;
        is_system = ctx->ctx_fl_system;
 
-       if (state != PFM_CTX_LOADED && state != PFM_CTX_MASKED) return -EINVAL;
+       /*
+        * context must be attached to issue the stop command (includes LOADED,MASKED,ZOMBIE)
+        */
+       if (state == PFM_CTX_UNLOADED) return -EINVAL;
 
        /*
         * In system wide and when the context is loaded, access can only happen
@@ -6312,15 +6315,15 @@ pfm_flush_pmds(struct task_struct *task, pfm_context_t *ctx)
         */
        is_self = ctx->ctx_task == task ? 1 : 0;
 
-#ifdef CONFIG_SMP
-       if (task == current) {
-#else
        /*
-        * in UP, the state can still be in the registers
+        * can access PMU is task is the owner of the PMU state on the current CPU
+        * or if we are running on the CPU bound to the context in system-wide mode
+        * (that is not necessarily the task the context is attached to in this mode).
+        * In system-wide we always have can_access_pmu true because a task running on an
+        * invalid processor is flagged earlier in the call stack (see pfm_stop).
         */
-       if (task == current || GET_PMU_OWNER() == task) {
-#endif
-               can_access_pmu = 1;
+       can_access_pmu = (GET_PMU_OWNER() == task) || (ctx->ctx_fl_system && ctx->ctx_cpu == smp_processor_id());
+       if (can_access_pmu) {
                /*
                 * Mark the PMU as not owned
                 * This will cause the interrupt handler to do nothing in case an overflow
@@ -6330,6 +6333,7 @@ pfm_flush_pmds(struct task_struct *task, pfm_context_t *ctx)
                 * on.
                 */
                SET_PMU_OWNER(NULL, NULL);
+               DPRINT(("releasing ownership\n"));
 
                /*
                 * read current overflow status: