aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/perf/Makefile.perf2
-rw-r--r--tools/perf/builtin-trace.c4
-rw-r--r--tools/perf/util/comm.c106
-rw-r--r--tools/perf/util/comm.h20
-rw-r--r--tools/perf/util/thread.c92
-rw-r--r--tools/perf/util/thread.h3
6 files changed, 200 insertions, 27 deletions
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index bc7cfa18a1e3..cb52bdb755c7 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -273,6 +273,7 @@ LIB_H += util/color.h
273LIB_H += util/values.h 273LIB_H += util/values.h
274LIB_H += util/sort.h 274LIB_H += util/sort.h
275LIB_H += util/hist.h 275LIB_H += util/hist.h
276LIB_H += util/comm.h
276LIB_H += util/thread.h 277LIB_H += util/thread.h
277LIB_H += util/thread_map.h 278LIB_H += util/thread_map.h
278LIB_H += util/trace-event.h 279LIB_H += util/trace-event.h
@@ -341,6 +342,7 @@ LIB_OBJS += $(OUTPUT)util/machine.o
341LIB_OBJS += $(OUTPUT)util/map.o 342LIB_OBJS += $(OUTPUT)util/map.o
342LIB_OBJS += $(OUTPUT)util/pstack.o 343LIB_OBJS += $(OUTPUT)util/pstack.o
343LIB_OBJS += $(OUTPUT)util/session.o 344LIB_OBJS += $(OUTPUT)util/session.o
345LIB_OBJS += $(OUTPUT)util/comm.o
344LIB_OBJS += $(OUTPUT)util/thread.o 346LIB_OBJS += $(OUTPUT)util/thread.o
345LIB_OBJS += $(OUTPUT)util/thread_map.o 347LIB_OBJS += $(OUTPUT)util/thread_map.o
346LIB_OBJS += $(OUTPUT)util/trace-event-parse.o 348LIB_OBJS += $(OUTPUT)util/trace-event-parse.o
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 95d639212d98..b3e57dc64546 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -1114,7 +1114,7 @@ static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thre
1114 1114
1115 if (trace->multiple_threads) { 1115 if (trace->multiple_threads) {
1116 if (trace->show_comm) 1116 if (trace->show_comm)
1117 printed += fprintf(fp, "%.14s/", thread->comm); 1117 printed += fprintf(fp, "%.14s/", thread__comm_str(thread));
1118 printed += fprintf(fp, "%d ", thread->tid); 1118 printed += fprintf(fp, "%d ", thread->tid);
1119 } 1119 }
1120 1120
@@ -1986,7 +1986,7 @@ static int trace__fprintf_one_thread(struct thread *thread, void *priv)
1986 else if (ratio > 5.0) 1986 else if (ratio > 5.0)
1987 color = PERF_COLOR_YELLOW; 1987 color = PERF_COLOR_YELLOW;
1988 1988
1989 printed += color_fprintf(fp, color, "%20s", thread->comm); 1989 printed += color_fprintf(fp, color, "%20s", thread__comm_str(thread));
1990 printed += fprintf(fp, " - %-5d :%11lu [", thread->tid, ttrace->nr_events); 1990 printed += fprintf(fp, " - %-5d :%11lu [", thread->tid, ttrace->nr_events);
1991 printed += color_fprintf(fp, color, "%5.1f%%", ratio); 1991 printed += color_fprintf(fp, color, "%5.1f%%", ratio);
1992 printed += fprintf(fp, " ] %10.3f ms\n", ttrace->runtime_ms); 1992 printed += fprintf(fp, " ] %10.3f ms\n", ttrace->runtime_ms);
diff --git a/tools/perf/util/comm.c b/tools/perf/util/comm.c
new file mode 100644
index 000000000000..8b3ac9f0207f
--- /dev/null
+++ b/tools/perf/util/comm.c
@@ -0,0 +1,106 @@
1#include "comm.h"
2#include "util.h"
3#include <stdlib.h>
4#include <stdio.h>
5
6struct comm_str {
7 char *str;
8 struct rb_node rb_node;
9 int ref;
10};
11
12/* Should perhaps be moved to struct machine */
13static struct rb_root comm_str_root;
14
15static void comm_str__get(struct comm_str *cs)
16{
17 cs->ref++;
18}
19
20static void comm_str__put(struct comm_str *cs)
21{
22 if (!--cs->ref) {
23 rb_erase(&cs->rb_node, &comm_str_root);
24 free(cs->str);
25 free(cs);
26 }
27}
28
29static struct comm_str *comm_str__alloc(const char *str)
30{
31 struct comm_str *cs;
32
33 cs = zalloc(sizeof(*cs));
34 if (!cs)
35 return NULL;
36
37 cs->str = strdup(str);
38 if (!cs->str) {
39 free(cs);
40 return NULL;
41 }
42
43 return cs;
44}
45
46static struct comm_str *comm_str__findnew(const char *str, struct rb_root *root)
47{
48 struct rb_node **p = &root->rb_node;
49 struct rb_node *parent = NULL;
50 struct comm_str *iter, *new;
51 int cmp;
52
53 while (*p != NULL) {
54 parent = *p;
55 iter = rb_entry(parent, struct comm_str, rb_node);
56
57 cmp = strcmp(str, iter->str);
58 if (!cmp)
59 return iter;
60
61 if (cmp < 0)
62 p = &(*p)->rb_left;
63 else
64 p = &(*p)->rb_right;
65 }
66
67 new = comm_str__alloc(str);
68 if (!new)
69 return NULL;
70
71 rb_link_node(&new->rb_node, parent, p);
72 rb_insert_color(&new->rb_node, root);
73
74 return new;
75}
76
77struct comm *comm__new(const char *str, u64 timestamp)
78{
79 struct comm *comm = zalloc(sizeof(*comm));
80
81 if (!comm)
82 return NULL;
83
84 comm->start = timestamp;
85
86 comm->comm_str = comm_str__findnew(str, &comm_str_root);
87 if (!comm->comm_str) {
88 free(comm);
89 return NULL;
90 }
91
92 comm_str__get(comm->comm_str);
93
94 return comm;
95}
96
97void comm__free(struct comm *comm)
98{
99 comm_str__put(comm->comm_str);
100 free(comm);
101}
102
103const char *comm__str(const struct comm *comm)
104{
105 return comm->comm_str->str;
106}
diff --git a/tools/perf/util/comm.h b/tools/perf/util/comm.h
new file mode 100644
index 000000000000..f62d215bede2
--- /dev/null
+++ b/tools/perf/util/comm.h
@@ -0,0 +1,20 @@
1#ifndef __PERF_COMM_H
2#define __PERF_COMM_H
3
4#include "../perf.h"
5#include <linux/rbtree.h>
6#include <linux/list.h>
7
8struct comm_str;
9
10struct comm {
11 struct comm_str *comm_str;
12 u64 start;
13 struct list_head list;
14};
15
16void comm__free(struct comm *comm);
17struct comm *comm__new(const char *str, u64 timestamp);
18const char *comm__str(const struct comm *comm);
19
20#endif /* __PERF_COMM_H */
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 0ea73fe383f5..15c53c2e109e 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -6,9 +6,12 @@
6#include "thread.h" 6#include "thread.h"
7#include "util.h" 7#include "util.h"
8#include "debug.h" 8#include "debug.h"
9#include "comm.h"
9 10
10struct thread *thread__new(pid_t pid, pid_t tid) 11struct thread *thread__new(pid_t pid, pid_t tid)
11{ 12{
13 char *comm_str;
14 struct comm *comm;
12 struct thread *thread = zalloc(sizeof(*thread)); 15 struct thread *thread = zalloc(sizeof(*thread));
13 16
14 if (thread != NULL) { 17 if (thread != NULL) {
@@ -16,47 +19,88 @@ struct thread *thread__new(pid_t pid, pid_t tid)
16 thread->pid_ = pid; 19 thread->pid_ = pid;
17 thread->tid = tid; 20 thread->tid = tid;
18 thread->ppid = -1; 21 thread->ppid = -1;
19 thread->comm = malloc(32); 22 INIT_LIST_HEAD(&thread->comm_list);
20 if (thread->comm) 23
21 snprintf(thread->comm, 32, ":%d", thread->tid); 24 comm_str = malloc(32);
25 if (!comm_str)
26 goto err_thread;
27
28 snprintf(comm_str, 32, ":%d", tid);
29 comm = comm__new(comm_str, 0);
30 free(comm_str);
31 if (!comm)
32 goto err_thread;
33
34 list_add(&comm->list, &thread->comm_list);
22 } 35 }
23 36
24 return thread; 37 return thread;
38
39err_thread:
40 free(thread);
41 return NULL;
25} 42}
26 43
27void thread__delete(struct thread *thread) 44void thread__delete(struct thread *thread)
28{ 45{
46 struct comm *comm, *tmp;
47
29 map_groups__exit(&thread->mg); 48 map_groups__exit(&thread->mg);
30 free(thread->comm); 49 list_for_each_entry_safe(comm, tmp, &thread->comm_list, list) {
50 list_del(&comm->list);
51 comm__free(comm);
52 }
53
31 free(thread); 54 free(thread);
32} 55}
33 56
34int thread__set_comm(struct thread *thread, const char *comm, 57static struct comm *thread__comm(const struct thread *thread)
35 u64 timestamp __maybe_unused)
36{ 58{
37 int err; 59 if (list_empty(&thread->comm_list))
60 return NULL;
38 61
39 if (thread->comm) 62 return list_first_entry(&thread->comm_list, struct comm, list);
40 free(thread->comm); 63}
41 thread->comm = strdup(comm); 64
42 err = thread->comm == NULL ? -ENOMEM : 0; 65/* CHECKME: time should always be 0 if event aren't ordered */
43 if (!err) { 66int thread__set_comm(struct thread *thread, const char *str, u64 timestamp)
44 thread->comm_set = true; 67{
68 struct comm *new, *curr = thread__comm(thread);
69
70 /* Override latest entry if it had no specific time coverage */
71 if (!curr->start) {
72 list_del(&curr->list);
73 comm__free(curr);
45 } 74 }
46 return err; 75
76 new = comm__new(str, timestamp);
77 if (!new)
78 return -ENOMEM;
79
80 list_add(&new->list, &thread->comm_list);
81 thread->comm_set = true;
82
83 return 0;
47} 84}
48 85
49const char *thread__comm_str(const struct thread *thread) 86const char *thread__comm_str(const struct thread *thread)
50{ 87{
51 return thread->comm; 88 const struct comm *comm = thread__comm(thread);
89
90 if (!comm)
91 return NULL;
92
93 return comm__str(comm);
52} 94}
53 95
96/* CHECKME: it should probably better return the max comm len from its comm list */
54int thread__comm_len(struct thread *thread) 97int thread__comm_len(struct thread *thread)
55{ 98{
56 if (!thread->comm_len) { 99 if (!thread->comm_len) {
57 if (!thread->comm) 100 const char *comm = thread__comm_str(thread);
101 if (!comm)
58 return 0; 102 return 0;
59 thread->comm_len = strlen(thread->comm); 103 thread->comm_len = strlen(comm);
60 } 104 }
61 105
62 return thread->comm_len; 106 return thread->comm_len;
@@ -74,17 +118,17 @@ void thread__insert_map(struct thread *thread, struct map *map)
74 map_groups__insert(&thread->mg, map); 118 map_groups__insert(&thread->mg, map);
75} 119}
76 120
77int thread__fork(struct thread *thread, struct thread *parent, 121int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp)
78 u64 timestamp __maybe_unused)
79{ 122{
80 int i; 123 int i, err;
81 124
82 if (parent->comm_set) { 125 if (parent->comm_set) {
83 if (thread->comm) 126 const char *comm = thread__comm_str(parent);
84 free(thread->comm); 127 if (!comm)
85 thread->comm = strdup(parent->comm);
86 if (!thread->comm)
87 return -ENOMEM; 128 return -ENOMEM;
129 err = thread__set_comm(thread, comm, timestamp);
130 if (!err)
131 return err;
88 thread->comm_set = true; 132 thread->comm_set = true;
89 } 133 }
90 134
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 4e9724270a64..8702c6b4163a 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -2,6 +2,7 @@
2#define __PERF_THREAD_H 2#define __PERF_THREAD_H
3 3
4#include <linux/rbtree.h> 4#include <linux/rbtree.h>
5#include <linux/list.h>
5#include <unistd.h> 6#include <unistd.h>
6#include <sys/types.h> 7#include <sys/types.h>
7#include "symbol.h" 8#include "symbol.h"
@@ -18,7 +19,7 @@ struct thread {
18 char shortname[3]; 19 char shortname[3];
19 bool comm_set; 20 bool comm_set;
20 bool dead; /* if set thread has exited */ 21 bool dead; /* if set thread has exited */
21 char *comm; 22 struct list_head comm_list;
22 int comm_len; 23 int comm_len;
23 24
24 void *priv; 25 void *priv;