2 * Copyright (C) 2018 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
3 * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
5 * SPDX-License-Identifier: GPL-2.0-only
9 #include "common/dynamic-array.hpp"
10 #include "common/macros.hpp"
11 #include "lttng/tracker.h"
13 #include "tracker.hpp"
15 #include <common/defaults.hpp>
16 #include <common/error.hpp>
17 #include <common/hashtable/hashtable.hpp>
18 #include <common/hashtable/utils.hpp>
19 #include <common/tracker.hpp>
20 #include <common/urcu.hpp>
22 #include <lttng/lttng-error.h>
26 #include <sys/types.h>
29 #include <urcu/list.h>
30 #include <urcu/rculfhash.h>
32 struct process_attr_tracker
{
33 enum lttng_tracking_policy policy
;
34 struct cds_lfht
*inclusion_set_ht
;
38 struct process_attr_tracker_value_node
{
39 struct process_attr_value
*value
;
40 struct cds_lfht_node inclusion_set_ht_node
;
41 struct rcu_head rcu_head
;
45 static void process_attr_tracker_value_node_rcu_free(struct rcu_head
*rcu_head
)
47 struct process_attr_tracker_value_node
*node
=
48 lttng::utils::container_of(rcu_head
, &process_attr_tracker_value_node::rcu_head
);
53 struct process_attr_tracker
*process_attr_tracker_create()
55 struct process_attr_tracker
*tracker
;
57 tracker
= zmalloc
<process_attr_tracker
>();
62 (void) process_attr_tracker_set_tracking_policy(tracker
, LTTNG_TRACKING_POLICY_INCLUDE_ALL
);
64 tracker
->inclusion_set_ht
= cds_lfht_new(
65 DEFAULT_HT_SIZE
, 1, 0, CDS_LFHT_AUTO_RESIZE
| CDS_LFHT_ACCOUNTING
, nullptr);
66 if (!tracker
->inclusion_set_ht
) {
72 process_attr_tracker_destroy(tracker
);
77 process_attr_tracker_remove_value_node(struct process_attr_tracker
*tracker
,
78 struct process_attr_tracker_value_node
*value_node
)
80 cds_lfht_del(tracker
->inclusion_set_ht
, &value_node
->inclusion_set_ht_node
);
81 process_attr_value_destroy(value_node
->value
);
82 call_rcu(&value_node
->rcu_head
, process_attr_tracker_value_node_rcu_free
);
85 static void process_attr_tracker_clear_inclusion_set(struct process_attr_tracker
*tracker
)
88 struct lttng_ht_iter iter
;
89 struct process_attr_tracker_value_node
*value_node
;
91 if (!tracker
->inclusion_set_ht
) {
96 lttng::urcu::read_lock_guard read_lock
;
98 cds_lfht_for_each_entry (
99 tracker
->inclusion_set_ht
, &iter
.iter
, value_node
, inclusion_set_ht_node
) {
100 process_attr_tracker_remove_value_node(tracker
, value_node
);
104 ret
= cds_lfht_destroy(tracker
->inclusion_set_ht
, nullptr);
105 LTTNG_ASSERT(ret
== 0);
106 tracker
->inclusion_set_ht
= nullptr;
109 static int process_attr_tracker_create_inclusion_set(struct process_attr_tracker
*tracker
)
111 LTTNG_ASSERT(!tracker
->inclusion_set_ht
);
112 tracker
->inclusion_set_ht
= cds_lfht_new(
113 DEFAULT_HT_SIZE
, 1, 0, CDS_LFHT_AUTO_RESIZE
| CDS_LFHT_ACCOUNTING
, nullptr);
114 return tracker
->inclusion_set_ht
? 0 : -1;
117 void process_attr_tracker_destroy(struct process_attr_tracker
*tracker
)
123 process_attr_tracker_clear_inclusion_set(tracker
);
127 enum lttng_tracking_policy
128 process_attr_tracker_get_tracking_policy(const struct process_attr_tracker
*tracker
)
130 return tracker
->policy
;
133 int process_attr_tracker_set_tracking_policy(struct process_attr_tracker
*tracker
,
134 enum lttng_tracking_policy tracking_policy
)
138 if (tracker
->policy
== tracking_policy
) {
142 process_attr_tracker_clear_inclusion_set(tracker
);
143 ret
= process_attr_tracker_create_inclusion_set(tracker
);
147 tracker
->policy
= tracking_policy
;
152 static int match_inclusion_set_value(struct cds_lfht_node
*node
, const void *key
)
154 const struct process_attr_value
*value_key
= (process_attr_value
*) key
;
155 const struct process_attr_tracker_value_node
*value_node
= caa_container_of(
156 node
, struct process_attr_tracker_value_node
, inclusion_set_ht_node
);
158 return process_attr_tracker_value_equal(value_node
->value
, value_key
);
161 static struct process_attr_tracker_value_node
*
162 process_attr_tracker_lookup(const struct process_attr_tracker
*tracker
,
163 const struct process_attr_value
*value
)
165 struct cds_lfht_iter iter
;
166 struct cds_lfht_node
*node
;
168 LTTNG_ASSERT(tracker
->policy
== LTTNG_TRACKING_POLICY_INCLUDE_SET
);
170 lttng::urcu::read_lock_guard read_lock
;
171 cds_lfht_lookup(tracker
->inclusion_set_ht
,
172 process_attr_value_hash(value
),
173 match_inclusion_set_value
,
176 node
= cds_lfht_iter_get_node(&iter
);
178 return node
? lttng::utils::container_of(
179 node
, &process_attr_tracker_value_node::inclusion_set_ht_node
) :
183 /* Protected by session mutex held by caller. */
184 enum process_attr_tracker_status
185 process_attr_tracker_inclusion_set_add_value(struct process_attr_tracker
*tracker
,
186 const struct process_attr_value
*value
)
188 enum process_attr_tracker_status status
= PROCESS_ATTR_TRACKER_STATUS_OK
;
189 struct process_attr_value
*value_copy
= nullptr;
190 struct process_attr_tracker_value_node
*value_node
= nullptr;
192 lttng::urcu::read_lock_guard read_lock
;
193 if (tracker
->policy
!= LTTNG_TRACKING_POLICY_INCLUDE_SET
) {
194 status
= PROCESS_ATTR_TRACKER_STATUS_INVALID_TRACKING_POLICY
;
198 if (process_attr_tracker_lookup(tracker
, value
)) {
199 status
= PROCESS_ATTR_TRACKER_STATUS_EXISTS
;
203 value_node
= zmalloc
<process_attr_tracker_value_node
>();
205 status
= PROCESS_ATTR_TRACKER_STATUS_ERROR
;
209 value_copy
= process_attr_value_copy(value
);
211 status
= PROCESS_ATTR_TRACKER_STATUS_ERROR
;
215 value_node
->value
= value_copy
;
216 cds_lfht_add(tracker
->inclusion_set_ht
,
217 process_attr_value_hash(value_copy
),
218 &value_node
->inclusion_set_ht_node
);
219 value_copy
= nullptr;
220 value_node
= nullptr;
223 process_attr_value_destroy(value_copy
);
231 /* Protected by session mutex held by caller. */
232 enum process_attr_tracker_status
233 process_attr_tracker_inclusion_set_remove_value(struct process_attr_tracker
*tracker
,
234 const struct process_attr_value
*value
)
236 struct process_attr_tracker_value_node
*value_node
;
237 enum process_attr_tracker_status status
= PROCESS_ATTR_TRACKER_STATUS_OK
;
239 lttng::urcu::read_lock_guard read_lock
;
240 if (tracker
->policy
!= LTTNG_TRACKING_POLICY_INCLUDE_SET
) {
241 status
= PROCESS_ATTR_TRACKER_STATUS_INVALID_TRACKING_POLICY
;
245 value_node
= process_attr_tracker_lookup(tracker
, value
);
247 status
= PROCESS_ATTR_TRACKER_STATUS_MISSING
;
251 process_attr_tracker_remove_value_node(tracker
, value_node
);
256 enum process_attr_tracker_status
257 process_attr_tracker_get_inclusion_set(const struct process_attr_tracker
*tracker
,
258 struct lttng_process_attr_values
**_values
)
260 struct lttng_ht_iter iter
;
261 struct process_attr_tracker_value_node
*value_node
;
262 enum process_attr_tracker_status status
= PROCESS_ATTR_TRACKER_STATUS_OK
;
263 struct lttng_process_attr_values
*values
;
264 struct process_attr_value
*new_value
= nullptr;
266 values
= lttng_process_attr_values_create();
268 status
= PROCESS_ATTR_TRACKER_STATUS_ERROR
;
272 if (tracker
->policy
!= LTTNG_TRACKING_POLICY_INCLUDE_SET
) {
273 status
= PROCESS_ATTR_TRACKER_STATUS_INVALID_TRACKING_POLICY
;
278 lttng::urcu::read_lock_guard read_lock
;
280 cds_lfht_for_each_entry (
281 tracker
->inclusion_set_ht
, &iter
.iter
, value_node
, inclusion_set_ht_node
) {
284 new_value
= process_attr_value_copy(value_node
->value
);
286 status
= PROCESS_ATTR_TRACKER_STATUS_ERROR
;
290 ret
= lttng_dynamic_pointer_array_add_pointer(&values
->array
, new_value
);
292 status
= PROCESS_ATTR_TRACKER_STATUS_ERROR
;
304 lttng_process_attr_values_destroy(values
);
305 process_attr_value_destroy(new_value
);