On 15.01.14 10:02:44, Weng Meiling wrote:
> On 2014/1/14 23:05, Robert Richter wrote:
> > @@ -94,6 +98,11 @@ static int op_create_counter(int cpu, int event)
> >  
> >     per_cpu(perf_events, cpu)[event] = pevent;
> >  
> > +   /* sync perf_events with overflow handler: */
> > +   smp_wmb();
> > +
> > +   perf_event_enable(pevent);
> > +
> 
> Should this step go before the if check:pevent->state != 
> PERF_EVENT_STATE_ACTIVE ?
> Because the attr->disabled is true, So after the 
> perf_event_create_kernel_counter
> the pevent->state is not PERF_EVENT_STATE_ACTIVE.

Right, the check is a problem. We need to move it after the event was
enabled. On error, we need to NULL the event, see below.

-Robert

---
 drivers/oprofile/oprofile_perf.c | 27 +++++++++++++++++++--------
 1 file changed, 19 insertions(+), 8 deletions(-)

diff --git a/drivers/oprofile/oprofile_perf.c b/drivers/oprofile/oprofile_perf.c
index d5b2732..9dfb236 100644
--- a/drivers/oprofile/oprofile_perf.c
+++ b/drivers/oprofile/oprofile_perf.c
@@ -38,6 +38,9 @@ static void op_overflow_handler(struct perf_event *event,
        int id;
        u32 cpu = smp_processor_id();
 
+       /* sync perf_events with op_create_counter(): */
+       smp_rmb();
+
        for (id = 0; id < num_counters; ++id)
                if (per_cpu(perf_events, cpu)[id] == event)
                        break;
@@ -68,6 +71,7 @@ static void op_perf_setup(void)
                attr->config            = counter_config[i].event;
                attr->sample_period     = counter_config[i].count;
                attr->pinned            = 1;
+               attr->disabled          = 1;
        }
 }
 
@@ -85,16 +89,23 @@ static int op_create_counter(int cpu, int event)
        if (IS_ERR(pevent))
                return PTR_ERR(pevent);
 
-       if (pevent->state != PERF_EVENT_STATE_ACTIVE) {
-               perf_event_release_kernel(pevent);
-               pr_warning("oprofile: failed to enable event %d "
-                               "on CPU %d\n", event, cpu);
-               return -EBUSY;
-       }
-
        per_cpu(perf_events, cpu)[event] = pevent;
 
-       return 0;
+       /* sync perf_events with overflow handler: */
+       smp_wmb();
+
+       perf_event_enable(pevent);
+
+       if (pevent->state == PERF_EVENT_STATE_ACTIVE)
+               return 0;
+
+       perf_event_release_kernel(pevent);
+       per_cpu(perf_events, cpu)[event] = NULL;
+
+       pr_warning("oprofile: failed to enable event %d on CPU %d\n",
+               event, cpu);
+
+       return -EBUSY;
 }
 
 static void op_destroy_counter(int cpu, int event)
-- 
1.8.4.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to