This is the mail archive of the systemtap@sourceware.org mailing list for the systemtap project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: container_of - complex indirections - guru code - workqueues


On 09/28/2011 04:17 PM, Turgis, Frederic wrote:
> I have assumed that guru code is only method to get data in following cases:
> 1 - data is retrieved by a "container_of(...)"  syntax

If we ever get to PR11207 (preprocessor macros), this would be a good
one to add.  In the meantime though, you can emulate it:

  offsetof(type, member) = & @cast(0, "type")->member
  container_of(ptr, type, member) = ptr - & @cast(0, "type")->member

> 2 - specific method like
> unsigned long data = atomic_long_read(&work->data);
> return (void *)(data & WORK_STRUCT_WQ_DATA_MASK);
> => then it would do (struct cpu_workqueue_struct *)data->wq->name

You can do most of this directly -- only getting the value of the MASK
is tricky.  You could do it with a tiny embedded %{ MASK %} block
though, or else hard-code it.

> On top of that, I also have the issue that definitions are sometimes
> internal to C file like "struct cpu_workqueue_struct" so I mix guru code
> and @cast (summarized below):
> function get_workqueue_pointer:long(ref:long) %{
>         struct work_struct *work; unsigned long data;
> 
>         work = (struct work_struct *)((uint32_t)(THIS->ref));

As an aside, (long) is a more portable intermediary for casting int64_t
arguments to pointers.

>         data = atomic_long_read(&work->data);
>         THIS->__retvalue = (data & WORK_STRUCT_WQ_DATA_MASK);
> %}
> 
> probe kernel.function("process_one_work") {
>         workqueue = get_workqueue_pointer($work);
>         printf("process_one_work %p %s \n", $work->func, kernel_string(@cast(workqueue, "struct cpu_workqueue_struct")->wq->name));
> }
> 
> Sounds reasonable or too hackish (shall I duplicate kernel code into my
> script) ? If you look at the code, you may find better solutions using
> same probe at a specific line of code but I wanted something more
> maintainable

How about:

probe kernel.function("process_one_work") {
    workqueue = atomic_long_read(& $work->data)
    workqueue &= %{ WORK_STRUCT_WQ_DATA_MASK %}
    name = @cast(workqueue, "struct cpu_workqueue_struct")->wq->name
    printf("process_one_work %p %s \n",
            $work->func, kernel_string(name));
}

That will still require a little guru to get the mask, but hopefully you
find that nicer.

> For curious people, I am doing this because of June patch on
> workqueues: it gathered associated kernel threads into a common pool
> so there is no direct association between kernel thread and workqueue
> name. You only get "kworker/x:y" or "kworker/u:y" task name :-(
> Worse, 1 execution of a kworker task can correspond to consecutive
> executions of several workqueues. So I needed to track
> "process_one_work(...)" execution with pointer on function executed
> and related workqueue name.
> 
> A final good probing approach could be interesting to be added to
> "scheduler" examples. I am "happy" with mine but experts can probably
> improve.

Yes, please share -- we like getting new examples, as many people start
by only running those scripts.

Thanks,
Josh


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]