2 * Copyright (C) 2007 Mathieu Desnoyers
4 * Dual LGPL v2.1/GPL v2 license.
7 #include <linux/module.h>
8 #include <linux/stat.h>
9 #include <linux/vmalloc.h>
10 #include <linux/marker.h>
11 #include <linux/uaccess.h>
12 #include <linux/string.h>
13 #include <linux/ctype.h>
14 #include <linux/list.h>
15 #include <linux/mutex.h>
16 #include <linux/seq_file.h>
17 #include <linux/slab.h>
19 #include "ltt-tracer.h"
21 #define DEFAULT_CHANNEL "cpu"
22 #define DEFAULT_PROBE "default"
24 LIST_HEAD(probes_list
);
27 * Mutex protecting the probe slab cache.
28 * Nests inside the traces mutex.
30 DEFINE_MUTEX(probes_mutex
);
32 struct ltt_available_probe default_probe
= {
35 .probe_func
= ltt_vtrace
,
36 .callbacks
[0] = ltt_serialize_data
,
39 static struct kmem_cache
*markers_loaded_cachep
;
40 static LIST_HEAD(markers_loaded_list
);
42 * List sorted by name strcmp order.
44 static LIST_HEAD(probes_registered_list
);
46 static struct ltt_available_probe
*get_probe_from_name(const char *pname
)
48 struct ltt_available_probe
*iter
;
49 int comparison
, found
= 0;
52 pname
= DEFAULT_PROBE
;
53 list_for_each_entry(iter
, &probes_registered_list
, node
) {
54 comparison
= strcmp(pname
, iter
->name
);
66 int ltt_probe_register(struct ltt_available_probe
*pdata
)
70 struct ltt_available_probe
*iter
;
72 mutex_lock(&probes_mutex
);
73 list_for_each_entry_reverse(iter
, &probes_registered_list
, node
) {
74 comparison
= strcmp(pdata
->name
, iter
->name
);
78 } else if (comparison
> 0) {
79 /* We belong to the location right after iter. */
80 list_add(&pdata
->node
, &iter
->node
);
84 /* Should be added at the head of the list */
85 list_add(&pdata
->node
, &probes_registered_list
);
87 mutex_unlock(&probes_mutex
);
90 EXPORT_SYMBOL_GPL(ltt_probe_register
);
93 * Called when a probe does not want to be called anymore.
95 int ltt_probe_unregister(struct ltt_available_probe
*pdata
)
98 struct ltt_active_marker
*amark
, *tmp
;
100 mutex_lock(&probes_mutex
);
101 list_for_each_entry_safe(amark
, tmp
, &markers_loaded_list
, node
) {
102 if (amark
->probe
== pdata
) {
103 ret
= marker_probe_unregister_private_data(
104 pdata
->probe_func
, amark
);
107 list_del(&amark
->node
);
108 kmem_cache_free(markers_loaded_cachep
, amark
);
111 list_del(&pdata
->node
);
113 mutex_unlock(&probes_mutex
);
116 EXPORT_SYMBOL_GPL(ltt_probe_unregister
);
119 * Connect marker "mname" to probe "pname".
120 * Only allow _only_ probe instance to be connected to a marker.
122 int ltt_marker_connect(const char *channel
, const char *mname
,
126 struct ltt_active_marker
*pdata
;
127 struct ltt_available_probe
*probe
;
130 mutex_lock(&probes_mutex
);
131 probe
= get_probe_from_name(pname
);
136 pdata
= marker_get_private_data(channel
, mname
, probe
->probe_func
, 0);
137 if (pdata
&& !IS_ERR(pdata
)) {
141 pdata
= kmem_cache_zalloc(markers_loaded_cachep
, GFP_KERNEL
);
146 pdata
->probe
= probe
;
148 * ID has priority over channel in case of conflict.
150 ret
= marker_probe_register(channel
, mname
, NULL
,
151 probe
->probe_func
, pdata
);
153 kmem_cache_free(markers_loaded_cachep
, pdata
);
155 list_add(&pdata
->node
, &markers_loaded_list
);
157 mutex_unlock(&probes_mutex
);
161 EXPORT_SYMBOL_GPL(ltt_marker_connect
);
164 * Disconnect marker "mname", probe "pname".
166 int ltt_marker_disconnect(const char *channel
, const char *mname
,
169 struct ltt_active_marker
*pdata
;
170 struct ltt_available_probe
*probe
;
173 mutex_lock(&probes_mutex
);
174 probe
= get_probe_from_name(pname
);
179 pdata
= marker_get_private_data(channel
, mname
, probe
->probe_func
, 0);
181 ret
= PTR_ERR(pdata
);
185 * Not registered by us.
190 ret
= marker_probe_unregister(channel
, mname
, probe
->probe_func
, pdata
);
194 list_del(&pdata
->node
);
195 kmem_cache_free(markers_loaded_cachep
, pdata
);
198 mutex_unlock(&probes_mutex
);
201 EXPORT_SYMBOL_GPL(ltt_marker_disconnect
);
203 static void disconnect_all_markers(void)
205 struct ltt_active_marker
*pdata
, *tmp
;
207 list_for_each_entry_safe(pdata
, tmp
, &markers_loaded_list
, node
) {
208 marker_probe_unregister_private_data(pdata
->probe
->probe_func
,
210 list_del(&pdata
->node
);
211 kmem_cache_free(markers_loaded_cachep
, pdata
);
215 static int __init
marker_control_init(void)
219 markers_loaded_cachep
= KMEM_CACHE(ltt_active_marker
, 0);
221 ret
= ltt_probe_register(&default_probe
);
223 ret
= ltt_marker_connect("metadata", "core_marker_format",
226 ret
= ltt_marker_connect("metadata", "core_marker_id", DEFAULT_PROBE
);
231 module_init(marker_control_init
);
233 static void __exit
marker_control_exit(void)
237 ret
= ltt_marker_disconnect("metadata", "core_marker_format",
240 ret
= ltt_marker_disconnect("metadata", "core_marker_id",
243 ret
= ltt_probe_unregister(&default_probe
);
245 disconnect_all_markers();
246 kmem_cache_destroy(markers_loaded_cachep
);
247 marker_synchronize_unregister();
249 module_exit(marker_control_exit
);
251 MODULE_LICENSE("GPL and additional rights");
252 MODULE_AUTHOR("Mathieu Desnoyers");
253 MODULE_DESCRIPTION("Linux Trace Toolkit Marker Control");