xref: /openbmc/linux/tools/perf/util/comm.c (revision 8b036556)
1 #include "comm.h"
2 #include "util.h"
3 #include <stdlib.h>
4 #include <stdio.h>
5 
6 struct comm_str {
7 	char *str;
8 	struct rb_node rb_node;
9 	int ref;
10 };
11 
12 /* Should perhaps be moved to struct machine */
13 static struct rb_root comm_str_root;
14 
15 static void comm_str__get(struct comm_str *cs)
16 {
17 	cs->ref++;
18 }
19 
20 static void comm_str__put(struct comm_str *cs)
21 {
22 	if (!--cs->ref) {
23 		rb_erase(&cs->rb_node, &comm_str_root);
24 		zfree(&cs->str);
25 		free(cs);
26 	}
27 }
28 
29 static struct comm_str *comm_str__alloc(const char *str)
30 {
31 	struct comm_str *cs;
32 
33 	cs = zalloc(sizeof(*cs));
34 	if (!cs)
35 		return NULL;
36 
37 	cs->str = strdup(str);
38 	if (!cs->str) {
39 		free(cs);
40 		return NULL;
41 	}
42 
43 	return cs;
44 }
45 
46 static struct comm_str *comm_str__findnew(const char *str, struct rb_root *root)
47 {
48 	struct rb_node **p = &root->rb_node;
49 	struct rb_node *parent = NULL;
50 	struct comm_str *iter, *new;
51 	int cmp;
52 
53 	while (*p != NULL) {
54 		parent = *p;
55 		iter = rb_entry(parent, struct comm_str, rb_node);
56 
57 		cmp = strcmp(str, iter->str);
58 		if (!cmp)
59 			return iter;
60 
61 		if (cmp < 0)
62 			p = &(*p)->rb_left;
63 		else
64 			p = &(*p)->rb_right;
65 	}
66 
67 	new = comm_str__alloc(str);
68 	if (!new)
69 		return NULL;
70 
71 	rb_link_node(&new->rb_node, parent, p);
72 	rb_insert_color(&new->rb_node, root);
73 
74 	return new;
75 }
76 
77 struct comm *comm__new(const char *str, u64 timestamp, bool exec)
78 {
79 	struct comm *comm = zalloc(sizeof(*comm));
80 
81 	if (!comm)
82 		return NULL;
83 
84 	comm->start = timestamp;
85 	comm->exec = exec;
86 
87 	comm->comm_str = comm_str__findnew(str, &comm_str_root);
88 	if (!comm->comm_str) {
89 		free(comm);
90 		return NULL;
91 	}
92 
93 	comm_str__get(comm->comm_str);
94 
95 	return comm;
96 }
97 
98 int comm__override(struct comm *comm, const char *str, u64 timestamp, bool exec)
99 {
100 	struct comm_str *new, *old = comm->comm_str;
101 
102 	new = comm_str__findnew(str, &comm_str_root);
103 	if (!new)
104 		return -ENOMEM;
105 
106 	comm_str__get(new);
107 	comm_str__put(old);
108 	comm->comm_str = new;
109 	comm->start = timestamp;
110 	if (exec)
111 		comm->exec = true;
112 
113 	return 0;
114 }
115 
116 void comm__free(struct comm *comm)
117 {
118 	comm_str__put(comm->comm_str);
119 	free(comm);
120 }
121 
122 const char *comm__str(const struct comm *comm)
123 {
124 	return comm->comm_str->str;
125 }
126