Markers: sync from LTTng 0.249 marker code
[ust.git] / libust / marker.c
CommitLineData
68c1021b 1/*
fe566790 2 * Copyright (C) 2007-2011 Mathieu Desnoyers
68c1021b 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
f37142a4
MD
6 * License as published by the Free Software Foundation;
7 * version 2.1 of the License.
68c1021b 8 *
34e4b7db 9 * This library is distributed in the hope that it will be useful,
68c1021b 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.
68c1021b 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
68c1021b 17 */
59b161cd 18
b0c4126f 19#define _LGPL_SOURCE
909bc43f
PMF
20#include <stdlib.h>
21#include <errno.h>
b7ea1a1c 22#include <urcu-bp.h>
17bb07b4 23#include <urcu/rculist.h>
10c56168 24#include <urcu/hlist.h>
769d0157 25
518d7abb 26#include <ust/core.h>
93d0f2ea 27#include <ust/marker.h>
535b0d0a 28#include <ust/marker-internal.h>
fbae86d6 29#include <ust/tracepoint.h>
81614639 30#include <ust/tracepoint-internal.h>
909bc43f 31
30ffe279 32#include "usterr_signal_safe.h"
59b161cd
PMF
33#include "channels.h"
34#include "tracercore.h"
c93858f1 35#include "tracer.h"
68c1021b 36
b521931e
MD
37extern struct ust_marker * const __start___ust_marker_ptrs[] __attribute__((visibility("hidden")));
38extern struct ust_marker * const __stop___ust_marker_ptrs[] __attribute__((visibility("hidden")));
defa46a7 39
b521931e
MD
40/* Set to 1 to enable ust_marker debug output */
41static const int ust_marker_debug;
68c1021b
PMF
42
43/*
fd0a1aea
MD
44 * ust_marker mutex protects the builtin and module ust_marker and the
45 * hash table, as well as the ust_marker_libs list.
68c1021b 46 */
b521931e 47static DEFINE_MUTEX(ust_marker_mutex);
b521931e 48static CDS_LIST_HEAD(ust_marker_libs);
772030fe 49
b521931e 50void lock_ust_marker(void)
68c1021b 51{
b521931e 52 pthread_mutex_lock(&ust_marker_mutex);
68c1021b
PMF
53}
54
b521931e 55void unlock_ust_marker(void)
68c1021b 56{
b521931e 57 pthread_mutex_unlock(&ust_marker_mutex);
68c1021b
PMF
58}
59
60/*
b521931e 61 * ust_marker hash table, containing the active ust_marker.
fd0a1aea 62 * Protected by ust_marker mutex.
68c1021b 63 */
5cfbb58f
MD
64#define UST_MARKER_HASH_BITS 6
65#define UST_MARKER_TABLE_SIZE (1 << UST_MARKER_HASH_BITS)
66static struct cds_hlist_head ust_marker_table[UST_MARKER_TABLE_SIZE];
68c1021b 67
fd0a1aea
MD
68struct ust_marker_probe_array {
69 struct rcu_head rcu;
70 struct ust_marker_probe_closure c[0];
71};
72
68c1021b
PMF
73/*
74 * Note about RCU :
b521931e
MD
75 * It is used to make sure every handler has finished using its private
76 * data between two consecutive operation (add or remove) on a given
77 * ust_marker. It is also used to delay the free of multiple probes
78 * array until a quiescent state is reached. ust_marker entries
79 * modifications are protected by the ust_marker_mutex.
68c1021b 80 */
b521931e 81struct ust_marker_entry {
10c56168 82 struct cds_hlist_node hlist;
68c1021b
PMF
83 char *format;
84 char *name;
85 /* Probe wrapper */
fe566790 86 void (*call)(const struct ust_marker *mdata, void *call_private, ...);
b521931e 87 struct ust_marker_probe_closure single;
fd0a1aea 88 struct ust_marker_probe_array *multi;
68c1021b 89 int refcount; /* Number of times armed. 0 if disarmed. */
68c1021b
PMF
90 u16 channel_id;
91 u16 event_id;
92 unsigned char ptype:1;
93 unsigned char format_allocated:1;
94 char channel[0]; /* Contains channel'\0'name'\0'format'\0' */
95};
96
68c1021b 97/**
b521931e
MD
98 * __ust_marker_empty_function - Empty probe callback
99 * @mdata: ust_marker data
68c1021b
PMF
100 * @probe_private: probe private data
101 * @call_private: call site private data
102 * @fmt: format string
103 * @...: variable argument list
104 *
b521931e
MD
105 * Empty callback provided as a probe to the ust_marker. By providing
106 * this to a disabled ust_marker, we make sure the execution flow is
107 * always valid even though the function pointer change and the
108 * ust_marker enabling are two distinct operations that modifies the
109 * execution flow of preemptible code.
68c1021b 110 */
b521931e 111notrace void __ust_marker_empty_function(const struct ust_marker *mdata,
fe566790 112 void *probe_private, void *call_private, const char *fmt, va_list *args)
68c1021b
PMF
113{
114}
68c1021b
PMF
115
116/*
b521931e
MD
117 * ust_marker_probe_cb Callback that prepares the variable argument list for probes.
118 * @mdata: pointer of type struct ust_marker
68c1021b
PMF
119 * @call_private: caller site private data
120 * @...: Variable argument list.
121 *
122 * Since we do not use "typical" pointer based RCU in the 1 argument case, we
0222e121 123 * need to put a full cmm_smp_rmb() in this branch. This is why we do not use
68c1021b
PMF
124 * rcu_dereference() for the pointer read.
125 */
b521931e 126notrace void ust_marker_probe_cb(const struct ust_marker *mdata,
fe566790 127 void *call_private, ...)
68c1021b
PMF
128{
129 va_list args;
130 char ptype;
131
132 /*
133 * rcu_read_lock_sched does two things : disabling preemption to make
134 * sure the teardown of the callbacks can be done correctly when they
135 * are in modules and they insure RCU read coherency.
136 */
fd0a1aea 137 rcu_read_lock();
68c1021b
PMF
138 ptype = mdata->ptype;
139 if (likely(!ptype)) {
b521931e 140 ust_marker_probe_func *func;
68c1021b 141 /* Must read the ptype before ptr. They are not data dependant,
0222e121
MD
142 * so we put an explicit cmm_smp_rmb() here. */
143 cmm_smp_rmb();
68c1021b
PMF
144 func = mdata->single.func;
145 /* Must read the ptr before private data. They are not data
0222e121
MD
146 * dependant, so we put an explicit cmm_smp_rmb() here. */
147 cmm_smp_rmb();
fe566790
MD
148 va_start(args, call_private);
149 func(mdata, mdata->single.probe_private, call_private,
68c1021b
PMF
150 mdata->format, &args);
151 va_end(args);
152 } else {
fd0a1aea 153 struct ust_marker_probe_array *multi;
68c1021b
PMF
154 int i;
155 /*
156 * Read mdata->ptype before mdata->multi.
157 */
0222e121 158 cmm_smp_rmb();
68c1021b
PMF
159 multi = mdata->multi;
160 /*
161 * multi points to an array, therefore accessing the array
162 * depends on reading multi. However, even in this case,
163 * we must insure that the pointer is read _before_ the array
0222e121
MD
164 * data. Same as rcu_dereference, but we need a full cmm_smp_rmb()
165 * in the fast path, so put the explicit cmm_barrier here.
68c1021b 166 */
0222e121 167 cmm_smp_read_barrier_depends();
fd0a1aea 168 for (i = 0; multi->c[i].func; i++) {
fe566790 169 va_start(args, call_private);
fd0a1aea 170 multi->c[i].func(mdata, multi->c[i].probe_private,
fe566790 171 call_private, mdata->format, &args);
68c1021b
PMF
172 va_end(args);
173 }
174 }
fd0a1aea 175 rcu_read_unlock();
68c1021b 176}
68c1021b
PMF
177
178/*
b521931e
MD
179 * ust_marker_probe_cb Callback that does not prepare the variable argument list.
180 * @mdata: pointer of type struct ust_marker
68c1021b
PMF
181 * @call_private: caller site private data
182 * @...: Variable argument list.
183 *
b521931e 184 * Should be connected to ust_marker "UST_MARKER_NOARGS".
68c1021b 185 */
b521931e 186static notrace void ust_marker_probe_cb_noarg(const struct ust_marker *mdata,
fe566790 187 void *call_private, ...)
68c1021b
PMF
188{
189 va_list args; /* not initialized */
190 char ptype;
191
fd0a1aea 192 rcu_read_lock();
68c1021b
PMF
193 ptype = mdata->ptype;
194 if (likely(!ptype)) {
b521931e 195 ust_marker_probe_func *func;
68c1021b 196 /* Must read the ptype before ptr. They are not data dependant,
0222e121
MD
197 * so we put an explicit cmm_smp_rmb() here. */
198 cmm_smp_rmb();
68c1021b
PMF
199 func = mdata->single.func;
200 /* Must read the ptr before private data. They are not data
0222e121
MD
201 * dependant, so we put an explicit cmm_smp_rmb() here. */
202 cmm_smp_rmb();
fe566790 203 func(mdata, mdata->single.probe_private, call_private,
68c1021b
PMF
204 mdata->format, &args);
205 } else {
fd0a1aea 206 struct ust_marker_probe_array *multi;
68c1021b
PMF
207 int i;
208 /*
209 * Read mdata->ptype before mdata->multi.
210 */
0222e121 211 cmm_smp_rmb();
68c1021b
PMF
212 multi = mdata->multi;
213 /*
214 * multi points to an array, therefore accessing the array
215 * depends on reading multi. However, even in this case,
216 * we must insure that the pointer is read _before_ the array
0222e121
MD
217 * data. Same as rcu_dereference, but we need a full cmm_smp_rmb()
218 * in the fast path, so put the explicit cmm_barrier here.
68c1021b 219 */
0222e121 220 cmm_smp_read_barrier_depends();
fd0a1aea
MD
221 for (i = 0; multi->c[i].func; i++)
222 multi->c[i].func(mdata, multi->c[i].probe_private,
68c1021b
PMF
223 call_private, mdata->format, &args);
224 }
fd0a1aea 225 rcu_read_unlock();
68c1021b
PMF
226}
227
228static void free_old_closure(struct rcu_head *head)
229{
fd0a1aea
MD
230 struct ust_marker_probe_array *multi =
231 _ust_container_of(head, struct ust_marker_probe_array, rcu);
232 free(multi);
68c1021b
PMF
233}
234
b521931e 235static void debug_print_probes(struct ust_marker_entry *entry)
68c1021b
PMF
236{
237 int i;
238
b521931e 239 if (!ust_marker_debug)
68c1021b
PMF
240 return;
241
242 if (!entry->ptype) {
c1f20530 243 DBG("Single probe : %p %p",
68c1021b
PMF
244 entry->single.func,
245 entry->single.probe_private);
246 } else {
fd0a1aea 247 for (i = 0; entry->multi->c[i].func; i++)
c1f20530 248 DBG("Multi probe %d : %p %p", i,
fd0a1aea
MD
249 entry->multi->c[i].func,
250 entry->multi->c[i].probe_private);
68c1021b
PMF
251 }
252}
253
fd0a1aea 254static struct ust_marker_probe_array *
b521931e
MD
255ust_marker_entry_add_probe(struct ust_marker_entry *entry,
256 ust_marker_probe_func *probe, void *probe_private)
68c1021b
PMF
257{
258 int nr_probes = 0;
fd0a1aea 259 struct ust_marker_probe_array *old, *new;
68c1021b
PMF
260
261 WARN_ON(!probe);
262
263 debug_print_probes(entry);
264 old = entry->multi;
265 if (!entry->ptype) {
266 if (entry->single.func == probe &&
267 entry->single.probe_private == probe_private)
268 return ERR_PTR(-EBUSY);
b521931e 269 if (entry->single.func == __ust_marker_empty_function) {
68c1021b
PMF
270 /* 0 -> 1 probes */
271 entry->single.func = probe;
272 entry->single.probe_private = probe_private;
273 entry->refcount = 1;
274 entry->ptype = 0;
275 debug_print_probes(entry);
276 return NULL;
277 } else {
278 /* 1 -> 2 probes */
279 nr_probes = 1;
280 old = NULL;
281 }
282 } else {
283 /* (N -> N+1), (N != 0, 1) probes */
fd0a1aea
MD
284 for (nr_probes = 0; old->c[nr_probes].func; nr_probes++)
285 if (old->c[nr_probes].func == probe
286 && old->c[nr_probes].probe_private
68c1021b
PMF
287 == probe_private)
288 return ERR_PTR(-EBUSY);
289 }
290 /* + 2 : one for new probe, one for NULL func */
fd0a1aea
MD
291 new = zmalloc(sizeof(struct ust_marker_probe_array)
292 + ((nr_probes + 2) * sizeof(struct ust_marker_probe_closure)));
68c1021b
PMF
293 if (new == NULL)
294 return ERR_PTR(-ENOMEM);
295 if (!old)
fd0a1aea 296 new->c[0] = entry->single;
68c1021b 297 else
fd0a1aea 298 memcpy(&new->c[0], &old->c[0],
b521931e 299 nr_probes * sizeof(struct ust_marker_probe_closure));
fd0a1aea
MD
300 new->c[nr_probes].func = probe;
301 new->c[nr_probes].probe_private = probe_private;
68c1021b
PMF
302 entry->refcount = nr_probes + 1;
303 entry->multi = new;
304 entry->ptype = 1;
305 debug_print_probes(entry);
306 return old;
307}
308
fd0a1aea 309static struct ust_marker_probe_array *
b521931e
MD
310ust_marker_entry_remove_probe(struct ust_marker_entry *entry,
311 ust_marker_probe_func *probe, void *probe_private)
68c1021b
PMF
312{
313 int nr_probes = 0, nr_del = 0, i;
fd0a1aea 314 struct ust_marker_probe_array *old, *new;
68c1021b
PMF
315
316 old = entry->multi;
317
318 debug_print_probes(entry);
319 if (!entry->ptype) {
320 /* 0 -> N is an error */
b521931e 321 WARN_ON(entry->single.func == __ust_marker_empty_function);
68c1021b
PMF
322 /* 1 -> 0 probes */
323 WARN_ON(probe && entry->single.func != probe);
324 WARN_ON(entry->single.probe_private != probe_private);
b521931e 325 entry->single.func = __ust_marker_empty_function;
68c1021b
PMF
326 entry->refcount = 0;
327 entry->ptype = 0;
328 debug_print_probes(entry);
329 return NULL;
330 } else {
331 /* (N -> M), (N > 1, M >= 0) probes */
fd0a1aea
MD
332 for (nr_probes = 0; old->c[nr_probes].func; nr_probes++) {
333 if ((!probe || old->c[nr_probes].func == probe)
334 && old->c[nr_probes].probe_private
68c1021b
PMF
335 == probe_private)
336 nr_del++;
337 }
338 }
339
340 if (nr_probes - nr_del == 0) {
341 /* N -> 0, (N > 1) */
b521931e 342 entry->single.func = __ust_marker_empty_function;
68c1021b
PMF
343 entry->refcount = 0;
344 entry->ptype = 0;
345 } else if (nr_probes - nr_del == 1) {
346 /* N -> 1, (N > 1) */
fd0a1aea
MD
347 for (i = 0; old->c[i].func; i++)
348 if ((probe && old->c[i].func != probe) ||
349 old->c[i].probe_private != probe_private)
350 entry->single = old->c[i];
68c1021b
PMF
351 entry->refcount = 1;
352 entry->ptype = 0;
353 } else {
354 int j = 0;
355 /* N -> M, (N > 1, M > 1) */
356 /* + 1 for NULL */
fd0a1aea
MD
357 new = zmalloc(sizeof(struct ust_marker_probe_array)
358 + ((nr_probes - nr_del + 1) * sizeof(struct ust_marker_probe_closure)));
68c1021b
PMF
359 if (new == NULL)
360 return ERR_PTR(-ENOMEM);
fd0a1aea
MD
361 for (i = 0; old->c[i].func; i++)
362 if ((probe && old->c[i].func != probe) ||
363 old->c[i].probe_private != probe_private)
364 new->c[j++] = old->c[i];
68c1021b
PMF
365 entry->refcount = nr_probes - nr_del;
366 entry->ptype = 1;
367 entry->multi = new;
368 }
369 debug_print_probes(entry);
370 return old;
371}
372
373/*
b521931e
MD
374 * Get ust_marker if the ust_marker is present in the ust_marker hash table.
375 * Must be called with ust_marker_mutex held.
68c1021b
PMF
376 * Returns NULL if not present.
377 */
b521931e 378static struct ust_marker_entry *get_ust_marker(const char *channel, const char *name)
68c1021b 379{
10c56168
DG
380 struct cds_hlist_head *head;
381 struct cds_hlist_node *node;
b521931e 382 struct ust_marker_entry *e;
68c1021b
PMF
383 size_t channel_len = strlen(channel) + 1;
384 size_t name_len = strlen(name) + 1;
385 u32 hash;
386
387 hash = jhash(channel, channel_len-1, 0) ^ jhash(name, name_len-1, 0);
5cfbb58f 388 head = &ust_marker_table[hash & ((1 << UST_MARKER_HASH_BITS)-1)];
10c56168 389 cds_hlist_for_each_entry(e, node, head, hlist) {
68c1021b
PMF
390 if (!strcmp(channel, e->channel) && !strcmp(name, e->name))
391 return e;
392 }
393 return NULL;
394}
395
396/*
b521931e
MD
397 * Add the ust_marker to the ust_marker hash table. Must be called with
398 * ust_marker_mutex held.
68c1021b 399 */
b521931e 400static struct ust_marker_entry *add_ust_marker(const char *channel, const char *name,
68c1021b
PMF
401 const char *format)
402{
10c56168
DG
403 struct cds_hlist_head *head;
404 struct cds_hlist_node *node;
b521931e 405 struct ust_marker_entry *e;
68c1021b
PMF
406 size_t channel_len = strlen(channel) + 1;
407 size_t name_len = strlen(name) + 1;
408 size_t format_len = 0;
409 u32 hash;
410
411 hash = jhash(channel, channel_len-1, 0) ^ jhash(name, name_len-1, 0);
412 if (format)
413 format_len = strlen(format) + 1;
5cfbb58f 414 head = &ust_marker_table[hash & ((1 << UST_MARKER_HASH_BITS)-1)];
10c56168 415 cds_hlist_for_each_entry(e, node, head, hlist) {
68c1021b 416 if (!strcmp(channel, e->channel) && !strcmp(name, e->name)) {
b521931e 417 DBG("ust_marker %s.%s busy", channel, name);
68c1021b
PMF
418 return ERR_PTR(-EBUSY); /* Already there */
419 }
420 }
421 /*
1dba3e6c 422 * Using zmalloc here to allocate a variable length element. Could
68c1021b
PMF
423 * cause some memory fragmentation if overused.
424 */
b521931e 425 e = zmalloc(sizeof(struct ust_marker_entry)
909bc43f 426 + channel_len + name_len + format_len);
68c1021b
PMF
427 if (!e)
428 return ERR_PTR(-ENOMEM);
429 memcpy(e->channel, channel, channel_len);
430 e->name = &e->channel[channel_len];
431 memcpy(e->name, name, name_len);
432 if (format) {
eddb0f66 433 e->format = &e->name[name_len];
68c1021b 434 memcpy(e->format, format, format_len);
b521931e
MD
435 if (strcmp(e->format, UST_MARKER_NOARGS) == 0)
436 e->call = ust_marker_probe_cb_noarg;
68c1021b 437 else
b521931e 438 e->call = ust_marker_probe_cb;
f36c12ab 439 __ust_marker(metadata, core_marker_format, NULL,
68c1021b
PMF
440 "channel %s name %s format %s",
441 e->channel, e->name, e->format);
442 } else {
443 e->format = NULL;
b521931e 444 e->call = ust_marker_probe_cb;
68c1021b 445 }
b521931e 446 e->single.func = __ust_marker_empty_function;
68c1021b
PMF
447 e->single.probe_private = NULL;
448 e->multi = NULL;
449 e->ptype = 0;
450 e->format_allocated = 0;
451 e->refcount = 0;
10c56168 452 cds_hlist_add_head(&e->hlist, head);
68c1021b
PMF
453 return e;
454}
455
456/*
b521931e 457 * Remove the ust_marker from the ust_marker hash table. Must be called with mutex_lock
68c1021b
PMF
458 * held.
459 */
b521931e 460static int remove_ust_marker(const char *channel, const char *name)
68c1021b 461{
10c56168
DG
462 struct cds_hlist_head *head;
463 struct cds_hlist_node *node;
b521931e 464 struct ust_marker_entry *e;
68c1021b
PMF
465 int found = 0;
466 size_t channel_len = strlen(channel) + 1;
467 size_t name_len = strlen(name) + 1;
468 u32 hash;
469 int ret;
470
471 hash = jhash(channel, channel_len-1, 0) ^ jhash(name, name_len-1, 0);
5cfbb58f 472 head = &ust_marker_table[hash & ((1 << UST_MARKER_HASH_BITS)-1)];
10c56168 473 cds_hlist_for_each_entry(e, node, head, hlist) {
68c1021b
PMF
474 if (!strcmp(channel, e->channel) && !strcmp(name, e->name)) {
475 found = 1;
476 break;
477 }
478 }
479 if (!found)
480 return -ENOENT;
b521931e 481 if (e->single.func != __ust_marker_empty_function)
68c1021b 482 return -EBUSY;
10c56168 483 cds_hlist_del(&e->hlist);
68c1021b 484 if (e->format_allocated)
909bc43f 485 free(e->format);
68c1021b
PMF
486 ret = ltt_channels_unregister(e->channel);
487 WARN_ON(ret);
909bc43f 488 free(e);
68c1021b
PMF
489 return 0;
490}
491
492/*
493 * Set the mark_entry format to the format found in the element.
494 */
b521931e 495static int ust_marker_set_format(struct ust_marker_entry *entry, const char *format)
68c1021b 496{
909bc43f 497 entry->format = strdup(format);
68c1021b
PMF
498 if (!entry->format)
499 return -ENOMEM;
500 entry->format_allocated = 1;
501
f36c12ab 502 __ust_marker(metadata, core_marker_format, NULL,
68c1021b
PMF
503 "channel %s name %s format %s",
504 entry->channel, entry->name, entry->format);
505 return 0;
506}
507
508/*
b521931e 509 * Sets the probe callback corresponding to one ust_marker.
68c1021b 510 */
b521931e 511static int set_ust_marker(struct ust_marker_entry *entry, struct ust_marker *elem,
68c1021b
PMF
512 int active)
513{
514 int ret = 0;
515 WARN_ON(strcmp(entry->name, elem->name) != 0);
516
517 if (entry->format) {
518 if (strcmp(entry->format, elem->format) != 0) {
b521931e 519 ERR("Format mismatch for probe %s (%s), ust_marker (%s)",
68c1021b
PMF
520 entry->name,
521 entry->format,
522 elem->format);
523 return -EPERM;
524 }
525 } else {
b521931e 526 ret = ust_marker_set_format(entry, elem->format);
68c1021b
PMF
527 if (ret)
528 return ret;
529 }
530
531 /*
532 * probe_cb setup (statically known) is done here. It is
533 * asynchronous with the rest of execution, therefore we only
534 * pass from a "safe" callback (with argument) to an "unsafe"
535 * callback (does not set arguments).
536 */
537 elem->call = entry->call;
538 elem->channel_id = entry->channel_id;
539 elem->event_id = entry->event_id;
540 /*
541 * Sanity check :
542 * We only update the single probe private data when the ptr is
543 * set to a _non_ single probe! (0 -> 1 and N -> 1, N != 1)
544 */
b521931e 545 WARN_ON(elem->single.func != __ust_marker_empty_function
68c1021b
PMF
546 && elem->single.probe_private != entry->single.probe_private
547 && !elem->ptype);
548 elem->single.probe_private = entry->single.probe_private;
549 /*
550 * Make sure the private data is valid when we update the
551 * single probe ptr.
552 */
0222e121 553 cmm_smp_wmb();
68c1021b
PMF
554 elem->single.func = entry->single.func;
555 /*
556 * We also make sure that the new probe callbacks array is consistent
557 * before setting a pointer to it.
558 */
559 rcu_assign_pointer(elem->multi, entry->multi);
560 /*
561 * Update the function or multi probe array pointer before setting the
562 * ptype.
563 */
0222e121 564 cmm_smp_wmb();
68c1021b
PMF
565 elem->ptype = entry->ptype;
566
f36c12ab 567 if (elem->tp_name && (active ^ elem->state)) {
12e81b07
PMF
568 WARN_ON(!elem->tp_cb);
569 /*
570 * It is ok to directly call the probe registration because type
686debc3 571 * checking has been done in the __ust_marker_tp() macro.
12e81b07
PMF
572 */
573
574 if (active) {
12e81b07
PMF
575 ret = tracepoint_probe_register_noupdate(
576 elem->tp_name,
9b9e13aa 577 elem->tp_cb, NULL);
12e81b07 578 } else {
12e81b07
PMF
579 /*
580 * tracepoint_probe_update_all() must be called
fd0a1aea 581 * before the library containing tp_cb is unloaded.
12e81b07 582 */
fd0a1aea
MD
583 ret = tracepoint_probe_unregister_noupdate(
584 elem->tp_name,
585 elem->tp_cb, NULL);
12e81b07
PMF
586 }
587 }
f36c12ab 588 elem->state = active;
68c1021b
PMF
589
590 return ret;
591}
592
593/*
b521931e 594 * Disable a ust_marker and its probe callback.
68c1021b
PMF
595 * Note: only waiting an RCU period after setting elem->call to the empty
596 * function insures that the original callback is not used anymore. This insured
fd0a1aea 597 * by rcu_read_lock around the call site.
68c1021b 598 */
b521931e 599static void disable_ust_marker(struct ust_marker *elem)
68c1021b 600{
12e81b07
PMF
601 int ret;
602
603 /* leave "call" as is. It is known statically. */
f36c12ab 604 if (elem->tp_name && elem->state) {
12e81b07
PMF
605 WARN_ON(!elem->tp_cb);
606 /*
607 * It is ok to directly call the probe registration because type
686debc3 608 * checking has been done in the __ust_marker_tp() macro.
12e81b07 609 */
12e81b07
PMF
610 /*
611 * tracepoint_probe_update_all() must be called
612 * before the module containing tp_cb is unloaded.
613 */
fd0a1aea
MD
614 ret = tracepoint_probe_unregister_noupdate(elem->tp_name,
615 elem->tp_cb, NULL);
616 WARN_ON(ret);
12e81b07 617 }
f36c12ab 618 elem->state = 0;
b521931e 619 elem->single.func = __ust_marker_empty_function;
68c1021b 620 /* Update the function before setting the ptype */
0222e121 621 cmm_smp_wmb();
68c1021b
PMF
622 elem->ptype = 0; /* single probe */
623 /*
624 * Leave the private data and channel_id/event_id there, because removal
625 * is racy and should be done only after an RCU period. These are never
626 * used until the next initialization anyway.
627 */
628}
629
a5311005 630/*
b521931e 631 * is_ust_marker_enabled - Check if a ust_marker is enabled
a5311005 632 * @channel: channel name
b521931e 633 * @name: ust_marker name
a5311005 634 *
b521931e 635 * Returns 1 if the ust_marker is enabled, 0 if disabled.
a5311005 636 */
b521931e 637int is_ust_marker_enabled(const char *channel, const char *name)
a5311005 638{
b521931e 639 struct ust_marker_entry *entry;
a5311005 640
b521931e
MD
641 pthread_mutex_lock(&ust_marker_mutex);
642 entry = get_ust_marker(channel, name);
643 pthread_mutex_unlock(&ust_marker_mutex);
a5311005
PMF
644
645 return entry && !!entry->refcount;
646}
647
68c1021b 648/**
b521931e 649 * ust_marker_update_probe_range - Update a probe range
68c1021b
PMF
650 * @begin: beginning of the range
651 * @end: end of the range
652 *
b521931e 653 * Updates the probe callback corresponding to a range of ust_marker.
68c1021b 654 */
fd0a1aea 655static
b521931e
MD
656void ust_marker_update_probe_range(struct ust_marker * const *begin,
657 struct ust_marker * const *end)
68c1021b 658{
b521931e
MD
659 struct ust_marker * const *iter;
660 struct ust_marker_entry *mark_entry;
68c1021b 661
68c1021b 662 for (iter = begin; iter < end; iter++) {
f08ebbe2
MD
663 if (!*iter)
664 continue; /* skip dummy */
b521931e 665 mark_entry = get_ust_marker((*iter)->channel, (*iter)->name);
68c1021b 666 if (mark_entry) {
b521931e 667 set_ust_marker(mark_entry, *iter, !!mark_entry->refcount);
68c1021b
PMF
668 /*
669 * ignore error, continue
670 */
671 } else {
b521931e 672 disable_ust_marker(*iter);
68c1021b
PMF
673 }
674 }
68c1021b
PMF
675}
676
b521931e 677static void lib_update_ust_marker(void)
772030fe 678{
b521931e 679 struct ust_marker_lib *lib;
772030fe 680
fd0a1aea 681 pthread_mutex_lock(&ust_marker_mutex);
b521931e
MD
682 cds_list_for_each_entry(lib, &ust_marker_libs, list)
683 ust_marker_update_probe_range(lib->ust_marker_start,
684 lib->ust_marker_start + lib->ust_marker_count);
fd0a1aea 685 pthread_mutex_unlock(&ust_marker_mutex);
772030fe
PMF
686}
687
68c1021b
PMF
688/*
689 * Update probes, removing the faulty probes.
690 *
691 * Internal callback only changed before the first probe is connected to it.
692 * Single probe private data can only be changed on 0 -> 1 and 2 -> 1
693 * transitions. All other transitions will leave the old private data valid.
694 * This makes the non-atomicity of the callback/private data updates valid.
695 *
696 * "special case" updates :
697 * 0 -> 1 callback
698 * 1 -> 0 callback
699 * 1 -> 2 callbacks
700 * 2 -> 1 callbacks
701 * Other updates all behave the same, just like the 2 -> 3 or 3 -> 2 updates.
b521931e 702 * Site effect : ust_marker_set_format may delete the ust_marker entry (creating a
68c1021b
PMF
703 * replacement).
704 */
b521931e 705static void ust_marker_update_probes(void)
68c1021b 706{
b521931e 707 lib_update_ust_marker();
12e81b07 708 tracepoint_probe_update_all();
68c1021b
PMF
709}
710
711/**
b521931e
MD
712 * ust_marker_probe_register - Connect a probe to a ust_marker
713 * @channel: ust_marker channel
714 * @name: ust_marker name
68c1021b
PMF
715 * @format: format string
716 * @probe: probe handler
717 * @probe_private: probe private data
718 *
719 * private data must be a valid allocated memory address, or NULL.
720 * Returns 0 if ok, error value on error.
721 * The probe address must at least be aligned on the architecture pointer size.
722 */
b521931e
MD
723int ust_marker_probe_register(const char *channel, const char *name,
724 const char *format, ust_marker_probe_func *probe,
68c1021b
PMF
725 void *probe_private)
726{
b521931e 727 struct ust_marker_entry *entry;
68c1021b 728 int ret = 0, ret_err;
fd0a1aea 729 struct ust_marker_probe_array *old;
68c1021b
PMF
730 int first_probe = 0;
731
b521931e
MD
732 pthread_mutex_lock(&ust_marker_mutex);
733 entry = get_ust_marker(channel, name);
68c1021b
PMF
734 if (!entry) {
735 first_probe = 1;
b521931e 736 entry = add_ust_marker(channel, name, format);
68c1021b
PMF
737 if (IS_ERR(entry))
738 ret = PTR_ERR(entry);
739 if (ret)
740 goto end;
741 ret = ltt_channels_register(channel);
742 if (ret)
b521931e 743 goto error_remove_ust_marker;
68c1021b
PMF
744 ret = ltt_channels_get_index_from_name(channel);
745 if (ret < 0)
746 goto error_unregister_channel;
747 entry->channel_id = ret;
748 ret = ltt_channels_get_event_id(channel, name);
749 if (ret < 0)
750 goto error_unregister_channel;
751 entry->event_id = ret;
752 ret = 0;
f36c12ab 753 __ust_marker(metadata, core_marker_id, NULL,
68c1021b
PMF
754 "channel %s name %s event_id %hu "
755 "int #1u%zu long #1u%zu pointer #1u%zu "
756 "size_t #1u%zu alignment #1u%u",
757 channel, name, entry->event_id,
758 sizeof(int), sizeof(long), sizeof(void *),
759 sizeof(size_t), ltt_get_alignment());
760 } else if (format) {
761 if (!entry->format)
b521931e 762 ret = ust_marker_set_format(entry, format);
68c1021b
PMF
763 else if (strcmp(entry->format, format))
764 ret = -EPERM;
765 if (ret)
766 goto end;
767 }
768
b521931e 769 old = ust_marker_entry_add_probe(entry, probe, probe_private);
68c1021b
PMF
770 if (IS_ERR(old)) {
771 ret = PTR_ERR(old);
772 if (first_probe)
773 goto error_unregister_channel;
774 else
775 goto end;
776 }
b521931e 777 pthread_mutex_unlock(&ust_marker_mutex);
68c1021b 778
b521931e
MD
779 /* Activate ust_marker if necessary */
780 ust_marker_update_probes();
68c1021b 781
fd0a1aea
MD
782 if (old) {
783 synchronize_rcu();
784 free_old_closure(&old->rcu);
785 }
786 return ret;
68c1021b
PMF
787
788error_unregister_channel:
789 ret_err = ltt_channels_unregister(channel);
790 WARN_ON(ret_err);
b521931e
MD
791error_remove_ust_marker:
792 ret_err = remove_ust_marker(channel, name);
68c1021b
PMF
793 WARN_ON(ret_err);
794end:
b521931e 795 pthread_mutex_unlock(&ust_marker_mutex);
68c1021b
PMF
796 return ret;
797}
68c1021b
PMF
798
799/**
b521931e
MD
800 * ust_marker_probe_unregister - Disconnect a probe from a ust_marker
801 * @channel: ust_marker channel
802 * @name: ust_marker name
68c1021b
PMF
803 * @probe: probe function pointer
804 * @probe_private: probe private data
805 *
b521931e 806 * Returns the private data given to ust_marker_probe_register, or an ERR_PTR().
68c1021b
PMF
807 * We do not need to call a synchronize_sched to make sure the probes have
808 * finished running before doing a module unload, because the module unload
809 * itself uses stop_machine(), which insures that every preempt disabled section
810 * have finished.
811 */
b521931e
MD
812int ust_marker_probe_unregister(const char *channel, const char *name,
813 ust_marker_probe_func *probe, void *probe_private)
68c1021b 814{
b521931e 815 struct ust_marker_entry *entry;
fd0a1aea
MD
816 struct ust_marker_probe_array *old;
817 int ret = 0;
68c1021b 818
b521931e
MD
819 pthread_mutex_lock(&ust_marker_mutex);
820 entry = get_ust_marker(channel, name);
fd0a1aea
MD
821 if (!entry) {
822 ret = -ENOENT;
68c1021b 823 goto end;
fd0a1aea 824 }
b521931e
MD
825 old = ust_marker_entry_remove_probe(entry, probe, probe_private);
826 pthread_mutex_unlock(&ust_marker_mutex);
68c1021b 827
b521931e 828 ust_marker_update_probes();
68c1021b 829
fd0a1aea
MD
830 if (old) {
831 synchronize_rcu();
832 free_old_closure(&old->rcu);
833 }
834 return ret;
835
68c1021b 836end:
b521931e 837 pthread_mutex_unlock(&ust_marker_mutex);
68c1021b
PMF
838 return ret;
839}
68c1021b 840
b521931e 841static struct ust_marker_entry *
fd0a1aea
MD
842get_ust_marker_from_private_data(ust_marker_probe_func *probe,
843 void *probe_private)
68c1021b 844{
b521931e 845 struct ust_marker_entry *entry;
68c1021b 846 unsigned int i;
10c56168
DG
847 struct cds_hlist_head *head;
848 struct cds_hlist_node *node;
68c1021b 849
5cfbb58f 850 for (i = 0; i < UST_MARKER_TABLE_SIZE; i++) {
b521931e 851 head = &ust_marker_table[i];
10c56168 852 cds_hlist_for_each_entry(entry, node, head, hlist) {
68c1021b
PMF
853 if (!entry->ptype) {
854 if (entry->single.func == probe
855 && entry->single.probe_private
856 == probe_private)
857 return entry;
858 } else {
fd0a1aea 859 struct ust_marker_probe_array *closure;
68c1021b 860 closure = entry->multi;
fd0a1aea
MD
861 for (i = 0; closure->c[i].func; i++) {
862 if (closure->c[i].func == probe &&
863 closure->c[i].probe_private
68c1021b
PMF
864 == probe_private)
865 return entry;
866 }
867 }
868 }
869 }
870 return NULL;
871}
872
873/**
b521931e 874 * ust_marker_probe_unregister_private_data - Disconnect a probe from a ust_marker
68c1021b
PMF
875 * @probe: probe function
876 * @probe_private: probe private data
877 *
878 * Unregister a probe by providing the registered private data.
b521931e 879 * Only removes the first ust_marker found in hash table.
68c1021b
PMF
880 * Return 0 on success or error value.
881 * We do not need to call a synchronize_sched to make sure the probes have
882 * finished running before doing a module unload, because the module unload
883 * itself uses stop_machine(), which insures that every preempt disabled section
884 * have finished.
885 */
b521931e 886int ust_marker_probe_unregister_private_data(ust_marker_probe_func *probe,
68c1021b
PMF
887 void *probe_private)
888{
b521931e 889 struct ust_marker_entry *entry;
68c1021b 890 int ret = 0;
fd0a1aea 891 struct ust_marker_probe_array *old;
909bc43f 892 char *channel = NULL, *name = NULL;
68c1021b 893
b521931e
MD
894 pthread_mutex_lock(&ust_marker_mutex);
895 entry = get_ust_marker_from_private_data(probe, probe_private);
68c1021b
PMF
896 if (!entry) {
897 ret = -ENOENT;
fd0a1aea 898 goto unlock;
68c1021b 899 }
b521931e 900 old = ust_marker_entry_remove_probe(entry, NULL, probe_private);
909bc43f
PMF
901 channel = strdup(entry->channel);
902 name = strdup(entry->name);
fd0a1aea
MD
903 /* Ignore busy error message */
904 remove_ust_marker(channel, name);
b521931e 905 pthread_mutex_unlock(&ust_marker_mutex);
68c1021b 906
b521931e 907 ust_marker_update_probes();
68c1021b 908
fd0a1aea
MD
909 if (old) {
910 synchronize_rcu();
911 free_old_closure(&old->rcu);
912 }
913 goto end;
914
915unlock:
b521931e 916 pthread_mutex_unlock(&ust_marker_mutex);
fd0a1aea 917end:
909bc43f
PMF
918 free(channel);
919 free(name);
68c1021b
PMF
920 return ret;
921}
68c1021b
PMF
922
923/**
b521931e
MD
924 * ust_marker_get_private_data - Get a ust_marker's probe private data
925 * @channel: ust_marker channel
926 * @name: ust_marker name
68c1021b
PMF
927 * @probe: probe to match
928 * @num: get the nth matching probe's private data
929 *
930 * Returns the nth private data pointer (starting from 0) matching, or an
931 * ERR_PTR.
932 * Returns the private data pointer, or an ERR_PTR.
933 * The private data pointer should _only_ be dereferenced if the caller is the
934 * owner of the data, or its content could vanish. This is mostly used to
935 * confirm that a caller is the owner of a registered probe.
936 */
b521931e
MD
937void *ust_marker_get_private_data(const char *channel, const char *name,
938 ust_marker_probe_func *probe, int num)
68c1021b 939{
10c56168
DG
940 struct cds_hlist_head *head;
941 struct cds_hlist_node *node;
b521931e 942 struct ust_marker_entry *e;
68c1021b
PMF
943 size_t channel_len = strlen(channel) + 1;
944 size_t name_len = strlen(name) + 1;
945 int i;
946 u32 hash;
947
948 hash = jhash(channel, channel_len-1, 0) ^ jhash(name, name_len-1, 0);
5cfbb58f 949 head = &ust_marker_table[hash & ((1 << UST_MARKER_HASH_BITS)-1)];
10c56168 950 cds_hlist_for_each_entry(e, node, head, hlist) {
68c1021b
PMF
951 if (!strcmp(channel, e->channel) && !strcmp(name, e->name)) {
952 if (!e->ptype) {
953 if (num == 0 && e->single.func == probe)
954 return e->single.probe_private;
955 } else {
fd0a1aea 956 struct ust_marker_probe_array *closure;
68c1021b
PMF
957 int match = 0;
958 closure = e->multi;
fd0a1aea
MD
959 for (i = 0; closure->c[i].func; i++) {
960 if (closure->c[i].func != probe)
68c1021b
PMF
961 continue;
962 if (match++ == num)
fd0a1aea 963 return closure->c[i].probe_private;
68c1021b
PMF
964 }
965 }
966 break;
967 }
968 }
969 return ERR_PTR(-ENOENT);
970}
68c1021b
PMF
971
972/**
fd0a1aea
MD
973 * ust_marker_get_iter_range - Get a next ust_marker iterator given a range.
974 * @ust_marker: current ust_marker (in), next ust_marker (out)
975 * @begin: beginning of the range
976 * @end: end of the range
68c1021b 977 *
fd0a1aea
MD
978 * Returns whether a next ust_marker has been found (1) or not (0).
979 * Will return the first ust_marker in the range if the input ust_marker is NULL.
980 * Called with markers mutex held.
68c1021b 981 */
fd0a1aea
MD
982static
983int ust_marker_get_iter_range(struct ust_marker * const **ust_marker,
984 struct ust_marker * const *begin,
985 struct ust_marker * const *end)
986{
987 if (!*ust_marker && begin != end)
988 *ust_marker = begin;
989 while (*ust_marker >= begin && *ust_marker < end) {
990 if (!**ust_marker)
991 (*ust_marker)++; /* skip dummy */
992 else
993 return 1;
994 }
995 return 0;
996}
68c1021b 997
772030fe
PMF
998/*
999 * Returns 0 if current not found.
1000 * Returns 1 if current found.
fd0a1aea 1001 * Called with markers mutex held.
772030fe 1002 */
fd0a1aea 1003static
b521931e 1004int lib_get_iter_ust_marker(struct ust_marker_iter *iter)
772030fe 1005{
b521931e 1006 struct ust_marker_lib *iter_lib;
772030fe
PMF
1007 int found = 0;
1008
b521931e 1009 cds_list_for_each_entry(iter_lib, &ust_marker_libs, list) {
772030fe
PMF
1010 if (iter_lib < iter->lib)
1011 continue;
1012 else if (iter_lib > iter->lib)
b521931e
MD
1013 iter->ust_marker = NULL;
1014 found = ust_marker_get_iter_range(&iter->ust_marker,
1015 iter_lib->ust_marker_start,
1016 iter_lib->ust_marker_start + iter_lib->ust_marker_count);
772030fe
PMF
1017 if (found) {
1018 iter->lib = iter_lib;
1019 break;
1020 }
1021 }
772030fe
PMF
1022 return found;
1023}
1024
fd0a1aea 1025/* Called with markers mutex held. */
b521931e 1026static void ust_marker_get_iter(struct ust_marker_iter *iter)
68c1021b
PMF
1027{
1028 int found = 0;
1029
b521931e 1030 found = lib_get_iter_ust_marker(iter);
68c1021b 1031 if (!found)
b521931e 1032 ust_marker_iter_reset(iter);
68c1021b
PMF
1033}
1034
fd0a1aea 1035/* Called with markers mutex held. */
b521931e 1036void ust_marker_iter_start(struct ust_marker_iter *iter)
68c1021b 1037{
b521931e 1038 ust_marker_get_iter(iter);
68c1021b 1039}
68c1021b 1040
fd0a1aea 1041/* Called with markers mutex held. */
b521931e 1042void ust_marker_iter_next(struct ust_marker_iter *iter)
68c1021b 1043{
b521931e 1044 iter->ust_marker++;
68c1021b 1045 /*
b521931e
MD
1046 * iter->ust_marker may be invalid because we blindly incremented it.
1047 * Make sure it is valid by marshalling on the ust_marker, getting the
1048 * ust_marker from following modules if necessary.
68c1021b 1049 */
b521931e 1050 ust_marker_get_iter(iter);
68c1021b 1051}
68c1021b 1052
fd0a1aea 1053/* Called with markers mutex held. */
b521931e 1054void ust_marker_iter_stop(struct ust_marker_iter *iter)
68c1021b
PMF
1055{
1056}
68c1021b 1057
fd0a1aea 1058/* Called with markers mutex held. */
b521931e 1059void ust_marker_iter_reset(struct ust_marker_iter *iter)
68c1021b 1060{
98963de4 1061 iter->lib = NULL;
b521931e 1062 iter->ust_marker = NULL;
68c1021b 1063}
68c1021b 1064
b521931e 1065void ltt_dump_ust_marker_state(struct ust_trace *trace)
9c67dc50 1066{
b521931e 1067 struct ust_marker_entry *entry;
9c67dc50 1068 struct ltt_probe_private_data call_data;
10c56168
DG
1069 struct cds_hlist_head *head;
1070 struct cds_hlist_node *node;
48454c95 1071 unsigned int i;
9c67dc50 1072
b521931e 1073 pthread_mutex_lock(&ust_marker_mutex);
9c67dc50
PMF
1074 call_data.trace = trace;
1075 call_data.serializer = NULL;
1076
5cfbb58f 1077 for (i = 0; i < UST_MARKER_TABLE_SIZE; i++) {
b521931e 1078 head = &ust_marker_table[i];
10c56168 1079 cds_hlist_for_each_entry(entry, node, head, hlist) {
f36c12ab 1080 __ust_marker(metadata, core_marker_id,
9c67dc50 1081 &call_data,
48454c95
PMF
1082 "channel %s name %s event_id %hu "
1083 "int #1u%zu long #1u%zu pointer #1u%zu "
1084 "size_t #1u%zu alignment #1u%u",
1085 entry->channel,
1086 entry->name,
1087 entry->event_id,
1088 sizeof(int), sizeof(long),
1089 sizeof(void *), sizeof(size_t),
1090 ltt_get_alignment());
1091 if (entry->format)
f36c12ab 1092 __ust_marker(metadata,
48454c95
PMF
1093 core_marker_format,
1094 &call_data,
1095 "channel %s name %s format %s",
1096 entry->channel,
1097 entry->name,
1098 entry->format);
1099 }
9c67dc50 1100 }
b521931e 1101 pthread_mutex_unlock(&ust_marker_mutex);
9c67dc50 1102}
98963de4 1103
b521931e 1104static void (*new_ust_marker_cb)(struct ust_marker *) = NULL;
20b37a31 1105
b521931e 1106void ust_marker_set_new_ust_marker_cb(void (*cb)(struct ust_marker *))
20b37a31 1107{
b521931e 1108 new_ust_marker_cb = cb;
20b37a31
PMF
1109}
1110
fd0a1aea
MD
1111static void new_ust_marker(struct ust_marker * const *start,
1112 struct ust_marker * const *end)
20b37a31 1113{
b521931e
MD
1114 if (new_ust_marker_cb) {
1115 struct ust_marker * const *m;
f08ebbe2
MD
1116
1117 for(m = start; m < end; m++) {
1118 if (*m)
b521931e 1119 new_ust_marker_cb(*m);
20b37a31
PMF
1120 }
1121 }
1122}
1123
fd0a1aea
MD
1124int ust_marker_register_lib(struct ust_marker * const *ust_marker_start,
1125 int ust_marker_count)
98963de4 1126{
b521931e 1127 struct ust_marker_lib *pl, *iter;
98963de4 1128
b521931e 1129 pl = (struct ust_marker_lib *) zmalloc(sizeof(struct ust_marker_lib));
98963de4 1130
b521931e
MD
1131 pl->ust_marker_start = ust_marker_start;
1132 pl->ust_marker_count = ust_marker_count;
98963de4 1133
b521931e 1134 lock_ust_marker();
b467f7a7
MD
1135
1136 /*
1137 * We sort the libs by struct lib pointer address.
1138 */
b521931e 1139 cds_list_for_each_entry_reverse(iter, &ust_marker_libs, list) {
b467f7a7
MD
1140 BUG_ON(iter == pl); /* Should never be in the list twice */
1141 if (iter < pl) {
1142 /* We belong to the location right after iter. */
1143 cds_list_add(&pl->list, &iter->list);
1144 goto lib_added;
1145 }
1146 }
1147 /* We should be added at the head of the list */
b521931e 1148 cds_list_add(&pl->list, &ust_marker_libs);
b467f7a7 1149lib_added:
b521931e 1150 unlock_ust_marker();
98963de4 1151
b521931e 1152 new_ust_marker(ust_marker_start, ust_marker_start + ust_marker_count);
20b37a31 1153
fd0a1aea 1154 /* TODO: update just the loaded lib */
b521931e 1155 lib_update_ust_marker();
4db647c5 1156
b521931e 1157 DBG("just registered a ust_marker section from %p and having %d ust_marker (minus dummy ust_marker)", ust_marker_start, ust_marker_count);
98963de4
PMF
1158
1159 return 0;
1160}
c463904d 1161
b521931e 1162int ust_marker_unregister_lib(struct ust_marker * const *ust_marker_start)
0b5207fa 1163{
b521931e 1164 struct ust_marker_lib *lib;
24b6668c 1165
b521931e 1166 lock_ust_marker();
b521931e
MD
1167 cds_list_for_each_entry(lib, &ust_marker_libs, list) {
1168 if(lib->ust_marker_start == ust_marker_start) {
1169 struct ust_marker_lib *lib2free = lib;
0222e121 1170 cds_list_del(&lib->list);
24b6668c
PMF
1171 free(lib2free);
1172 break;
1173 }
1174 }
b521931e 1175 unlock_ust_marker();
24b6668c 1176
0b5207fa
PMF
1177 return 0;
1178}
1179
4db647c5
PMF
1180static int initialized = 0;
1181
b521931e 1182void __attribute__((constructor)) init_ust_marker(void)
c463904d 1183{
900e307e 1184 if (!initialized) {
b521931e
MD
1185 ust_marker_register_lib(__start___ust_marker_ptrs,
1186 __stop___ust_marker_ptrs
1187 - __start___ust_marker_ptrs);
4db647c5
PMF
1188 initialized = 1;
1189 }
c463904d 1190}
24b6668c 1191
b521931e 1192void __attribute__((destructor)) destroy_ust_marker(void)
24b6668c 1193{
b521931e 1194 ust_marker_unregister_lib(__start___ust_marker_ptrs);
24b6668c 1195}
This page took 0.106101 seconds and 4 git commands to generate.