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