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
,
127 struct ltt_active_marker
*pdata
;
128 struct ltt_available_probe
*probe
;
131 mutex_lock(&probes_mutex
);
132 probe
= get_probe_from_name(pname
);
137 pdata
= marker_get_private_data(channel
, mname
, probe
->probe_func
, 0);
138 if (pdata
&& !IS_ERR(pdata
)) {
142 pdata
= kmem_cache_zalloc(markers_loaded_cachep
, GFP_KERNEL
);
147 pdata
->probe
= probe
;
149 * ID has priority over channel in case of conflict.
151 ret
= marker_probe_register(channel
, mname
, NULL
,
152 probe
->probe_func
, pdata
);
154 kmem_cache_free(markers_loaded_cachep
, pdata
);
156 list_add(&pdata
->node
, &markers_loaded_list
);
158 mutex_unlock(&probes_mutex
);
162 EXPORT_SYMBOL_GPL(ltt_marker_connect
);
165 * Disconnect marker "mname", probe "pname".
167 int ltt_marker_disconnect(const char *channel
, const char *mname
,
170 struct ltt_active_marker
*pdata
;
171 struct ltt_available_probe
*probe
;
174 mutex_lock(&probes_mutex
);
175 probe
= get_probe_from_name(pname
);
180 pdata
= marker_get_private_data(channel
, mname
, probe
->probe_func
, 0);
182 ret
= PTR_ERR(pdata
);
186 * Not registered by us.
191 ret
= marker_probe_unregister(channel
, mname
, probe
->probe_func
, pdata
);
195 list_del(&pdata
->node
);
196 kmem_cache_free(markers_loaded_cachep
, pdata
);
199 mutex_unlock(&probes_mutex
);
202 EXPORT_SYMBOL_GPL(ltt_marker_disconnect
);
204 static void disconnect_all_markers(void)
206 struct ltt_active_marker
*pdata
, *tmp
;
208 list_for_each_entry_safe(pdata
, tmp
, &markers_loaded_list
, node
) {
209 marker_probe_unregister_private_data(pdata
->probe
->probe_func
,
211 list_del(&pdata
->node
);
212 kmem_cache_free(markers_loaded_cachep
, pdata
);
216 static int __init
marker_control_init(void)
220 markers_loaded_cachep
= KMEM_CACHE(ltt_active_marker
, 0);
222 ret
= ltt_probe_register(&default_probe
);
224 ret
= ltt_marker_connect("metadata", "core_marker_format",
227 ret
= ltt_marker_connect("metadata", "core_marker_id", DEFAULT_PROBE
);
232 module_init(marker_control_init
);
234 static void __exit
marker_control_exit(void)
238 ret
= ltt_marker_disconnect("metadata", "core_marker_format",
241 ret
= ltt_marker_disconnect("metadata", "core_marker_id",
244 ret
= ltt_probe_unregister(&default_probe
);
246 disconnect_all_markers();
247 kmem_cache_destroy(markers_loaded_cachep
);
248 marker_synchronize_unregister();
250 module_exit(marker_control_exit
);
252 MODULE_LICENSE("GPL and additional rights");
253 MODULE_AUTHOR("Mathieu Desnoyers");
254 MODULE_DESCRIPTION("Linux Trace Toolkit Marker Control");