1 // SPDX-License-Identifier: GPL-2.0
7 #include <linux/refcount.h>
8 #include <linux/rbtree.h>
9 #include <linux/zalloc.h>
14 struct rb_node rb_node
;
18 /* Should perhaps be moved to struct machine */
19 static struct rb_root comm_str_root
;
20 static struct rw_semaphore comm_str_lock
= {.lock
= PTHREAD_RWLOCK_INITIALIZER
,};
22 static struct comm_str
*comm_str__get(struct comm_str
*cs
)
24 if (cs
&& refcount_inc_not_zero(&cs
->refcnt
))
30 static void comm_str__put(struct comm_str
*cs
)
32 if (cs
&& refcount_dec_and_test(&cs
->refcnt
)) {
33 down_write(&comm_str_lock
);
34 rb_erase(&cs
->rb_node
, &comm_str_root
);
35 up_write(&comm_str_lock
);
41 static struct comm_str
*comm_str__alloc(const char *str
)
45 cs
= zalloc(sizeof(*cs
));
49 cs
->str
= strdup(str
);
55 refcount_set(&cs
->refcnt
, 1);
61 struct comm_str
*__comm_str__findnew(const char *str
, struct rb_root
*root
)
63 struct rb_node
**p
= &root
->rb_node
;
64 struct rb_node
*parent
= NULL
;
65 struct comm_str
*iter
, *new;
70 iter
= rb_entry(parent
, struct comm_str
, rb_node
);
73 * If we race with comm_str__put, iter->refcnt is 0
74 * and it will be removed within comm_str__put call
75 * shortly, ignore it in this search.
77 cmp
= strcmp(str
, iter
->str
);
78 if (!cmp
&& comm_str__get(iter
))
87 new = comm_str__alloc(str
);
91 rb_link_node(&new->rb_node
, parent
, p
);
92 rb_insert_color(&new->rb_node
, root
);
97 static struct comm_str
*comm_str__findnew(const char *str
, struct rb_root
*root
)
101 down_write(&comm_str_lock
);
102 cs
= __comm_str__findnew(str
, root
);
103 up_write(&comm_str_lock
);
108 struct comm
*comm__new(const char *str
, u64 timestamp
, bool exec
)
110 struct comm
*comm
= zalloc(sizeof(*comm
));
115 comm
->start
= timestamp
;
118 comm
->comm_str
= comm_str__findnew(str
, &comm_str_root
);
119 if (!comm
->comm_str
) {
127 int comm__override(struct comm
*comm
, const char *str
, u64 timestamp
, bool exec
)
129 struct comm_str
*new, *old
= comm
->comm_str
;
131 new = comm_str__findnew(str
, &comm_str_root
);
136 comm
->comm_str
= new;
137 comm
->start
= timestamp
;
144 void comm__free(struct comm
*comm
)
146 comm_str__put(comm
->comm_str
);
150 const char *comm__str(const struct comm
*comm
)
152 return comm
->comm_str
->str
;