public inbox for systemtap@sourceware.org
 help / color / mirror / Atom feed
* container_of - complex indirections - guru code - workqueues
@ 2011-09-28 23:17 Turgis, Frederic
  2011-09-29 20:39 ` Josh Stone
  0 siblings, 1 reply; 3+ messages in thread
From: Turgis, Frederic @ 2011-09-28 23:17 UTC (permalink / raw)
  To: SystemTap

Hi,

I have assumed that guru code is only method to get data in following cases:
1 - data is retrieved by a "container_of(...)"  syntax

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

Is it right ?

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));
        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


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.

Regards
Fred

Frederic Turgis
OMAP Platform Business Unit - OMAP System Engineering - Platform Enablement


Texas Instruments France SA, 821 Avenue Jack Kilby, 06270 Villeneuve Loubet. 036 420 040 R.C.S Antibes. Capital de EUR 753.920



^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: container_of - complex indirections - guru code - workqueues
  2011-09-28 23:17 container_of - complex indirections - guru code - workqueues Turgis, Frederic
@ 2011-09-29 20:39 ` Josh Stone
  2011-09-30 15:12   ` Turgis, Frederic
  0 siblings, 1 reply; 3+ messages in thread
From: Josh Stone @ 2011-09-29 20:39 UTC (permalink / raw)
  To: Turgis, Frederic; +Cc: SystemTap

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

^ permalink raw reply	[flat|nested] 3+ messages in thread

* RE: container_of - complex indirections - guru code - workqueues
  2011-09-29 20:39 ` Josh Stone
@ 2011-09-30 15:12   ` Turgis, Frederic
  0 siblings, 0 replies; 3+ messages in thread
From: Turgis, Frederic @ 2011-09-30 15:12 UTC (permalink / raw)
  To: Josh Stone; +Cc: SystemTap

>  offsetof(type, member) = & @cast(0, "type")->member
>  container_of(ptr, type, member) = ptr - & @cast(0, "type")->member
Very nice. In fact, I was not aware of the "&" and the 0 of @cast(0, ...) from reading the doc (even if & makes sense and @cast(0,...) is used in tapset). It opens new ideas to me

>> 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):
Thanks for the rewrite.
In fact, I shall better explain this point. "atomic_long_read(& $work->data)" + "workqueue &= %{ WORK_STRUCT_WQ_DATA_MASK %}" are already duplication of content of get_work_cwq(...), which is static so guru can't call it. So I shall duplicate code.
But tapset + & + @cast(0, ...) + rest of syntax are powerful enough to avoid guru for most of my needs.

>Yes, please share -- we like getting new examples, as many
>people start by only running those scripts.
I will rewrite based on your inputs and share it. This is interesting for workqueues and also in terms in syntax. Eventually new keywords shall be added for syntax itself

Regards
Fred

Texas Instruments France SA, 821 Avenue Jack Kilby, 06270 Villeneuve Loubet. 036 420 040 R.C.S Antibes. Capital de EUR 753.920



^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2011-09-30 15:12 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-09-28 23:17 container_of - complex indirections - guru code - workqueues Turgis, Frederic
2011-09-29 20:39 ` Josh Stone
2011-09-30 15:12   ` Turgis, Frederic

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).