4 * LTTng Process ID trackering.
6 * Copyright (C) 2014 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; only
11 * version 2.1 of the License.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 #include <linux/module.h>
24 #include <linux/slab.h>
25 #include <linux/err.h>
26 #include <linux/seq_file.h>
27 #include <linux/stringify.h>
28 #include <linux/hash.h>
29 #include <linux/rcupdate.h>
31 #include <wrapper/tracepoint.h>
32 #include <wrapper/rcu.h>
33 #include <wrapper/list.h>
34 #include <lttng-events.h>
37 * Hash table is allocated and freed when there are no possible
38 * concurrent lookups (ensured by the alloc/free caller). However,
39 * there can be concurrent RCU lookups vs add/del operations.
41 * Concurrent updates of the PID hash table are forbidden: the caller
42 * must ensure mutual exclusion. This is currently done by holding the
43 * sessions_mutex across calls to create, destroy, add, and del
44 * functions of this API.
46 int lttng_id_tracker_get_node_id(const struct lttng_id_hash_node
*node
)
52 * Lookup performed from RCU read-side critical section (RCU sched),
53 * protected by preemption off at the tracepoint call site.
54 * Return true if found, false if not found.
56 bool lttng_id_tracker_lookup(struct lttng_id_tracker_rcu
*p
, int id
)
58 struct hlist_head
*head
;
59 struct lttng_id_hash_node
*e
;
60 uint32_t hash
= hash_32(id
, 32);
62 head
= &p
->id_hash
[hash
& (LTTNG_ID_TABLE_SIZE
- 1)];
63 lttng_hlist_for_each_entry_rcu(e
, head
, hlist
) {
65 return true; /* Found */
69 EXPORT_SYMBOL_GPL(lttng_id_tracker_lookup
);
71 static struct lttng_id_tracker_rcu
*lttng_id_tracker_rcu_create(void)
73 struct lttng_id_tracker_rcu
*tracker
;
75 tracker
= kzalloc(sizeof(struct lttng_id_tracker_rcu
), GFP_KERNEL
);
82 * Tracker add and del operations support concurrent RCU lookups.
84 int lttng_id_tracker_add(struct lttng_id_tracker
*lf
, int id
)
86 struct hlist_head
*head
;
87 struct lttng_id_hash_node
*e
;
88 struct lttng_id_tracker_rcu
*p
= lf
->p
;
89 uint32_t hash
= hash_32(id
, 32);
90 bool allocated
= false;
93 p
= lttng_id_tracker_rcu_create();
98 head
= &p
->id_hash
[hash
& (LTTNG_ID_TABLE_SIZE
- 1)];
99 lttng_hlist_for_each_entry(e
, head
, hlist
) {
103 e
= kmalloc(sizeof(struct lttng_id_hash_node
), GFP_KERNEL
);
107 hlist_add_head_rcu(&e
->hlist
, head
);
109 rcu_assign_pointer(lf
->p
, p
);
115 void id_tracker_del_node_rcu(struct lttng_id_hash_node
*e
)
117 hlist_del_rcu(&e
->hlist
);
119 * We choose to use a heavyweight synchronize on removal here,
120 * since removal of an ID from the tracker mask is a rare
121 * operation, and we don't want to use more cache lines than
122 * what we really need when doing the ID lookups, so we don't
123 * want to afford adding a rcu_head field to those pid hash
131 * This removal is only used on destroy, so it does not need to support
132 * concurrent RCU lookups.
135 void id_tracker_del_node(struct lttng_id_hash_node
*e
)
137 hlist_del(&e
->hlist
);
141 int lttng_id_tracker_del(struct lttng_id_tracker
*lf
, int id
)
143 struct hlist_head
*head
;
144 struct lttng_id_hash_node
*e
;
145 struct lttng_id_tracker_rcu
*p
= lf
->p
;
146 uint32_t hash
= hash_32(id
, 32);
150 head
= &p
->id_hash
[hash
& (LTTNG_ID_TABLE_SIZE
- 1)];
152 * No need of _safe iteration, because we stop traversal as soon
153 * as we remove the entry.
155 lttng_hlist_for_each_entry(e
, head
, hlist
) {
157 id_tracker_del_node_rcu(e
);
161 return -ENOENT
; /* Not found */
164 static void lttng_id_tracker_rcu_destroy(struct lttng_id_tracker_rcu
*p
)
170 for (i
= 0; i
< LTTNG_ID_TABLE_SIZE
; i
++) {
171 struct hlist_head
*head
= &p
->id_hash
[i
];
172 struct lttng_id_hash_node
*e
;
173 struct hlist_node
*tmp
;
175 lttng_hlist_for_each_entry_safe(e
, tmp
, head
, hlist
)
176 id_tracker_del_node(e
);
181 int lttng_id_tracker_empty_set(struct lttng_id_tracker
*lf
)
183 struct lttng_id_tracker_rcu
*p
, *oldp
;
185 p
= lttng_id_tracker_rcu_create();
189 rcu_assign_pointer(lf
->p
, p
);
191 lttng_id_tracker_rcu_destroy(oldp
);
195 void lttng_id_tracker_destroy(struct lttng_id_tracker
*lf
, bool rcu
)
197 struct lttng_id_tracker_rcu
*p
= lf
->p
;
201 rcu_assign_pointer(lf
->p
, NULL
);
204 lttng_id_tracker_rcu_destroy(p
);
This page took 0.036126 seconds and 5 git commands to generate.