1 /* SPDX-License-Identifier: (GPL-2.0 or LGPL-2.1)
5 * LTTng Process ID tracking.
7 * Copyright (C) 2014 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
10 #include <linux/module.h>
11 #include <linux/slab.h>
12 #include <linux/err.h>
13 #include <linux/seq_file.h>
14 #include <linux/stringify.h>
15 #include <linux/hash.h>
16 #include <linux/rcupdate.h>
18 #include <wrapper/tracepoint.h>
19 #include <wrapper/rcu.h>
20 #include <wrapper/list.h>
21 #include <lttng-events.h>
24 * Hash table is allocated and freed when there are no possible
25 * concurrent lookups (ensured by the alloc/free caller). However,
26 * there can be concurrent RCU lookups vs add/del operations.
28 * Concurrent updates of the PID hash table are forbidden: the caller
29 * must ensure mutual exclusion. This is currently done by holding the
30 * sessions_mutex across calls to create, destroy, add, and del
31 * functions of this API.
33 int lttng_pid_tracker_get_node_pid(const struct lttng_pid_hash_node
*node
)
39 * Lookup performed from RCU read-side critical section (RCU sched),
40 * protected by preemption off at the tracepoint call site.
41 * Return 1 if found, 0 if not found.
43 bool lttng_pid_tracker_lookup(struct lttng_pid_tracker
*lpf
, int pid
)
45 struct hlist_head
*head
;
46 struct lttng_pid_hash_node
*e
;
47 uint32_t hash
= hash_32(pid
, 32);
49 head
= &lpf
->pid_hash
[hash
& (LTTNG_PID_TABLE_SIZE
- 1)];
50 lttng_hlist_for_each_entry_rcu(e
, head
, hlist
) {
56 EXPORT_SYMBOL_GPL(lttng_pid_tracker_lookup
);
59 * Tracker add and del operations support concurrent RCU lookups.
61 int lttng_pid_tracker_add(struct lttng_pid_tracker
*lpf
, int pid
)
63 struct hlist_head
*head
;
64 struct lttng_pid_hash_node
*e
;
65 uint32_t hash
= hash_32(pid
, 32);
67 head
= &lpf
->pid_hash
[hash
& (LTTNG_PID_TABLE_SIZE
- 1)];
68 lttng_hlist_for_each_entry(e
, head
, hlist
) {
72 e
= kmalloc(sizeof(struct lttng_pid_hash_node
), GFP_KERNEL
);
76 hlist_add_head_rcu(&e
->hlist
, head
);
81 void pid_tracker_del_node_rcu(struct lttng_pid_hash_node
*e
)
83 hlist_del_rcu(&e
->hlist
);
85 * We choose to use a heavyweight synchronize on removal here,
86 * since removal of a PID from the tracker mask is a rare
87 * operation, and we don't want to use more cache lines than
88 * what we really need when doing the PID lookups, so we don't
89 * want to afford adding a rcu_head field to those pid hash
97 * This removal is only used on destroy, so it does not need to support
98 * concurrent RCU lookups.
101 void pid_tracker_del_node(struct lttng_pid_hash_node
*e
)
103 hlist_del(&e
->hlist
);
107 int lttng_pid_tracker_del(struct lttng_pid_tracker
*lpf
, int pid
)
109 struct hlist_head
*head
;
110 struct lttng_pid_hash_node
*e
;
111 uint32_t hash
= hash_32(pid
, 32);
113 head
= &lpf
->pid_hash
[hash
& (LTTNG_PID_TABLE_SIZE
- 1)];
115 * No need of _safe iteration, because we stop traversal as soon
116 * as we remove the entry.
118 lttng_hlist_for_each_entry(e
, head
, hlist
) {
120 pid_tracker_del_node_rcu(e
);
124 return -ENOENT
; /* Not found */
127 struct lttng_pid_tracker
*lttng_pid_tracker_create(void)
129 return kzalloc(sizeof(struct lttng_pid_tracker
), GFP_KERNEL
);
132 void lttng_pid_tracker_destroy(struct lttng_pid_tracker
*lpf
)
136 for (i
= 0; i
< LTTNG_PID_TABLE_SIZE
; i
++) {
137 struct hlist_head
*head
= &lpf
->pid_hash
[i
];
138 struct lttng_pid_hash_node
*e
;
139 struct hlist_node
*tmp
;
141 lttng_hlist_for_each_entry_safe(e
, tmp
, head
, hlist
)
142 pid_tracker_del_node(e
);
This page took 0.047507 seconds and 4 git commands to generate.