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