#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include "session.h"
#include "thread.h"
#include "util.h"
#include "debug.h"
-static struct rb_root threads;
-static struct thread *last_match;
+int find_all_tid(int pid, pid_t ** all_tid)
+{
+ char name[256];
+ int items;
+ struct dirent **namelist = NULL;
+ int ret = 0;
+ int i;
+
+ sprintf(name, "/proc/%d/task", pid);
+ items = scandir(name, &namelist, NULL, NULL);
+ if (items <= 0)
+ return -ENOENT;
+ *all_tid = malloc(sizeof(pid_t) * items);
+ if (!*all_tid) {
+ ret = -ENOMEM;
+ goto failure;
+ }
+
+ for (i = 0; i < items; i++)
+ (*all_tid)[i] = atoi(namelist[i]->d_name);
+
+ ret = items;
+
+failure:
+ for (i=0; i<items; i++)
+ free(namelist[i]);
+ free(namelist);
+
+ return ret;
+}
void map_groups__init(struct map_groups *self)
{
return self;
}
+static void map_groups__flush(struct map_groups *self)
+{
+ int type;
+
+ for (type = 0; type < MAP__NR_TYPES; type++) {
+ struct rb_root *root = &self->maps[type];
+ struct rb_node *next = rb_first(root);
+
+ while (next) {
+ struct map *pos = rb_entry(next, struct map, rb_node);
+ next = rb_next(&pos->rb_node);
+ rb_erase(&pos->rb_node, root);
+ /*
+ * We may have references to this map, for
+ * instance in some hist_entry instances, so
+ * just move them to a separate list.
+ */
+ list_add_tail(&pos->node, &self->removed_maps[pos->type]);
+ }
+ }
+}
+
int thread__set_comm(struct thread *self, const char *comm)
{
+ int err;
+
if (self->comm)
free(self->comm);
self->comm = strdup(comm);
- return self->comm ? 0 : -ENOMEM;
+ err = self->comm == NULL ? -ENOMEM : 0;
+ if (!err) {
+ self->comm_set = true;
+ map_groups__flush(&self->mg);
+ }
+ return err;
}
int thread__comm_len(struct thread *self)
return self->comm_len;
}
-static const char *map_type__name[MAP__NR_TYPES] = {
- [MAP__FUNCTION] = "Functions",
- [MAP__VARIABLE] = "Variables",
-};
-
-static size_t __map_groups__fprintf_maps(struct map_groups *self,
- enum map_type type, FILE *fp)
+size_t __map_groups__fprintf_maps(struct map_groups *self,
+ enum map_type type, FILE *fp)
{
size_t printed = fprintf(fp, "%s:\n", map_type__name[type]);
struct rb_node *nd;
struct map *pos = rb_entry(nd, struct map, rb_node);
printed += fprintf(fp, "Map:");
printed += map__fprintf(pos, fp);
- if (verbose > 1) {
+ if (verbose > 2) {
printed += dso__fprintf(pos->dso, type, fp);
printed += fprintf(fp, "--\n");
}
map_groups__fprintf(&self->mg, fp);
}
-struct thread *threads__findnew(pid_t pid)
+struct thread *perf_session__findnew(struct perf_session *self, pid_t pid)
{
- struct rb_node **p = &threads.rb_node;
+ struct rb_node **p = &self->threads.rb_node;
struct rb_node *parent = NULL;
struct thread *th;
* so most of the time we dont have to look up
* the full rbtree:
*/
- if (last_match && last_match->pid == pid)
- return last_match;
+ if (self->last_match && self->last_match->pid == pid)
+ return self->last_match;
while (*p != NULL) {
parent = *p;
th = rb_entry(parent, struct thread, rb_node);
if (th->pid == pid) {
- last_match = th;
+ self->last_match = th;
return th;
}
th = thread__new(pid);
if (th != NULL) {
rb_link_node(&th->rb_node, parent, p);
- rb_insert_color(&th->rb_node, &threads);
- last_match = th;
+ rb_insert_color(&th->rb_node, &self->threads);
+ self->last_match = th;
}
return th;
}
-static void map_groups__remove_overlappings(struct map_groups *self,
- struct map *map)
+static int map_groups__fixup_overlappings(struct map_groups *self,
+ struct map *map)
{
struct rb_root *root = &self->maps[map->type];
struct rb_node *next = rb_first(root);
* list.
*/
list_add_tail(&pos->node, &self->removed_maps[map->type]);
+ /*
+ * Now check if we need to create new maps for areas not
+ * overlapped by the new map:
+ */
+ if (map->start > pos->start) {
+ struct map *before = map__clone(pos);
+
+ if (before == NULL)
+ return -ENOMEM;
+
+ before->end = map->start - 1;
+ map_groups__insert(self, before);
+ if (verbose >= 2)
+ map__fprintf(before, stderr);
+ }
+
+ if (map->end < pos->end) {
+ struct map *after = map__clone(pos);
+
+ if (after == NULL)
+ return -ENOMEM;
+
+ after->start = map->end + 1;
+ map_groups__insert(self, after);
+ if (verbose >= 2)
+ map__fprintf(after, stderr);
+ }
}
+
+ return 0;
}
void maps__insert(struct rb_root *maps, struct map *map)
void thread__insert_map(struct thread *self, struct map *map)
{
- map_groups__remove_overlappings(&self->mg, map);
+ map_groups__fixup_overlappings(&self->mg, map);
map_groups__insert(&self->mg, map);
}
{
int i;
- if (self->comm)
- free(self->comm);
- self->comm = strdup(parent->comm);
- if (!self->comm)
- return -ENOMEM;
+ if (parent->comm_set) {
+ if (self->comm)
+ free(self->comm);
+ self->comm = strdup(parent->comm);
+ if (!self->comm)
+ return -ENOMEM;
+ self->comm_set = true;
+ }
for (i = 0; i < MAP__NR_TYPES; ++i)
if (map_groups__clone(&self->mg, &parent->mg, i) < 0)
return 0;
}
-size_t threads__fprintf(FILE *fp)
+size_t perf_session__fprintf(struct perf_session *self, FILE *fp)
{
size_t ret = 0;
struct rb_node *nd;
- for (nd = rb_first(&threads); nd; nd = rb_next(nd)) {
+ for (nd = rb_first(&self->threads); nd; nd = rb_next(nd)) {
struct thread *pos = rb_entry(nd, struct thread, rb_node);
ret += thread__fprintf(pos, fp);
return NULL;
}
+