diff options
| author | Olof Johansson <olof@lixom.net> | 2013-11-15 18:17:59 -0500 |
|---|---|---|
| committer | Olof Johansson <olof@lixom.net> | 2013-11-15 18:17:59 -0500 |
| commit | 6886059f2ef5d62c73e87a905e84fa4f87d56074 (patch) | |
| tree | dfe6e1611d7c50057df52db7b55eafbfb8e33a93 /tools/perf/util/thread.c | |
| parent | ca439c9b983ffa14e9eae6030e3ee80ad039388f (diff) | |
| parent | 26273e02a0cf18eb72416559310d3294390a9024 (diff) | |
Merge tag 'omap-for-v3.13/fixes-for-merge-window-take2' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap into fixes
Few clock fixes, a runtime PM fix, and pinctrl-single fix along
with few other fixes that popped up during the merge window.
* tag 'omap-for-v3.13/fixes-for-merge-window-take2' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap:
ARM: OMAP2+: Fix build for dra7xx without omap4 and 5
ARM: OMAP2+: omap_device: maintain sane runtime pm status around suspend/resume
doc: devicetree: Add bindings documentation for omap-des driver
ARM: dts: doc: Document missing compatible property for omap-sham driver
ARM: OMAP3: Beagle: fix return value check in beagle_opp_init()
ARM: OMAP: devicetree: fix SPI node compatible property syntax items
pinctrl: single: call pcs_soc->rearm() whenever IRQ mask is changed
ARM: OMAP2+: smsc911x: fix return value check in gpmc_smsc911x_init()
+ sync with newer trunk
Diffstat (limited to 'tools/perf/util/thread.c')
| -rw-r--r-- | tools/perf/util/thread.c | 137 |
1 files changed, 94 insertions, 43 deletions
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index e3d4a550a703..cd8e2f592719 100644 --- a/tools/perf/util/thread.c +++ b/tools/perf/util/thread.c | |||
| @@ -6,86 +6,137 @@ | |||
| 6 | #include "thread.h" | 6 | #include "thread.h" |
| 7 | #include "util.h" | 7 | #include "util.h" |
| 8 | #include "debug.h" | 8 | #include "debug.h" |
| 9 | #include "comm.h" | ||
| 9 | 10 | ||
| 10 | struct thread *thread__new(pid_t pid, pid_t tid) | 11 | struct thread *thread__new(pid_t pid, pid_t tid) |
| 11 | { | 12 | { |
| 12 | struct thread *self = zalloc(sizeof(*self)); | 13 | char *comm_str; |
| 13 | 14 | struct comm *comm; | |
| 14 | if (self != NULL) { | 15 | struct thread *thread = zalloc(sizeof(*thread)); |
| 15 | map_groups__init(&self->mg); | 16 | |
| 16 | self->pid_ = pid; | 17 | if (thread != NULL) { |
| 17 | self->tid = tid; | 18 | map_groups__init(&thread->mg); |
| 18 | self->ppid = -1; | 19 | thread->pid_ = pid; |
| 19 | self->comm = malloc(32); | 20 | thread->tid = tid; |
| 20 | if (self->comm) | 21 | thread->ppid = -1; |
| 21 | snprintf(self->comm, 32, ":%d", self->tid); | 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 | |||
| 39 | err_thread: | ||
| 40 | free(thread); | ||
| 41 | return NULL; | ||
| 42 | } | ||
| 43 | |||
| 44 | void 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); | ||
| 22 | } | 52 | } |
| 23 | 53 | ||
| 24 | return self; | 54 | free(thread); |
| 25 | } | 55 | } |
| 26 | 56 | ||
| 27 | void thread__delete(struct thread *self) | 57 | struct comm *thread__comm(const struct thread *thread) |
| 28 | { | 58 | { |
| 29 | map_groups__exit(&self->mg); | 59 | if (list_empty(&thread->comm_list)) |
| 30 | free(self->comm); | 60 | return NULL; |
| 31 | free(self); | 61 | |
| 62 | return list_first_entry(&thread->comm_list, struct comm, list); | ||
| 32 | } | 63 | } |
| 33 | 64 | ||
| 34 | int thread__set_comm(struct thread *self, const char *comm) | 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) | ||
| 35 | { | 67 | { |
| 36 | int err; | 68 | struct comm *new, *curr = thread__comm(thread); |
| 37 | 69 | ||
| 38 | if (self->comm) | 70 | /* Override latest entry if it had no specific time coverage */ |
| 39 | free(self->comm); | 71 | if (!curr->start) { |
| 40 | self->comm = strdup(comm); | 72 | comm__override(curr, str, timestamp); |
| 41 | err = self->comm == NULL ? -ENOMEM : 0; | 73 | return 0; |
| 42 | if (!err) { | ||
| 43 | self->comm_set = true; | ||
| 44 | } | 74 | } |
| 45 | return err; | 75 | |
| 76 | new = comm__new(str, timestamp); | ||
| 77 | if (!new) | ||
| 78 | return -ENOMEM; | ||
| 79 | |||
| 80 | list_add(&new->list, &thread->comm_list); | ||
| 81 | thread->comm_set = true; | ||
| 82 | |||
| 83 | return 0; | ||
| 84 | } | ||
| 85 | |||
| 86 | const char *thread__comm_str(const struct thread *thread) | ||
| 87 | { | ||
| 88 | const struct comm *comm = thread__comm(thread); | ||
| 89 | |||
| 90 | if (!comm) | ||
| 91 | return NULL; | ||
| 92 | |||
| 93 | return comm__str(comm); | ||
| 46 | } | 94 | } |
| 47 | 95 | ||
| 48 | int thread__comm_len(struct thread *self) | 96 | /* CHECKME: it should probably better return the max comm len from its comm list */ |
| 97 | int thread__comm_len(struct thread *thread) | ||
| 49 | { | 98 | { |
| 50 | if (!self->comm_len) { | 99 | if (!thread->comm_len) { |
| 51 | if (!self->comm) | 100 | const char *comm = thread__comm_str(thread); |
| 101 | if (!comm) | ||
| 52 | return 0; | 102 | return 0; |
| 53 | self->comm_len = strlen(self->comm); | 103 | thread->comm_len = strlen(comm); |
| 54 | } | 104 | } |
| 55 | 105 | ||
| 56 | return self->comm_len; | 106 | return thread->comm_len; |
| 57 | } | 107 | } |
| 58 | 108 | ||
| 59 | size_t thread__fprintf(struct thread *thread, FILE *fp) | 109 | size_t thread__fprintf(struct thread *thread, FILE *fp) |
| 60 | { | 110 | { |
| 61 | return fprintf(fp, "Thread %d %s\n", thread->tid, thread->comm) + | 111 | return fprintf(fp, "Thread %d %s\n", thread->tid, thread__comm_str(thread)) + |
| 62 | map_groups__fprintf(&thread->mg, verbose, fp); | 112 | map_groups__fprintf(&thread->mg, verbose, fp); |
| 63 | } | 113 | } |
| 64 | 114 | ||
| 65 | void thread__insert_map(struct thread *self, struct map *map) | 115 | void thread__insert_map(struct thread *thread, struct map *map) |
| 66 | { | 116 | { |
| 67 | map_groups__fixup_overlappings(&self->mg, map, verbose, stderr); | 117 | map_groups__fixup_overlappings(&thread->mg, map, verbose, stderr); |
| 68 | map_groups__insert(&self->mg, map); | 118 | map_groups__insert(&thread->mg, map); |
| 69 | } | 119 | } |
| 70 | 120 | ||
| 71 | int thread__fork(struct thread *self, struct thread *parent) | 121 | int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp) |
| 72 | { | 122 | { |
| 73 | int i; | 123 | int i, err; |
| 74 | 124 | ||
| 75 | if (parent->comm_set) { | 125 | if (parent->comm_set) { |
| 76 | if (self->comm) | 126 | const char *comm = thread__comm_str(parent); |
| 77 | free(self->comm); | 127 | if (!comm) |
| 78 | self->comm = strdup(parent->comm); | ||
| 79 | if (!self->comm) | ||
| 80 | return -ENOMEM; | 128 | return -ENOMEM; |
| 81 | self->comm_set = true; | 129 | err = thread__set_comm(thread, comm, timestamp); |
| 130 | if (!err) | ||
| 131 | return err; | ||
| 132 | thread->comm_set = true; | ||
| 82 | } | 133 | } |
| 83 | 134 | ||
| 84 | for (i = 0; i < MAP__NR_TYPES; ++i) | 135 | for (i = 0; i < MAP__NR_TYPES; ++i) |
| 85 | if (map_groups__clone(&self->mg, &parent->mg, i) < 0) | 136 | if (map_groups__clone(&thread->mg, &parent->mg, i) < 0) |
| 86 | return -ENOMEM; | 137 | return -ENOMEM; |
| 87 | 138 | ||
| 88 | self->ppid = parent->tid; | 139 | thread->ppid = parent->tid; |
| 89 | 140 | ||
| 90 | return 0; | 141 | return 0; |
| 91 | } | 142 | } |
