Commit | Line | Data |
---|---|---|
6baa0a5a FW |
1 | #include "../perf.h" |
2 | #include <stdlib.h> | |
3 | #include <stdio.h> | |
4 | #include <string.h> | |
b3165f41 | 5 | #include "session.h" |
6baa0a5a FW |
6 | #include "thread.h" |
7 | #include "util.h" | |
6e086437 | 8 | #include "debug.h" |
1902efe7 | 9 | #include "comm.h" |
6baa0a5a | 10 | |
99d725fc | 11 | struct thread *thread__new(pid_t pid, pid_t tid) |
6baa0a5a | 12 | { |
1902efe7 FW |
13 | char *comm_str; |
14 | struct comm *comm; | |
c824c433 | 15 | struct thread *thread = zalloc(sizeof(*thread)); |
6baa0a5a | 16 | |
c824c433 ACM |
17 | if (thread != NULL) { |
18 | map_groups__init(&thread->mg); | |
19 | thread->pid_ = pid; | |
20 | thread->tid = tid; | |
21 | thread->ppid = -1; | |
1902efe7 FW |
22 | INIT_LIST_HEAD(&thread->comm_list); |
23 | ||
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); | |
6baa0a5a FW |
35 | } |
36 | ||
c824c433 | 37 | return thread; |
1902efe7 FW |
38 | |
39 | err_thread: | |
40 | free(thread); | |
41 | return NULL; | |
6baa0a5a FW |
42 | } |
43 | ||
c824c433 | 44 | void thread__delete(struct thread *thread) |
591765fd | 45 | { |
1902efe7 FW |
46 | struct comm *comm, *tmp; |
47 | ||
c824c433 | 48 | map_groups__exit(&thread->mg); |
1902efe7 FW |
49 | list_for_each_entry_safe(comm, tmp, &thread->comm_list, list) { |
50 | list_del(&comm->list); | |
51 | comm__free(comm); | |
52 | } | |
53 | ||
c824c433 | 54 | free(thread); |
591765fd ACM |
55 | } |
56 | ||
4dfced35 | 57 | struct comm *thread__comm(const struct thread *thread) |
6baa0a5a | 58 | { |
1902efe7 FW |
59 | if (list_empty(&thread->comm_list)) |
60 | return NULL; | |
4385d580 | 61 | |
1902efe7 FW |
62 | return list_first_entry(&thread->comm_list, struct comm, list); |
63 | } | |
64 | ||
65 | /* CHECKME: time should always be 0 if event aren't ordered */ | |
66 | int thread__set_comm(struct thread *thread, const char *str, u64 timestamp) | |
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) { | |
4dfced35 | 72 | comm__override(curr, str, timestamp); |
a5285ad9 FW |
73 | } else { |
74 | new = comm__new(str, timestamp); | |
75 | if (!new) | |
76 | return -ENOMEM; | |
77 | list_add(&new->list, &thread->comm_list); | |
4385d580 | 78 | } |
1902efe7 | 79 | |
1902efe7 FW |
80 | thread->comm_set = true; |
81 | ||
82 | return 0; | |
6baa0a5a FW |
83 | } |
84 | ||
b9c5143a FW |
85 | const char *thread__comm_str(const struct thread *thread) |
86 | { | |
1902efe7 FW |
87 | const struct comm *comm = thread__comm(thread); |
88 | ||
89 | if (!comm) | |
90 | return NULL; | |
91 | ||
92 | return comm__str(comm); | |
b9c5143a FW |
93 | } |
94 | ||
1902efe7 | 95 | /* CHECKME: it should probably better return the max comm len from its comm list */ |
c824c433 | 96 | int thread__comm_len(struct thread *thread) |
a4fb581b | 97 | { |
c824c433 | 98 | if (!thread->comm_len) { |
1902efe7 FW |
99 | const char *comm = thread__comm_str(thread); |
100 | if (!comm) | |
a4fb581b | 101 | return 0; |
1902efe7 | 102 | thread->comm_len = strlen(comm); |
a4fb581b FW |
103 | } |
104 | ||
c824c433 | 105 | return thread->comm_len; |
a4fb581b FW |
106 | } |
107 | ||
3f067dca | 108 | size_t thread__fprintf(struct thread *thread, FILE *fp) |
9958e1f0 | 109 | { |
b9c5143a | 110 | return fprintf(fp, "Thread %d %s\n", thread->tid, thread__comm_str(thread)) + |
3f067dca | 111 | map_groups__fprintf(&thread->mg, verbose, fp); |
6baa0a5a FW |
112 | } |
113 | ||
c824c433 | 114 | void thread__insert_map(struct thread *thread, struct map *map) |
1b46cddf | 115 | { |
c824c433 ACM |
116 | map_groups__fixup_overlappings(&thread->mg, map, verbose, stderr); |
117 | map_groups__insert(&thread->mg, map); | |
6baa0a5a FW |
118 | } |
119 | ||
1902efe7 | 120 | int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp) |
95011c60 | 121 | { |
1902efe7 | 122 | int i, err; |
6baa0a5a | 123 | |
faa5c5c3 | 124 | if (parent->comm_set) { |
1902efe7 FW |
125 | const char *comm = thread__comm_str(parent); |
126 | if (!comm) | |
faa5c5c3 | 127 | return -ENOMEM; |
1902efe7 | 128 | err = thread__set_comm(thread, comm, timestamp); |
8d00be81 | 129 | if (err) |
1902efe7 | 130 | return err; |
c824c433 | 131 | thread->comm_set = true; |
faa5c5c3 | 132 | } |
6baa0a5a | 133 | |
95011c60 | 134 | for (i = 0; i < MAP__NR_TYPES; ++i) |
c824c433 | 135 | if (map_groups__clone(&thread->mg, &parent->mg, i) < 0) |
6baa0a5a | 136 | return -ENOMEM; |
70c57efb | 137 | |
c824c433 | 138 | thread->ppid = parent->tid; |
70c57efb | 139 | |
6baa0a5a FW |
140 | return 0; |
141 | } |