2 * Copyright (C) 2007 Mathieu Desnoyers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 /* This file contains a high-level API for activating and deactivating ust_markers,
21 * and making sure ust_markers in a given library can be released when the library
29 #include "usterr_signal_safe.h"
31 #define DEFAULT_CHANNEL "cpu"
32 #define DEFAULT_PROBE "default"
34 static int initialized
;
36 CDS_LIST_HEAD(probes_list
);
39 * Mutex protecting the probe slab cache.
40 * Nests inside the traces mutex.
42 DEFINE_MUTEX(probes_mutex
);
44 struct ltt_available_probe default_probe
= {
47 .probe_func
= ltt_vtrace
,
48 .callbacks
[0] = ltt_serialize_data
,
51 //ust//static struct kmem_cache *ust_markers_loaded_cachep;
52 static CDS_LIST_HEAD(ust_markers_loaded_list
);
54 * List sorted by name strcmp order.
56 static CDS_LIST_HEAD(probes_registered_list
);
58 static struct ltt_available_probe
*get_probe_from_name(const char *pname
)
60 struct ltt_available_probe
*iter
;
61 int comparison
, found
= 0;
64 pname
= DEFAULT_PROBE
;
65 cds_list_for_each_entry(iter
, &probes_registered_list
, node
) {
66 comparison
= strcmp(pname
, iter
->name
);
79 static char *skip_spaces(char *buf)
81 while (*buf != '\0' && isspace(*buf))
86 static char *skip_nonspaces(char *buf)
88 while (*buf != '\0' && !isspace(*buf))
93 static void get_ust_marker_string(char *buf, char **start,
96 *start = skip_spaces(buf);
97 *end = skip_nonspaces(*start);
102 int ltt_probe_register(struct ltt_available_probe
*pdata
)
106 struct ltt_available_probe
*iter
;
108 pthread_mutex_lock(&probes_mutex
);
109 cds_list_for_each_entry_reverse(iter
, &probes_registered_list
, node
) {
110 comparison
= strcmp(pdata
->name
, iter
->name
);
114 } else if (comparison
> 0) {
115 /* We belong to the location right after iter. */
116 cds_list_add(&pdata
->node
, &iter
->node
);
120 /* Should be added at the head of the list */
121 cds_list_add(&pdata
->node
, &probes_registered_list
);
123 pthread_mutex_unlock(&probes_mutex
);
128 * Called when a probe does not want to be called anymore.
130 int ltt_probe_unregister(struct ltt_available_probe
*pdata
)
133 struct ltt_active_ust_marker
*amark
, *tmp
;
135 pthread_mutex_lock(&probes_mutex
);
136 cds_list_for_each_entry_safe(amark
, tmp
, &ust_markers_loaded_list
, node
) {
137 if (amark
->probe
== pdata
) {
138 ret
= ust_marker_probe_unregister_private_data(
139 pdata
->probe_func
, amark
);
142 cds_list_del(&amark
->node
);
146 cds_list_del(&pdata
->node
);
148 pthread_mutex_unlock(&probes_mutex
);
153 * Connect ust_marker "mname" to probe "pname".
154 * Only allow _only_ probe instance to be connected to a ust_marker.
156 int ltt_ust_marker_connect(const char *channel
, const char *mname
,
161 struct ltt_active_ust_marker
*pdata
;
162 struct ltt_available_probe
*probe
;
165 pthread_mutex_lock(&probes_mutex
);
166 probe
= get_probe_from_name(pname
);
171 pdata
= ust_marker_get_private_data(channel
, mname
, probe
->probe_func
, 0);
172 if (pdata
&& !IS_ERR(pdata
)) {
176 pdata
= zmalloc(sizeof(struct ltt_active_ust_marker
));
181 pdata
->probe
= probe
;
183 * ID has priority over channel in case of conflict.
185 ret
= ust_marker_probe_register(channel
, mname
, NULL
,
186 probe
->probe_func
, pdata
);
190 cds_list_add(&pdata
->node
, &ust_markers_loaded_list
);
192 pthread_mutex_unlock(&probes_mutex
);
198 * Disconnect ust_marker "mname", probe "pname".
200 int ltt_ust_marker_disconnect(const char *channel
, const char *mname
,
203 struct ltt_active_ust_marker
*pdata
;
204 struct ltt_available_probe
*probe
;
207 pthread_mutex_lock(&probes_mutex
);
208 probe
= get_probe_from_name(pname
);
213 pdata
= ust_marker_get_private_data(channel
, mname
, probe
->probe_func
, 0);
215 ret
= PTR_ERR(pdata
);
219 * Not registered by us.
224 ret
= ust_marker_probe_unregister(channel
, mname
, probe
->probe_func
, pdata
);
228 cds_list_del(&pdata
->node
);
232 pthread_mutex_unlock(&probes_mutex
);
236 static void disconnect_all_ust_markers(void)
238 struct ltt_active_ust_marker
*pdata
, *tmp
;
240 cds_list_for_each_entry_safe(pdata
, tmp
, &ust_markers_loaded_list
, node
) {
241 ust_marker_probe_unregister_private_data(pdata
->probe
->probe_func
,
243 cds_list_del(&pdata
->node
);
248 void __attribute__((constructor
)) init_ust_marker_control(void)
254 ret
= ltt_probe_register(&default_probe
);
256 ret
= ltt_ust_marker_connect("metadata", "core_marker_format",
259 ret
= ltt_ust_marker_connect("metadata", "core_marker_id", DEFAULT_PROBE
);
265 static void __attribute__((destructor
)) ust_marker_control_exit(void)
269 ret
= ltt_ust_marker_disconnect("metadata", "core_marker_format",
272 ret
= ltt_ust_marker_disconnect("metadata", "core_marker_id",
275 ret
= ltt_probe_unregister(&default_probe
);
277 disconnect_all_ust_markers();
278 ust_marker_synchronize_unregister();