4 * LTTng adaptation layer for Linux kernel 3.15+ tracepoints.
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/mutex.h>
24 #include <linux/err.h>
25 #include <linux/notifier.h>
26 #include <linux/tracepoint.h>
27 #include <linux/slab.h>
28 #include <linux/jhash.h>
29 #include <linux/module.h>
31 #include <lttng-tracepoint.h>
32 #include <wrapper/list.h>
35 * Protect the tracepoint table. lttng_tracepoint_mutex nests within
36 * kernel/tracepoint.c tp_modlist_mutex. kernel/tracepoint.c
37 * tracepoint_mutex nests within lttng_tracepoint_mutex.
40 DEFINE_MUTEX(lttng_tracepoint_mutex
);
42 #define TRACEPOINT_HASH_BITS 6
43 #define TRACEPOINT_TABLE_SIZE (1 << TRACEPOINT_HASH_BITS)
45 struct hlist_head tracepoint_table
[TRACEPOINT_TABLE_SIZE
];
48 * The tracepoint entry is the node contained within the hash table. It
49 * is a mapping from the "string" key to the struct tracepoint pointer.
51 struct tracepoint_entry
{
52 struct hlist_node hlist
;
53 struct tracepoint
*tp
;
55 struct list_head probes
;
59 struct lttng_tp_probe
{
60 struct tracepoint_func tp_func
;
61 struct list_head list
;
65 int add_probe(struct tracepoint_entry
*e
, void *probe
, void *data
)
67 struct lttng_tp_probe
*p
;
70 list_for_each_entry(p
, &e
->probes
, list
) {
71 if (p
->tp_func
.func
== probe
&& p
->tp_func
.data
== data
) {
78 p
= kmalloc(sizeof(struct lttng_tp_probe
), GFP_KERNEL
);
81 p
->tp_func
.func
= probe
;
82 p
->tp_func
.data
= data
;
83 list_add(&p
->list
, &e
->probes
);
88 int remove_probe(struct tracepoint_entry
*e
, void *probe
, void *data
)
90 struct lttng_tp_probe
*p
;
93 list_for_each_entry(p
, &e
->probes
, list
) {
94 if (p
->tp_func
.func
== probe
&& p
->tp_func
.data
== data
) {
110 * Get tracepoint if the tracepoint is present in the tracepoint hash table.
111 * Must be called with lttng_tracepoint_mutex held.
112 * Returns NULL if not present.
115 struct tracepoint_entry
*get_tracepoint(const char *name
)
117 struct hlist_head
*head
;
118 struct tracepoint_entry
*e
;
119 u32 hash
= jhash(name
, strlen(name
), 0);
121 head
= &tracepoint_table
[hash
& (TRACEPOINT_TABLE_SIZE
- 1)];
122 lttng_hlist_for_each_entry(e
, head
, hlist
) {
123 if (!strcmp(name
, e
->name
))
130 * Add the tracepoint to the tracepoint hash table. Must be called with
131 * lttng_tracepoint_mutex held.
134 struct tracepoint_entry
*add_tracepoint(const char *name
)
136 struct hlist_head
*head
;
137 struct tracepoint_entry
*e
;
138 size_t name_len
= strlen(name
) + 1;
139 u32 hash
= jhash(name
, name_len
- 1, 0);
141 head
= &tracepoint_table
[hash
& (TRACEPOINT_TABLE_SIZE
- 1)];
142 lttng_hlist_for_each_entry(e
, head
, hlist
) {
143 if (!strcmp(name
, e
->name
)) {
145 "tracepoint %s busy\n", name
);
146 return ERR_PTR(-EEXIST
); /* Already there */
150 * Using kmalloc here to allocate a variable length element. Could
151 * cause some memory fragmentation if overused.
153 e
= kmalloc(sizeof(struct tracepoint_entry
) + name_len
, GFP_KERNEL
);
155 return ERR_PTR(-ENOMEM
);
156 memcpy(&e
->name
[0], name
, name_len
);
159 INIT_LIST_HEAD(&e
->probes
);
160 hlist_add_head(&e
->hlist
, head
);
165 * Remove the tracepoint from the tracepoint hash table. Must be called
166 * with lttng_tracepoint_mutex held.
169 void remove_tracepoint(struct tracepoint_entry
*e
)
171 hlist_del(&e
->hlist
);
175 int lttng_tracepoint_probe_register(const char *name
, void *probe
, void *data
)
177 struct tracepoint_entry
*e
;
180 mutex_lock(<tng_tracepoint_mutex
);
181 e
= get_tracepoint(name
);
183 e
= add_tracepoint(name
);
189 /* add (probe, data) to entry */
190 ret
= add_probe(e
, probe
, data
);
195 ret
= tracepoint_probe_register(e
->tp
, probe
, data
);
200 mutex_unlock(<tng_tracepoint_mutex
);
204 int lttng_tracepoint_probe_unregister(const char *name
, void *probe
, void *data
)
206 struct tracepoint_entry
*e
;
209 mutex_lock(<tng_tracepoint_mutex
);
210 e
= get_tracepoint(name
);
215 /* remove (probe, data) from entry */
216 ret
= remove_probe(e
, probe
, data
);
220 ret
= tracepoint_probe_unregister(e
->tp
, probe
, data
);
225 remove_tracepoint(e
);
227 mutex_unlock(<tng_tracepoint_mutex
);
231 #ifdef CONFIG_MODULES
234 int lttng_tracepoint_coming(struct tp_module
*tp_mod
)
238 mutex_lock(<tng_tracepoint_mutex
);
239 for (i
= 0; i
< tp_mod
->mod
->num_tracepoints
; i
++) {
240 struct tracepoint
*tp
;
241 struct tracepoint_entry
*e
;
242 struct lttng_tp_probe
*p
;
244 tp
= tp_mod
->mod
->tracepoints_ptrs
[i
];
245 e
= get_tracepoint(tp
->name
);
247 e
= add_tracepoint(tp
->name
);
249 pr_warn("LTTng: error (%ld) adding tracepoint\n",
254 /* If already enabled, just check consistency */
256 WARN_ON(e
->tp
!= tp
);
261 /* register each (probe, data) */
262 list_for_each_entry(p
, &e
->probes
, list
) {
265 ret
= tracepoint_probe_register(e
->tp
,
266 p
->tp_func
.func
, p
->tp_func
.data
);
270 mutex_unlock(<tng_tracepoint_mutex
);
275 int lttng_tracepoint_going(struct tp_module
*tp_mod
)
279 mutex_lock(<tng_tracepoint_mutex
);
280 for (i
= 0; i
< tp_mod
->mod
->num_tracepoints
; i
++) {
281 struct tracepoint
*tp
;
282 struct tracepoint_entry
*e
;
283 struct lttng_tp_probe
*p
;
285 tp
= tp_mod
->mod
->tracepoints_ptrs
[i
];
286 e
= get_tracepoint(tp
->name
);
289 /* unregister each (probe, data) */
290 list_for_each_entry(p
, &e
->probes
, list
) {
293 ret
= tracepoint_probe_unregister(e
->tp
,
294 p
->tp_func
.func
, p
->tp_func
.data
);
299 remove_tracepoint(e
);
301 mutex_unlock(<tng_tracepoint_mutex
);
306 int lttng_tracepoint_notify(struct notifier_block
*self
,
307 unsigned long val
, void *data
)
309 struct tp_module
*tp_mod
= data
;
313 case MODULE_STATE_COMING
:
314 ret
= lttng_tracepoint_coming(tp_mod
);
316 case MODULE_STATE_GOING
:
317 ret
= lttng_tracepoint_going(tp_mod
);
326 struct notifier_block lttng_tracepoint_notifier
= {
327 .notifier_call
= lttng_tracepoint_notify
,
332 int lttng_tracepoint_module_init(void)
334 return register_tracepoint_module_notifier(<tng_tracepoint_notifier
);
338 void lttng_tracepoint_module_exit(void)
340 WARN_ON(unregister_tracepoint_module_notifier(<tng_tracepoint_notifier
));
343 #else /* #ifdef CONFIG_MODULES */
346 int lttng_tracepoint_module_init(void)
352 void lttng_tracepoint_module_exit(void)
356 #endif /* #else #ifdef CONFIG_MODULES */
359 void lttng_kernel_tracepoint_add(struct tracepoint
*tp
, void *priv
)
361 struct tracepoint_entry
*e
;
362 struct lttng_tp_probe
*p
;
365 mutex_lock(<tng_tracepoint_mutex
);
366 e
= get_tracepoint(tp
->name
);
368 e
= add_tracepoint(tp
->name
);
370 pr_warn("LTTng: error (%ld) adding tracepoint\n",
372 *ret
= (int) PTR_ERR(e
);
376 /* If already enabled, just check consistency */
378 WARN_ON(e
->tp
!= tp
);
383 /* register each (probe, data) */
384 list_for_each_entry(p
, &e
->probes
, list
) {
387 ret
= tracepoint_probe_register(e
->tp
,
388 p
->tp_func
.func
, p
->tp_func
.data
);
392 mutex_unlock(<tng_tracepoint_mutex
);
396 void lttng_kernel_tracepoint_remove(struct tracepoint
*tp
, void *priv
)
398 struct tracepoint_entry
*e
;
401 mutex_lock(<tng_tracepoint_mutex
);
402 e
= get_tracepoint(tp
->name
);
403 if (!e
|| e
->refcount
!= 1 || !list_empty(&e
->probes
)) {
407 remove_tracepoint(e
);
409 mutex_unlock(<tng_tracepoint_mutex
);
412 int __init
lttng_tracepoint_init(void)
416 for_each_kernel_tracepoint(lttng_kernel_tracepoint_add
, &ret
);
419 ret
= lttng_tracepoint_module_init();
428 for_each_kernel_tracepoint(lttng_kernel_tracepoint_remove
,
436 void lttng_tracepoint_exit(void)
440 lttng_tracepoint_module_exit();
441 for_each_kernel_tracepoint(lttng_kernel_tracepoint_remove
, &ret
);
443 mutex_lock(<tng_tracepoint_mutex
);
444 for (i
= 0; i
< TRACEPOINT_TABLE_SIZE
; i
++) {
445 struct hlist_head
*head
= &tracepoint_table
[i
];
447 /* All tracepoints should be removed */
448 WARN_ON(!hlist_empty(head
));
450 mutex_unlock(<tng_tracepoint_mutex
);