lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAM9d7chrHpOs-zN0o4WH=L=h8RPQEKa9dQFvGebRaUQFLNfNmA@mail.gmail.com>
Date:	Sun, 28 Dec 2014 23:50:42 +0900
From:	Namhyung Kim <namhyung@...nel.org>
To:	David Ahern <dsahern@...il.com>
Cc:	Arnaldo Carvalho de Melo <acme@...nel.org>,
	Ingo Molnar <mingo@...nel.org>,
	Peter Zijlstra <a.p.zijlstra@...llo.nl>,
	Jiri Olsa <jolsa@...hat.com>,
	LKML <linux-kernel@...r.kernel.org>,
	Stephane Eranian <eranian@...gle.com>,
	Adrian Hunter <adrian.hunter@...el.com>,
	Andi Kleen <andi@...stfloor.org>,
	Frederic Weisbecker <fweisbec@...il.com>
Subject: Re: [PATCH 15/37] perf tools: Introduce machine__find*_thread_time()

On Sun, Dec 28, 2014 at 1:33 AM, David Ahern <dsahern@...il.com> wrote:
> On 12/24/14 12:15 AM, Namhyung Kim wrote:
>>
>> @@ -61,12 +61,12 @@ static int unwind_entry(struct unwind_entry *entry,
>> void *arg)
>>   __attribute__ ((noinline))
>>   static int unwind_thread(struct thread *thread)
>>   {
>> -       struct perf_sample sample;
>> +       struct perf_sample sample = {
>> +               .time = -1ULL,
>> +       };
>
>
> 1-liner like the others?

Did you mean this?

        struct perf_sample sample = { .time = -1ULL, };

>
>
>
>> diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
>> index 582e011adc92..2cc088d71922 100644
>> --- a/tools/perf/util/machine.c
>> +++ b/tools/perf/util/machine.c
>> @@ -431,6 +431,103 @@ struct thread *machine__find_thread(struct machine
>> *machine, pid_t pid,
>>         return __machine__findnew_thread(machine, pid, tid, false);
>>   }
>>
>> +static void machine__remove_thread(struct machine *machine, struct thread
>> *th);
>
>
> Why is this declaration needed?

It seems like a leftover from previous changes, will remove.


>
>> +
>> +static struct thread *__machine__findnew_thread_time(struct machine
>> *machine,
>> +                                                    pid_t pid, pid_t tid,
>> +                                                    u64 timestamp, bool
>> create)
>> +{
>> +       struct thread *curr, *pos, *new;
>> +       struct thread *th = NULL;
>> +       struct rb_node **p;
>> +       struct rb_node *parent = NULL;
>> +       bool initial = timestamp == (u64)0;
>> +
>> +       curr = __machine__findnew_thread(machine, pid, tid, initial);
>
>
> What if create arg is false? Should initial arg also be false?

Nop, the create arg adds the thread to the dead thread tree (or
missing thread tree later).  And the initial flag adds it to the
normal threads tree like in case of synthesized events.  This was
because I firstly used the *_findnew_thread_time() for the meta event
processing, but then I realized that using *_findnew_thread() makes
the processing much easier since the meta events are processed
sequencially.  And this *_findnew_thread_time() is used only for
sample processing.  Maybe we can use 'false' instead of the
'initial'..


>
>> +       if (curr && timestamp >= curr->start_time)
>> +               return curr;
>> +
>> +       p = &machine->dead_threads.rb_node;
>> +       while (*p != NULL) {
>> +               parent = *p;
>> +               th = rb_entry(parent, struct thread, rb_node);
>> +
>> +               if (th->tid == tid) {
>> +                       list_for_each_entry(pos, &th->node, node) {
>> +                               if (timestamp >= pos->start_time &&
>> +                                   pos->start_time > th->start_time) {
>> +                                       th = pos;
>> +                                       break;
>> +                               }
>> +                       }
>> +
>> +                       if (timestamp >= th->start_time) {
>> +                               machine__update_thread_pid(machine, th,
>> pid);
>> +                               return th;
>> +                       }
>> +                       break;
>> +               }
>> +
>> +               if (tid < th->tid)
>> +                       p = &(*p)->rb_left;
>> +               else
>> +                       p = &(*p)->rb_right;
>> +       }
>
>
> Can the dead_threads search be put in a separate function --
> machine__find_dead_thread?

Okay, I can do it.


>
>> +
>> +       if (!create)
>> +               return NULL;
>> +
>> +       if (!curr)
>> +               return __machine__findnew_thread(machine, pid, tid, true);
>> +
>> +       new = thread__new(pid, tid);
>> +       if (new == NULL)
>> +               return NULL;
>> +
>> +       new->start_time = timestamp;
>> +
>> +       if (*p) {
>> +               list_for_each_entry(pos, &th->node, node) {
>> +                       /* sort by time */
>> +                       if (timestamp >= pos->start_time) {
>> +                               th = pos;
>> +                               break;
>> +                       }
>> +               }
>> +               list_add_tail(&new->node, &th->node);
>> +       } else {
>> +               rb_link_node(&new->rb_node, parent, p);
>> +               rb_insert_color(&new->rb_node, &machine->dead_threads);
>> +       }
>
>
> Why insert this unknown tid on the dead_threads list?

Well, mostly the search will be succeeded, and if it failed it's
either newly created thread so curr = NULL and adds it to the normal
tree.  Otherwise (rarely) there might be a missing fork event and the
sample is for an older thread in that any timestamp didn't match to
existing (current and dead) threads.  So I added it to the dead thread
tree.  But with multi-thread support enabled, it'll be added to the
new missing threads tree which is protected by a mutex.


>
>> +
>> +       /*
>> +        * We have to initialize map_groups separately
>> +        * after rb tree is updated.
>> +        *
>> +        * The reason is that we call machine__findnew_thread
>> +        * within thread__init_map_groups to find the thread
>> +        * leader and that would screwed the rb tree.
>> +        */
>> +       if (thread__init_map_groups(new, machine)) {
>> +               thread__delete(new);
>> +               return NULL;
>> +       }
>> +
>> +       return new;
>> +}
>
>
> ---8<---
>
>> @@ -1265,6 +1362,16 @@ static void machine__remove_thread(struct machine
>> *machine, struct thread *th)
>>                 pos = rb_entry(parent, struct thread, rb_node);
>>
>>                 if (pos->tid == th->tid) {
>> +                       struct thread *old;
>> +
>> +                       /* sort by time */
>> +                       list_for_each_entry(old, &pos->node, node) {
>> +                               if (th->start_time >= old->start_time) {
>> +                                       pos = old;
>> +                                       break;
>> +                               }
>> +                       }
>> +
>
>
> this change seems unrelated to the patch subject --
> machine__find*_thread_time.

It searchs a thread in the dead threads tree based on timestamp value.
So the list should be sorted by time order.  But yes, I agree that
this change should be moved to the dead thread conversion patch.

Thanks,
Namhyung
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ