at v3.14 144 lines 3.0 kB view raw
1#include "../perf.h" 2#include <stdlib.h> 3#include <stdio.h> 4#include <string.h> 5#include "session.h" 6#include "thread.h" 7#include "util.h" 8#include "debug.h" 9#include "comm.h" 10 11struct thread *thread__new(pid_t pid, pid_t tid) 12{ 13 char *comm_str; 14 struct comm *comm; 15 struct thread *thread = zalloc(sizeof(*thread)); 16 17 if (thread != NULL) { 18 map_groups__init(&thread->mg); 19 thread->pid_ = pid; 20 thread->tid = tid; 21 thread->ppid = -1; 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); 35 } 36 37 return thread; 38 39err_thread: 40 free(thread); 41 return NULL; 42} 43 44void thread__delete(struct thread *thread) 45{ 46 struct comm *comm, *tmp; 47 48 map_groups__exit(&thread->mg); 49 list_for_each_entry_safe(comm, tmp, &thread->comm_list, list) { 50 list_del(&comm->list); 51 comm__free(comm); 52 } 53 54 free(thread); 55} 56 57struct comm *thread__comm(const struct thread *thread) 58{ 59 if (list_empty(&thread->comm_list)) 60 return NULL; 61 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 */ 66int thread__set_comm(struct thread *thread, const char *str, u64 timestamp) 67{ 68 struct comm *new, *curr = thread__comm(thread); 69 int err; 70 71 /* Override latest entry if it had no specific time coverage */ 72 if (!curr->start) { 73 err = comm__override(curr, str, timestamp); 74 if (err) 75 return err; 76 } else { 77 new = comm__new(str, timestamp); 78 if (!new) 79 return -ENOMEM; 80 list_add(&new->list, &thread->comm_list); 81 } 82 83 thread->comm_set = true; 84 85 return 0; 86} 87 88const char *thread__comm_str(const struct thread *thread) 89{ 90 const struct comm *comm = thread__comm(thread); 91 92 if (!comm) 93 return NULL; 94 95 return comm__str(comm); 96} 97 98/* CHECKME: it should probably better return the max comm len from its comm list */ 99int thread__comm_len(struct thread *thread) 100{ 101 if (!thread->comm_len) { 102 const char *comm = thread__comm_str(thread); 103 if (!comm) 104 return 0; 105 thread->comm_len = strlen(comm); 106 } 107 108 return thread->comm_len; 109} 110 111size_t thread__fprintf(struct thread *thread, FILE *fp) 112{ 113 return fprintf(fp, "Thread %d %s\n", thread->tid, thread__comm_str(thread)) + 114 map_groups__fprintf(&thread->mg, verbose, fp); 115} 116 117void thread__insert_map(struct thread *thread, struct map *map) 118{ 119 map_groups__fixup_overlappings(&thread->mg, map, verbose, stderr); 120 map_groups__insert(&thread->mg, map); 121} 122 123int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp) 124{ 125 int i, err; 126 127 if (parent->comm_set) { 128 const char *comm = thread__comm_str(parent); 129 if (!comm) 130 return -ENOMEM; 131 err = thread__set_comm(thread, comm, timestamp); 132 if (err) 133 return err; 134 thread->comm_set = true; 135 } 136 137 for (i = 0; i < MAP__NR_TYPES; ++i) 138 if (map_groups__clone(&thread->mg, &parent->mg, i) < 0) 139 return -ENOMEM; 140 141 thread->ppid = parent->tid; 142 143 return 0; 144}