On 09/09, Roland McGrath wrote:
>
> >     2. Is utrace_barrier() correct???? Note the example above,
> >        it assumes that utrace_barrier() itself is the barrier
> >        wrt reporting. But, is it?
>
> I don't think I understand the question.

Sorry for delay on this. I have a lot of emails unanswered, in particular
about jctl issues. And this one.

I still didn't find the time to read the code around set/clear ->reporting,
it is subtle and needs a fresh head.

But at least, I think finish_callback() needs an mb() before clearing
->reporting.

Let me repeat the pseudo-code from the previous email. Say, we have
a global (for simplicity) pointer:

        something_t *ptr;

We have a callback

        void my_report_callback(...)
        {
                if (ptr)
                        dereference(ptr);
        }

And the tracer does:

        void *tmp = ptr;
        ptr = NULL;
        utrace_barrier(my_engine);
        kfree(tmp);

This should work correctly, right?

But, I think this is racy because finish_callback() clears ->reporting
without the barrier. this means (in theory) utrace_barrier() can see
->reporting == NULL before my_report_callback() sees ptr == NULL. And
perhaps utrace_barrier() itself needs a barrier.

utrace_barrier() takes utrace->lock, but the reporting loop doesn't
always take this lock. So we have

        TRACER:                 TRACEE:

        ptr = NULL;             if (ptr)
                                        dereference(ptr);
        if (!->reporting)
                kfree(ptr);     ->reporting = NULL;

This looks racy.

Oleg.

Reply via email to