Update version to 0.16
[ust.git] / libust / marker-control.c
CommitLineData
ba6459ba
PMF
1/*
2 * Copyright (C) 2007 Mathieu Desnoyers
3 *
34e4b7db
PMF
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.
ba6459ba 8 *
34e4b7db 9 * This library is distributed in the hope that it will be useful,
ba6459ba 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
34e4b7db
PMF
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
ba6459ba 13 *
34e4b7db
PMF
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
ba6459ba 17 *
93e5ce29
PMF
18 */
19
b521931e
MD
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
93e5ce29 22 * is unloaded.
ba6459ba
PMF
23 */
24
772030fe 25#include <ctype.h>
909bc43f 26#include <stdlib.h>
772030fe 27
c93858f1 28#include "tracer.h"
30ffe279 29#include "usterr_signal_safe.h"
ba6459ba
PMF
30
31#define DEFAULT_CHANNEL "cpu"
32#define DEFAULT_PROBE "default"
33
d4d511d9
MD
34static int initialized;
35
0222e121 36CDS_LIST_HEAD(probes_list);
ba6459ba
PMF
37
38/*
39 * Mutex protecting the probe slab cache.
40 * Nests inside the traces mutex.
41 */
42DEFINE_MUTEX(probes_mutex);
43
44struct ltt_available_probe default_probe = {
45 .name = "default",
46 .format = NULL,
47 .probe_func = ltt_vtrace,
48 .callbacks[0] = ltt_serialize_data,
49};
50
b521931e
MD
51//ust//static struct kmem_cache *ust_markers_loaded_cachep;
52static CDS_LIST_HEAD(ust_markers_loaded_list);
ba6459ba
PMF
53/*
54 * List sorted by name strcmp order.
55 */
0222e121 56static CDS_LIST_HEAD(probes_registered_list);
ba6459ba 57
ba6459ba
PMF
58static struct ltt_available_probe *get_probe_from_name(const char *pname)
59{
60 struct ltt_available_probe *iter;
61 int comparison, found = 0;
62
63 if (!pname)
64 pname = DEFAULT_PROBE;
0222e121 65 cds_list_for_each_entry(iter, &probes_registered_list, node) {
ba6459ba
PMF
66 comparison = strcmp(pname, iter->name);
67 if (!comparison)
68 found = 1;
69 if (comparison <= 0)
70 break;
71 }
72 if (found)
73 return iter;
74 else
75 return NULL;
76}
77
772030fe 78/* (unused)
ba6459ba
PMF
79static char *skip_spaces(char *buf)
80{
81 while (*buf != '\0' && isspace(*buf))
82 buf++;
83 return buf;
84}
85
86static char *skip_nonspaces(char *buf)
87{
88 while (*buf != '\0' && !isspace(*buf))
89 buf++;
90 return buf;
91}
92
b521931e 93static void get_ust_marker_string(char *buf, char **start,
ba6459ba
PMF
94 char **end)
95{
96 *start = skip_spaces(buf);
97 *end = skip_nonspaces(*start);
98 **end = '\0';
99}
772030fe 100*/
ba6459ba
PMF
101
102int ltt_probe_register(struct ltt_available_probe *pdata)
103{
104 int ret = 0;
105 int comparison;
106 struct ltt_available_probe *iter;
107
f7b16408 108 pthread_mutex_lock(&probes_mutex);
0222e121 109 cds_list_for_each_entry_reverse(iter, &probes_registered_list, node) {
ba6459ba
PMF
110 comparison = strcmp(pdata->name, iter->name);
111 if (!comparison) {
112 ret = -EBUSY;
113 goto end;
114 } else if (comparison > 0) {
115 /* We belong to the location right after iter. */
0222e121 116 cds_list_add(&pdata->node, &iter->node);
ba6459ba
PMF
117 goto end;
118 }
119 }
120 /* Should be added at the head of the list */
0222e121 121 cds_list_add(&pdata->node, &probes_registered_list);
ba6459ba 122end:
f7b16408 123 pthread_mutex_unlock(&probes_mutex);
ba6459ba
PMF
124 return ret;
125}
ba6459ba
PMF
126
127/*
128 * Called when a probe does not want to be called anymore.
129 */
130int ltt_probe_unregister(struct ltt_available_probe *pdata)
131{
132 int ret = 0;
b521931e 133 struct ltt_active_ust_marker *amark, *tmp;
ba6459ba 134
f7b16408 135 pthread_mutex_lock(&probes_mutex);
b521931e 136 cds_list_for_each_entry_safe(amark, tmp, &ust_markers_loaded_list, node) {
ba6459ba 137 if (amark->probe == pdata) {
b521931e 138 ret = ust_marker_probe_unregister_private_data(
ba6459ba
PMF
139 pdata->probe_func, amark);
140 if (ret)
141 goto end;
0222e121 142 cds_list_del(&amark->node);
ba6459ba
PMF
143 free(amark);
144 }
145 }
0222e121 146 cds_list_del(&pdata->node);
ba6459ba 147end:
f7b16408 148 pthread_mutex_unlock(&probes_mutex);
ba6459ba
PMF
149 return ret;
150}
ba6459ba
PMF
151
152/*
b521931e
MD
153 * Connect ust_marker "mname" to probe "pname".
154 * Only allow _only_ probe instance to be connected to a ust_marker.
ba6459ba 155 */
b521931e 156int ltt_ust_marker_connect(const char *channel, const char *mname,
ba6459ba
PMF
157 const char *pname)
158
159{
160 int ret;
b521931e 161 struct ltt_active_ust_marker *pdata;
ba6459ba
PMF
162 struct ltt_available_probe *probe;
163
164 ltt_lock_traces();
f7b16408 165 pthread_mutex_lock(&probes_mutex);
ba6459ba
PMF
166 probe = get_probe_from_name(pname);
167 if (!probe) {
168 ret = -ENOENT;
169 goto end;
170 }
b521931e 171 pdata = ust_marker_get_private_data(channel, mname, probe->probe_func, 0);
ba6459ba
PMF
172 if (pdata && !IS_ERR(pdata)) {
173 ret = -EEXIST;
174 goto end;
175 }
b521931e 176 pdata = zmalloc(sizeof(struct ltt_active_ust_marker));
ba6459ba
PMF
177 if (!pdata) {
178 ret = -ENOMEM;
179 goto end;
180 }
181 pdata->probe = probe;
182 /*
183 * ID has priority over channel in case of conflict.
184 */
b521931e 185 ret = ust_marker_probe_register(channel, mname, NULL,
ba6459ba
PMF
186 probe->probe_func, pdata);
187 if (ret)
188 free(pdata);
189 else
b521931e 190 cds_list_add(&pdata->node, &ust_markers_loaded_list);
ba6459ba 191end:
f7b16408 192 pthread_mutex_unlock(&probes_mutex);
ba6459ba
PMF
193 ltt_unlock_traces();
194 return ret;
195}
ba6459ba
PMF
196
197/*
b521931e 198 * Disconnect ust_marker "mname", probe "pname".
ba6459ba 199 */
b521931e 200int ltt_ust_marker_disconnect(const char *channel, const char *mname,
ba6459ba
PMF
201 const char *pname)
202{
b521931e 203 struct ltt_active_ust_marker *pdata;
ba6459ba
PMF
204 struct ltt_available_probe *probe;
205 int ret = 0;
206
f7b16408 207 pthread_mutex_lock(&probes_mutex);
ba6459ba
PMF
208 probe = get_probe_from_name(pname);
209 if (!probe) {
210 ret = -ENOENT;
211 goto end;
212 }
b521931e 213 pdata = ust_marker_get_private_data(channel, mname, probe->probe_func, 0);
ba6459ba
PMF
214 if (IS_ERR(pdata)) {
215 ret = PTR_ERR(pdata);
216 goto end;
217 } else if (!pdata) {
218 /*
219 * Not registered by us.
220 */
221 ret = -EPERM;
222 goto end;
223 }
b521931e 224 ret = ust_marker_probe_unregister(channel, mname, probe->probe_func, pdata);
ba6459ba
PMF
225 if (ret)
226 goto end;
227 else {
0222e121 228 cds_list_del(&pdata->node);
ba6459ba
PMF
229 free(pdata);
230 }
231end:
f7b16408 232 pthread_mutex_unlock(&probes_mutex);
ba6459ba
PMF
233 return ret;
234}
ba6459ba 235
b521931e 236static void disconnect_all_ust_markers(void)
ba6459ba 237{
b521931e 238 struct ltt_active_ust_marker *pdata, *tmp;
ba6459ba 239
b521931e
MD
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,
ba6459ba 242 pdata);
0222e121 243 cds_list_del(&pdata->node);
ba6459ba
PMF
244 free(pdata);
245 }
246}
247
b521931e 248void __attribute__((constructor)) init_ust_marker_control(void)
ba6459ba 249{
b27f8e75 250 if (!initialized) {
4db647c5 251 int ret;
ba6459ba 252
b27f8e75 253 init_ust_marker();
4db647c5
PMF
254 ret = ltt_probe_register(&default_probe);
255 BUG_ON(ret);
b521931e 256 ret = ltt_ust_marker_connect("metadata", "core_marker_format",
4db647c5
PMF
257 DEFAULT_PROBE);
258 BUG_ON(ret);
b521931e 259 ret = ltt_ust_marker_connect("metadata", "core_marker_id", DEFAULT_PROBE);
4db647c5 260 BUG_ON(ret);
4db647c5
PMF
261 initialized = 1;
262 }
ba6459ba 263}
ba6459ba 264
b521931e 265static void __attribute__((destructor)) ust_marker_control_exit(void)
ba6459ba
PMF
266{
267 int ret;
268
b521931e 269 ret = ltt_ust_marker_disconnect("metadata", "core_marker_format",
ba6459ba
PMF
270 DEFAULT_PROBE);
271 BUG_ON(ret);
b521931e 272 ret = ltt_ust_marker_disconnect("metadata", "core_marker_id",
ba6459ba
PMF
273 DEFAULT_PROBE);
274 BUG_ON(ret);
275 ret = ltt_probe_unregister(&default_probe);
276 BUG_ON(ret);
b521931e 277 disconnect_all_ust_markers();
b27f8e75 278 ust_marker_synchronize_unregister();
ba6459ba 279}
This page took 0.050604 seconds and 4 git commands to generate.