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
)
87 if (!tracker
->inclusion_set_ht
) {
91 for (auto *value_node
: lttng::urcu::lfht_iteration_adapter
<
92 process_attr_tracker_value_node
,
93 decltype(process_attr_tracker_value_node::inclusion_set_ht_node
),
94 &process_attr_tracker_value_node::inclusion_set_ht_node
>(
95 *tracker
->inclusion_set_ht
)) {
96 process_attr_tracker_remove_value_node(tracker
, value_node
);
99 const auto ret
= cds_lfht_destroy(tracker
->inclusion_set_ht
, nullptr);
100 LTTNG_ASSERT(ret
== 0);
101 tracker
->inclusion_set_ht
= nullptr;
104 static int process_attr_tracker_create_inclusion_set(struct process_attr_tracker
*tracker
)
106 LTTNG_ASSERT(!tracker
->inclusion_set_ht
);
107 tracker
->inclusion_set_ht
= cds_lfht_new(
108 DEFAULT_HT_SIZE
, 1, 0, CDS_LFHT_AUTO_RESIZE
| CDS_LFHT_ACCOUNTING
, nullptr);
109 return tracker
->inclusion_set_ht
? 0 : -1;
112 void process_attr_tracker_destroy(struct process_attr_tracker
*tracker
)
118 process_attr_tracker_clear_inclusion_set(tracker
);
122 enum lttng_tracking_policy
123 process_attr_tracker_get_tracking_policy(const struct process_attr_tracker
*tracker
)
125 return tracker
->policy
;
128 int process_attr_tracker_set_tracking_policy(struct process_attr_tracker
*tracker
,
129 enum lttng_tracking_policy tracking_policy
)
133 if (tracker
->policy
== tracking_policy
) {
137 process_attr_tracker_clear_inclusion_set(tracker
);
138 ret
= process_attr_tracker_create_inclusion_set(tracker
);
142 tracker
->policy
= tracking_policy
;
147 static int match_inclusion_set_value(struct cds_lfht_node
*node
, const void *key
)
149 const struct process_attr_value
*value_key
= (process_attr_value
*) key
;
150 const struct process_attr_tracker_value_node
*value_node
= caa_container_of(
151 node
, struct process_attr_tracker_value_node
, inclusion_set_ht_node
);
153 return process_attr_tracker_value_equal(value_node
->value
, value_key
);
156 static struct process_attr_tracker_value_node
*
157 process_attr_tracker_lookup(const struct process_attr_tracker
*tracker
,
158 const struct process_attr_value
*value
)
160 struct cds_lfht_iter iter
;
161 struct cds_lfht_node
*node
;
163 LTTNG_ASSERT(tracker
->policy
== LTTNG_TRACKING_POLICY_INCLUDE_SET
);
165 const lttng::urcu::read_lock_guard read_lock
;
166 cds_lfht_lookup(tracker
->inclusion_set_ht
,
167 process_attr_value_hash(value
),
168 match_inclusion_set_value
,
171 node
= cds_lfht_iter_get_node(&iter
);
173 return node
? lttng::utils::container_of(
174 node
, &process_attr_tracker_value_node::inclusion_set_ht_node
) :
178 /* Protected by session mutex held by caller. */
179 enum process_attr_tracker_status
180 process_attr_tracker_inclusion_set_add_value(struct process_attr_tracker
*tracker
,
181 const struct process_attr_value
*value
)
183 enum process_attr_tracker_status status
= PROCESS_ATTR_TRACKER_STATUS_OK
;
184 struct process_attr_value
*value_copy
= nullptr;
185 struct process_attr_tracker_value_node
*value_node
= nullptr;
187 const lttng::urcu::read_lock_guard read_lock
;
188 if (tracker
->policy
!= LTTNG_TRACKING_POLICY_INCLUDE_SET
) {
189 status
= PROCESS_ATTR_TRACKER_STATUS_INVALID_TRACKING_POLICY
;
193 if (process_attr_tracker_lookup(tracker
, value
)) {
194 status
= PROCESS_ATTR_TRACKER_STATUS_EXISTS
;
198 value_node
= zmalloc
<process_attr_tracker_value_node
>();
200 status
= PROCESS_ATTR_TRACKER_STATUS_ERROR
;
204 value_copy
= process_attr_value_copy(value
);
206 status
= PROCESS_ATTR_TRACKER_STATUS_ERROR
;
210 value_node
->value
= value_copy
;
211 cds_lfht_add(tracker
->inclusion_set_ht
,
212 process_attr_value_hash(value_copy
),
213 &value_node
->inclusion_set_ht_node
);
214 value_copy
= nullptr;
215 value_node
= nullptr;
218 process_attr_value_destroy(value_copy
);
226 /* Protected by session mutex held by caller. */
227 enum process_attr_tracker_status
228 process_attr_tracker_inclusion_set_remove_value(struct process_attr_tracker
*tracker
,
229 const struct process_attr_value
*value
)
231 struct process_attr_tracker_value_node
*value_node
;
232 enum process_attr_tracker_status status
= PROCESS_ATTR_TRACKER_STATUS_OK
;
234 const lttng::urcu::read_lock_guard read_lock
;
235 if (tracker
->policy
!= LTTNG_TRACKING_POLICY_INCLUDE_SET
) {
236 status
= PROCESS_ATTR_TRACKER_STATUS_INVALID_TRACKING_POLICY
;
240 value_node
= process_attr_tracker_lookup(tracker
, value
);
242 status
= PROCESS_ATTR_TRACKER_STATUS_MISSING
;
246 process_attr_tracker_remove_value_node(tracker
, value_node
);
251 enum process_attr_tracker_status
252 process_attr_tracker_get_inclusion_set(const struct process_attr_tracker
*tracker
,
253 struct lttng_process_attr_values
**_values
)
255 enum process_attr_tracker_status status
= PROCESS_ATTR_TRACKER_STATUS_OK
;
256 struct lttng_process_attr_values
*values
;
257 struct process_attr_value
*new_value
= nullptr;
259 values
= lttng_process_attr_values_create();
261 status
= PROCESS_ATTR_TRACKER_STATUS_ERROR
;
265 if (tracker
->policy
!= LTTNG_TRACKING_POLICY_INCLUDE_SET
) {
266 status
= PROCESS_ATTR_TRACKER_STATUS_INVALID_TRACKING_POLICY
;
270 for (auto *value_node
: lttng::urcu::lfht_iteration_adapter
<
271 process_attr_tracker_value_node
,
272 decltype(process_attr_tracker_value_node::inclusion_set_ht_node
),
273 &process_attr_tracker_value_node::inclusion_set_ht_node
>(
274 *tracker
->inclusion_set_ht
)) {
277 new_value
= process_attr_value_copy(value_node
->value
);
279 status
= PROCESS_ATTR_TRACKER_STATUS_ERROR
;
283 ret
= lttng_dynamic_pointer_array_add_pointer(&values
->array
, new_value
);
285 status
= PROCESS_ATTR_TRACKER_STATUS_ERROR
;
296 lttng_process_attr_values_destroy(values
);
297 process_attr_value_destroy(new_value
);