1*6baa0a5aSFrederic Weisbecker #include "../perf.h" 2*6baa0a5aSFrederic Weisbecker #include <stdlib.h> 3*6baa0a5aSFrederic Weisbecker #include <stdio.h> 4*6baa0a5aSFrederic Weisbecker #include <string.h> 5*6baa0a5aSFrederic Weisbecker #include "thread.h" 6*6baa0a5aSFrederic Weisbecker #include "util.h" 7*6baa0a5aSFrederic Weisbecker 8*6baa0a5aSFrederic Weisbecker static struct thread *thread__new(pid_t pid) 9*6baa0a5aSFrederic Weisbecker { 10*6baa0a5aSFrederic Weisbecker struct thread *self = malloc(sizeof(*self)); 11*6baa0a5aSFrederic Weisbecker 12*6baa0a5aSFrederic Weisbecker if (self != NULL) { 13*6baa0a5aSFrederic Weisbecker self->pid = pid; 14*6baa0a5aSFrederic Weisbecker self->comm = malloc(32); 15*6baa0a5aSFrederic Weisbecker if (self->comm) 16*6baa0a5aSFrederic Weisbecker snprintf(self->comm, 32, ":%d", self->pid); 17*6baa0a5aSFrederic Weisbecker INIT_LIST_HEAD(&self->maps); 18*6baa0a5aSFrederic Weisbecker } 19*6baa0a5aSFrederic Weisbecker 20*6baa0a5aSFrederic Weisbecker return self; 21*6baa0a5aSFrederic Weisbecker } 22*6baa0a5aSFrederic Weisbecker 23*6baa0a5aSFrederic Weisbecker int thread__set_comm(struct thread *self, const char *comm) 24*6baa0a5aSFrederic Weisbecker { 25*6baa0a5aSFrederic Weisbecker if (self->comm) 26*6baa0a5aSFrederic Weisbecker free(self->comm); 27*6baa0a5aSFrederic Weisbecker self->comm = strdup(comm); 28*6baa0a5aSFrederic Weisbecker return self->comm ? 0 : -ENOMEM; 29*6baa0a5aSFrederic Weisbecker } 30*6baa0a5aSFrederic Weisbecker 31*6baa0a5aSFrederic Weisbecker static size_t thread__fprintf(struct thread *self, FILE *fp) 32*6baa0a5aSFrederic Weisbecker { 33*6baa0a5aSFrederic Weisbecker struct map *pos; 34*6baa0a5aSFrederic Weisbecker size_t ret = fprintf(fp, "Thread %d %s\n", self->pid, self->comm); 35*6baa0a5aSFrederic Weisbecker 36*6baa0a5aSFrederic Weisbecker list_for_each_entry(pos, &self->maps, node) 37*6baa0a5aSFrederic Weisbecker ret += map__fprintf(pos, fp); 38*6baa0a5aSFrederic Weisbecker 39*6baa0a5aSFrederic Weisbecker return ret; 40*6baa0a5aSFrederic Weisbecker } 41*6baa0a5aSFrederic Weisbecker 42*6baa0a5aSFrederic Weisbecker struct thread * 43*6baa0a5aSFrederic Weisbecker threads__findnew(pid_t pid, struct rb_root *threads, struct thread **last_match) 44*6baa0a5aSFrederic Weisbecker { 45*6baa0a5aSFrederic Weisbecker struct rb_node **p = &threads->rb_node; 46*6baa0a5aSFrederic Weisbecker struct rb_node *parent = NULL; 47*6baa0a5aSFrederic Weisbecker struct thread *th; 48*6baa0a5aSFrederic Weisbecker 49*6baa0a5aSFrederic Weisbecker /* 50*6baa0a5aSFrederic Weisbecker * Font-end cache - PID lookups come in blocks, 51*6baa0a5aSFrederic Weisbecker * so most of the time we dont have to look up 52*6baa0a5aSFrederic Weisbecker * the full rbtree: 53*6baa0a5aSFrederic Weisbecker */ 54*6baa0a5aSFrederic Weisbecker if (*last_match && (*last_match)->pid == pid) 55*6baa0a5aSFrederic Weisbecker return *last_match; 56*6baa0a5aSFrederic Weisbecker 57*6baa0a5aSFrederic Weisbecker while (*p != NULL) { 58*6baa0a5aSFrederic Weisbecker parent = *p; 59*6baa0a5aSFrederic Weisbecker th = rb_entry(parent, struct thread, rb_node); 60*6baa0a5aSFrederic Weisbecker 61*6baa0a5aSFrederic Weisbecker if (th->pid == pid) { 62*6baa0a5aSFrederic Weisbecker *last_match = th; 63*6baa0a5aSFrederic Weisbecker return th; 64*6baa0a5aSFrederic Weisbecker } 65*6baa0a5aSFrederic Weisbecker 66*6baa0a5aSFrederic Weisbecker if (pid < th->pid) 67*6baa0a5aSFrederic Weisbecker p = &(*p)->rb_left; 68*6baa0a5aSFrederic Weisbecker else 69*6baa0a5aSFrederic Weisbecker p = &(*p)->rb_right; 70*6baa0a5aSFrederic Weisbecker } 71*6baa0a5aSFrederic Weisbecker 72*6baa0a5aSFrederic Weisbecker th = thread__new(pid); 73*6baa0a5aSFrederic Weisbecker if (th != NULL) { 74*6baa0a5aSFrederic Weisbecker rb_link_node(&th->rb_node, parent, p); 75*6baa0a5aSFrederic Weisbecker rb_insert_color(&th->rb_node, threads); 76*6baa0a5aSFrederic Weisbecker *last_match = th; 77*6baa0a5aSFrederic Weisbecker } 78*6baa0a5aSFrederic Weisbecker 79*6baa0a5aSFrederic Weisbecker return th; 80*6baa0a5aSFrederic Weisbecker } 81*6baa0a5aSFrederic Weisbecker 82*6baa0a5aSFrederic Weisbecker void thread__insert_map(struct thread *self, struct map *map) 83*6baa0a5aSFrederic Weisbecker { 84*6baa0a5aSFrederic Weisbecker struct map *pos, *tmp; 85*6baa0a5aSFrederic Weisbecker 86*6baa0a5aSFrederic Weisbecker list_for_each_entry_safe(pos, tmp, &self->maps, node) { 87*6baa0a5aSFrederic Weisbecker if (map__overlap(pos, map)) { 88*6baa0a5aSFrederic Weisbecker list_del_init(&pos->node); 89*6baa0a5aSFrederic Weisbecker /* XXX leaks dsos */ 90*6baa0a5aSFrederic Weisbecker free(pos); 91*6baa0a5aSFrederic Weisbecker } 92*6baa0a5aSFrederic Weisbecker } 93*6baa0a5aSFrederic Weisbecker 94*6baa0a5aSFrederic Weisbecker list_add_tail(&map->node, &self->maps); 95*6baa0a5aSFrederic Weisbecker } 96*6baa0a5aSFrederic Weisbecker 97*6baa0a5aSFrederic Weisbecker int thread__fork(struct thread *self, struct thread *parent) 98*6baa0a5aSFrederic Weisbecker { 99*6baa0a5aSFrederic Weisbecker struct map *map; 100*6baa0a5aSFrederic Weisbecker 101*6baa0a5aSFrederic Weisbecker if (self->comm) 102*6baa0a5aSFrederic Weisbecker free(self->comm); 103*6baa0a5aSFrederic Weisbecker self->comm = strdup(parent->comm); 104*6baa0a5aSFrederic Weisbecker if (!self->comm) 105*6baa0a5aSFrederic Weisbecker return -ENOMEM; 106*6baa0a5aSFrederic Weisbecker 107*6baa0a5aSFrederic Weisbecker list_for_each_entry(map, &parent->maps, node) { 108*6baa0a5aSFrederic Weisbecker struct map *new = map__clone(map); 109*6baa0a5aSFrederic Weisbecker if (!new) 110*6baa0a5aSFrederic Weisbecker return -ENOMEM; 111*6baa0a5aSFrederic Weisbecker thread__insert_map(self, new); 112*6baa0a5aSFrederic Weisbecker } 113*6baa0a5aSFrederic Weisbecker 114*6baa0a5aSFrederic Weisbecker return 0; 115*6baa0a5aSFrederic Weisbecker } 116*6baa0a5aSFrederic Weisbecker 117*6baa0a5aSFrederic Weisbecker struct map *thread__find_map(struct thread *self, u64 ip) 118*6baa0a5aSFrederic Weisbecker { 119*6baa0a5aSFrederic Weisbecker struct map *pos; 120*6baa0a5aSFrederic Weisbecker 121*6baa0a5aSFrederic Weisbecker if (self == NULL) 122*6baa0a5aSFrederic Weisbecker return NULL; 123*6baa0a5aSFrederic Weisbecker 124*6baa0a5aSFrederic Weisbecker list_for_each_entry(pos, &self->maps, node) 125*6baa0a5aSFrederic Weisbecker if (ip >= pos->start && ip <= pos->end) 126*6baa0a5aSFrederic Weisbecker return pos; 127*6baa0a5aSFrederic Weisbecker 128*6baa0a5aSFrederic Weisbecker return NULL; 129*6baa0a5aSFrederic Weisbecker } 130*6baa0a5aSFrederic Weisbecker 131*6baa0a5aSFrederic Weisbecker size_t threads__fprintf(FILE *fp, struct rb_root *threads) 132*6baa0a5aSFrederic Weisbecker { 133*6baa0a5aSFrederic Weisbecker size_t ret = 0; 134*6baa0a5aSFrederic Weisbecker struct rb_node *nd; 135*6baa0a5aSFrederic Weisbecker 136*6baa0a5aSFrederic Weisbecker for (nd = rb_first(threads); nd; nd = rb_next(nd)) { 137*6baa0a5aSFrederic Weisbecker struct thread *pos = rb_entry(nd, struct thread, rb_node); 138*6baa0a5aSFrederic Weisbecker 139*6baa0a5aSFrederic Weisbecker ret += thread__fprintf(pos, fp); 140*6baa0a5aSFrederic Weisbecker } 141*6baa0a5aSFrederic Weisbecker 142*6baa0a5aSFrederic Weisbecker return ret; 143*6baa0a5aSFrederic Weisbecker } 144