10 /* Skip "." and ".." directories */
11 static int filter(const struct dirent
*dir
)
13 if (dir
->d_name
[0] == '.')
19 struct thread_map
*thread_map__new_by_pid(pid_t pid
)
21 struct thread_map
*threads
;
24 struct dirent
**namelist
= NULL
;
27 sprintf(name
, "/proc/%d/task", pid
);
28 items
= scandir(name
, &namelist
, filter
, NULL
);
32 threads
= malloc(sizeof(*threads
) + sizeof(pid_t
) * items
);
33 if (threads
!= NULL
) {
34 for (i
= 0; i
< items
; i
++)
35 threads
->map
[i
] = atoi(namelist
[i
]->d_name
);
39 for (i
=0; i
<items
; i
++)
46 struct thread_map
*thread_map__new_by_tid(pid_t tid
)
48 struct thread_map
*threads
= malloc(sizeof(*threads
) + sizeof(pid_t
));
50 if (threads
!= NULL
) {
51 threads
->map
[0] = tid
;
58 struct thread_map
*thread_map__new(pid_t pid
, pid_t tid
)
61 return thread_map__new_by_pid(pid
);
62 return thread_map__new_by_tid(tid
);
65 static struct thread
*thread__new(pid_t pid
)
67 struct thread
*self
= zalloc(sizeof(*self
));
70 map_groups__init(&self
->mg
);
72 self
->comm
= malloc(32);
74 snprintf(self
->comm
, 32, ":%d", self
->pid
);
80 void thread__delete(struct thread
*self
)
82 map_groups__exit(&self
->mg
);
87 int thread__set_comm(struct thread
*self
, const char *comm
)
93 self
->comm
= strdup(comm
);
94 err
= self
->comm
== NULL
? -ENOMEM
: 0;
96 self
->comm_set
= true;
97 map_groups__flush(&self
->mg
);
102 int thread__comm_len(struct thread
*self
)
104 if (!self
->comm_len
) {
107 self
->comm_len
= strlen(self
->comm
);
110 return self
->comm_len
;
113 static size_t thread__fprintf(struct thread
*self
, FILE *fp
)
115 return fprintf(fp
, "Thread %d %s\n", self
->pid
, self
->comm
) +
116 map_groups__fprintf(&self
->mg
, verbose
, fp
);
119 struct thread
*perf_session__findnew(struct perf_session
*self
, pid_t pid
)
121 struct rb_node
**p
= &self
->threads
.rb_node
;
122 struct rb_node
*parent
= NULL
;
126 * Font-end cache - PID lookups come in blocks,
127 * so most of the time we dont have to look up
130 if (self
->last_match
&& self
->last_match
->pid
== pid
)
131 return self
->last_match
;
135 th
= rb_entry(parent
, struct thread
, rb_node
);
137 if (th
->pid
== pid
) {
138 self
->last_match
= th
;
148 th
= thread__new(pid
);
150 rb_link_node(&th
->rb_node
, parent
, p
);
151 rb_insert_color(&th
->rb_node
, &self
->threads
);
152 self
->last_match
= th
;
158 void thread__insert_map(struct thread
*self
, struct map
*map
)
160 map_groups__fixup_overlappings(&self
->mg
, map
, verbose
, stderr
);
161 map_groups__insert(&self
->mg
, map
);
164 int thread__fork(struct thread
*self
, struct thread
*parent
)
168 if (parent
->comm_set
) {
171 self
->comm
= strdup(parent
->comm
);
174 self
->comm_set
= true;
177 for (i
= 0; i
< MAP__NR_TYPES
; ++i
)
178 if (map_groups__clone(&self
->mg
, &parent
->mg
, i
) < 0)
183 size_t perf_session__fprintf(struct perf_session
*self
, FILE *fp
)
188 for (nd
= rb_first(&self
->threads
); nd
; nd
= rb_next(nd
)) {
189 struct thread
*pos
= rb_entry(nd
, struct thread
, rb_node
);
191 ret
+= thread__fprintf(pos
, fp
);