On 11/16, Roland McGrath wrote:
>
> > But this smp_rmb() in task_utrace_struct() is only needed when the
> > caller does something like
> >
> >     if (task_utrace_flags(tsk))
> >             do_something(task_utrace_struct());
>
> If you look at where task_utrace_struct() is used, it's basically always
> like this.  All the tracehook.h callers into utrace.c do that.
>
> ...
>
> But that's not the only place, is it?  Every utrace_report_* and most every
> other utrace.c entry point is called from tracehook.h code using this pattern.
> Those can have the same issue.  So you'd have to make all of those do an:
>       if (unlikely(!utrace))
>               return;
> sort of check.  Is that what you mean?

Yes, agreed, this doesn't look good.

So, I think it is better to add the barriers into task_utrace_struct()
like you already did.

(a very minor nit: s/read_barrier_depends/smp_read_barrier_depends/)


Just to complete the discussion, we could do

        static inline unsigned long task_utrace_flags(struct task_struct *task)
        {
                if (!task->utrace)
                        return 0;
                return task->utrace_flags;
        }

to void rmb() without complicationg the code, but this still adds
some overhead to the hot path.

And a bit offtopic question. Apart from "task_utrace_flags() should
be as fast as possible", any other reason we can't move ->utrace_flags
into "struct utrace" ?

In the "likely" case we should worry about (the task was never
traced), ->utrace == NULL and

        task_utrace_flags(struct task_struct *task)
        {
                if (likley(!task->utrace))
                        return 0;
                return task->utrace->flags;
        }

shouldn't be slower. If the task was ever traced and then utraced
this adds the extra dereference, yes.

Oleg.

Reply via email to