Adapt lttng-ust to use multiflavor symbols from liburcu 0.11
[lttng-ust.git] / liblttng-ust / tracepoint.c
CommitLineData
f99be407 1/*
b27f8e75 2 * Copyright (C) 2008-2011 Mathieu Desnoyers
1f8b0dff 3 * Copyright (C) 2009 Pierre-Marc Fournier
f99be407 4 *
34e4b7db
PMF
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
f37142a4
MD
7 * License as published by the Free Software Foundation;
8 * version 2.1 of the License.
f99be407 9 *
34e4b7db 10 * This library is distributed in the hope that it will be useful,
f99be407 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
34e4b7db
PMF
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
f99be407 14 *
34e4b7db
PMF
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1f8b0dff
PMF
18 *
19 * Ported to userspace by Pierre-Marc Fournier.
f99be407 20 */
1f8b0dff 21
b0c4126f 22#define _LGPL_SOURCE
474d745f 23#include <errno.h>
b728d87e
MD
24#include <stdint.h>
25#include <stddef.h>
33661f97 26#include <stdio.h>
44c72f10 27
b728d87e 28#include <urcu/arch.h>
d6ddec3f 29#include <urcu/urcu-bp.h>
10c56168 30#include <urcu/hlist.h>
edaa1431 31#include <urcu/uatomic.h>
b728d87e 32#include <urcu/compiler.h>
c082d14b 33#include <urcu/system.h>
44c72f10
MD
34
35#include <lttng/tracepoint.h>
ff412fb5 36#include <lttng/ust-abi.h> /* for LTTNG_UST_SYM_NAME_LEN */
44c72f10
MD
37
38#include <usterr-signal-safe.h>
35897f8b 39#include <helper.h>
474d745f 40
23c8854a 41#include "tracepoint-internal.h"
7dd08bec 42#include "lttng-tracer-core.h"
596c4223 43#include "jhash.h"
8f3f8c99 44#include "error.h"
b0c4126f 45
5517d34d 46/* Test compiler support for weak symbols with hidden visibility. */
b0e63efd
MD
47int __tracepoint_test_symbol1 __attribute__((weak, visibility("hidden")));
48void *__tracepoint_test_symbol2 __attribute__((weak, visibility("hidden")));
49struct {
50 char a[24];
51} __tracepoint_test_symbol3 __attribute__((weak, visibility("hidden")));
5517d34d 52
f99be407
PMF
53/* Set to 1 to enable tracepoint debug output */
54static const int tracepoint_debug;
b27f8e75 55static int initialized;
0fd0de10
FD
56
57/*
58 * If tracepoint_destructors_state = 1, tracepoint destructors are
59 * enabled. They are disabled otherwise.
60 */
61static int tracepoint_destructors_state = 1;
62
63/*
64 * Expose the now deprecated symbol __tracepoints__disable_destructors for
65 * backward compatibility of applications built against old versions of
66 * lttng-ust. We need to keep __tracepoints__disable_destructors up to date
67 * within the new destructor disabling API because old applications read this
68 * symbol directly.
69 */
70int __tracepoints__disable_destructors __attribute__((weak));
71
1a206094 72static void (*new_tracepoint_cb)(struct lttng_ust_tracepoint *);
f99be407 73
8792fbae
MD
74/*
75 * tracepoint_mutex nests inside UST mutex.
76 *
77 * Note about interaction with fork/clone: UST does not hold the
78 * tracepoint mutex across fork/clone because it is either:
79 * - nested within UST mutex, in which case holding the UST mutex across
80 * fork/clone suffice,
81 * - taken by a library constructor, which should never race with a
82 * fork/clone if the application is expected to continue running with
83 * the same memory layout (no following exec()).
84 */
85static pthread_mutex_t tracepoint_mutex = PTHREAD_MUTEX_INITIALIZER;
86
efa2c591
MD
87/*
88 * libraries that contain tracepoints (struct tracepoint_lib).
8792fbae 89 * Protected by tracepoint mutex.
efa2c591 90 */
0222e121 91static CDS_LIST_HEAD(libs);
474d745f 92
f99be407 93/*
8792fbae 94 * The tracepoint mutex protects the library tracepoints, the hash table, and
17dfb34b 95 * the library list.
8792fbae 96 * All calls to the tracepoint API must be protected by the tracepoint mutex,
17dfb34b 97 * excepts calls to tracepoint_register_lib and
8792fbae 98 * tracepoint_unregister_lib, which take the tracepoint mutex themselves.
f99be407 99 */
f99be407
PMF
100
101/*
102 * Tracepoint hash table, containing the active tracepoints.
8792fbae 103 * Protected by tracepoint mutex.
f99be407 104 */
814f7df1 105#define TRACEPOINT_HASH_BITS 12
f99be407 106#define TRACEPOINT_TABLE_SIZE (1 << TRACEPOINT_HASH_BITS)
10c56168 107static struct cds_hlist_head tracepoint_table[TRACEPOINT_TABLE_SIZE];
f99be407 108
b27f8e75
MD
109static CDS_LIST_HEAD(old_probes);
110static int need_update;
111
baa1e0bc
MD
112static CDS_LIST_HEAD(release_queue);
113static int release_queue_need_update;
114
f99be407
PMF
115/*
116 * Note about RCU :
117 * It is used to to delay the free of multiple probes array until a quiescent
118 * state is reached.
8792fbae 119 * Tracepoint entries modifications are protected by the tracepoint mutex.
f99be407
PMF
120 */
121struct tracepoint_entry {
10c56168 122 struct cds_hlist_node hlist;
1a206094 123 struct lttng_ust_tracepoint_probe *probes;
f99be407 124 int refcount; /* Number of times armed. 0 if disarmed. */
8a7ad54b 125 int callsite_refcount; /* how many libs use this tracepoint */
2c05c691
FD
126 char *signature;
127 char *name;
f99be407
PMF
128};
129
130struct tp_probes {
131 union {
0222e121 132 struct cds_list_head list;
ade7037b
MD
133 /* Field below only used for call_rcu scheme */
134 /* struct rcu_head head; */
f99be407 135 } u;
1a206094 136 struct lttng_ust_tracepoint_probe probes[0];
f99be407
PMF
137};
138
3469bbbe
MD
139/*
140 * Callsite hash table, containing the tracepoint call sites.
141 * Protected by tracepoint mutex.
142 */
143#define CALLSITE_HASH_BITS 12
144#define CALLSITE_TABLE_SIZE (1 << CALLSITE_HASH_BITS)
145static struct cds_hlist_head callsite_table[CALLSITE_TABLE_SIZE];
146
147struct callsite_entry {
148 struct cds_hlist_node hlist; /* hash table node */
149 struct cds_list_head node; /* lib list of callsites node */
1a206094 150 struct lttng_ust_tracepoint *tp;
2c05c691 151 bool tp_entry_callsite_ref; /* Has a tp_entry took a ref on this callsite */
3469bbbe
MD
152};
153
5e6df7ea 154/* coverity[+alloc] */
efa2c591 155static void *allocate_probes(int count)
f99be407 156{
1a206094
SM
157 struct tp_probes *p =
158 zmalloc(count * sizeof(struct lttng_ust_tracepoint_probe)
159 + sizeof(struct tp_probes));
f99be407
PMF
160 return p == NULL ? NULL : p->probes;
161}
162
5e6df7ea 163/* coverity[+free : arg-0] */
efa2c591 164static void release_probes(void *old)
f99be407
PMF
165{
166 if (old) {
b728d87e 167 struct tp_probes *tp_probes = caa_container_of(old,
f99be407 168 struct tp_probes, probes[0]);
d6ddec3f 169 urcu_bp_synchronize_rcu();
909bc43f 170 free(tp_probes);
f99be407
PMF
171 }
172}
173
174static void debug_print_probes(struct tracepoint_entry *entry)
175{
176 int i;
177
9dec086e 178 if (!tracepoint_debug || !entry->probes)
f99be407
PMF
179 return;
180
9dec086e
NC
181 for (i = 0; entry->probes[i].func; i++)
182 DBG("Probe %d : %p", i, entry->probes[i].func);
f99be407
PMF
183}
184
185static void *
9dec086e 186tracepoint_entry_add_probe(struct tracepoint_entry *entry,
fbdeb5ec 187 void (*probe)(void), void *data)
f99be407
PMF
188{
189 int nr_probes = 0;
1a206094 190 struct lttng_ust_tracepoint_probe *old, *new;
f99be407 191
d7509147
MD
192 if (!probe) {
193 WARN_ON(1);
194 return ERR_PTR(-EINVAL);
195 }
f99be407 196 debug_print_probes(entry);
9dec086e 197 old = entry->probes;
f99be407
PMF
198 if (old) {
199 /* (N -> N+1), (N != 0, 1) probes */
9dec086e
NC
200 for (nr_probes = 0; old[nr_probes].func; nr_probes++)
201 if (old[nr_probes].func == probe &&
202 old[nr_probes].data == data)
f99be407
PMF
203 return ERR_PTR(-EEXIST);
204 }
205 /* + 2 : one for new probe, one for NULL func */
206 new = allocate_probes(nr_probes + 2);
207 if (new == NULL)
208 return ERR_PTR(-ENOMEM);
209 if (old)
1a206094
SM
210 memcpy(new, old,
211 nr_probes * sizeof(struct lttng_ust_tracepoint_probe));
9dec086e
NC
212 new[nr_probes].func = probe;
213 new[nr_probes].data = data;
214 new[nr_probes + 1].func = NULL;
f99be407 215 entry->refcount = nr_probes + 1;
9dec086e 216 entry->probes = new;
f99be407
PMF
217 debug_print_probes(entry);
218 return old;
219}
220
221static void *
fbdeb5ec
MD
222tracepoint_entry_remove_probe(struct tracepoint_entry *entry,
223 void (*probe)(void), void *data)
f99be407
PMF
224{
225 int nr_probes = 0, nr_del = 0, i;
1a206094 226 struct lttng_ust_tracepoint_probe *old, *new;
f99be407 227
9dec086e 228 old = entry->probes;
f99be407
PMF
229
230 if (!old)
231 return ERR_PTR(-ENOENT);
232
233 debug_print_probes(entry);
234 /* (N -> M), (N > 1, M >= 0) probes */
956c6fab
MD
235 if (probe) {
236 for (nr_probes = 0; old[nr_probes].func; nr_probes++) {
237 if (old[nr_probes].func == probe &&
238 old[nr_probes].data == data)
239 nr_del++;
240 }
f99be407
PMF
241 }
242
243 if (nr_probes - nr_del == 0) {
244 /* N -> 0, (N > 1) */
9dec086e 245 entry->probes = NULL;
f99be407
PMF
246 entry->refcount = 0;
247 debug_print_probes(entry);
248 return old;
249 } else {
250 int j = 0;
251 /* N -> M, (N > 1, M > 0) */
252 /* + 1 for NULL */
253 new = allocate_probes(nr_probes - nr_del + 1);
254 if (new == NULL)
255 return ERR_PTR(-ENOMEM);
9dec086e 256 for (i = 0; old[i].func; i++)
956c6fab 257 if (old[i].func != probe || old[i].data != data)
f99be407 258 new[j++] = old[i];
9dec086e 259 new[nr_probes - nr_del].func = NULL;
f99be407 260 entry->refcount = nr_probes - nr_del;
9dec086e 261 entry->probes = new;
f99be407
PMF
262 }
263 debug_print_probes(entry);
264 return old;
265}
266
267/*
268 * Get tracepoint if the tracepoint is present in the tracepoint hash table.
8792fbae 269 * Must be called with tracepoint mutex held.
f99be407
PMF
270 * Returns NULL if not present.
271 */
272static struct tracepoint_entry *get_tracepoint(const char *name)
273{
10c56168
DG
274 struct cds_hlist_head *head;
275 struct cds_hlist_node *node;
f99be407 276 struct tracepoint_entry *e;
ff412fb5
MD
277 size_t name_len = strlen(name);
278 uint32_t hash;
f99be407 279
ff412fb5
MD
280 if (name_len > LTTNG_UST_SYM_NAME_LEN - 1) {
281 WARN("Truncating tracepoint name %s which exceeds size limits of %u chars", name, LTTNG_UST_SYM_NAME_LEN - 1);
282 name_len = LTTNG_UST_SYM_NAME_LEN - 1;
283 }
284 hash = jhash(name, name_len, 0);
f99be407 285 head = &tracepoint_table[hash & (TRACEPOINT_TABLE_SIZE - 1)];
10c56168 286 cds_hlist_for_each_entry(e, node, head, hlist) {
ff412fb5 287 if (!strncmp(name, e->name, LTTNG_UST_SYM_NAME_LEN - 1))
f99be407
PMF
288 return e;
289 }
290 return NULL;
291}
292
293/*
294 * Add the tracepoint to the tracepoint hash table. Must be called with
8792fbae 295 * tracepoint mutex held.
f99be407 296 */
67e5f391
MD
297static struct tracepoint_entry *add_tracepoint(const char *name,
298 const char *signature)
f99be407 299{
10c56168
DG
300 struct cds_hlist_head *head;
301 struct cds_hlist_node *node;
f99be407 302 struct tracepoint_entry *e;
ff412fb5 303 size_t name_len = strlen(name);
2c05c691
FD
304 size_t sig_len = strlen(signature);
305 size_t sig_off, name_off;
ff412fb5 306 uint32_t hash;
f99be407 307
ff412fb5
MD
308 if (name_len > LTTNG_UST_SYM_NAME_LEN - 1) {
309 WARN("Truncating tracepoint name %s which exceeds size limits of %u chars", name, LTTNG_UST_SYM_NAME_LEN - 1);
310 name_len = LTTNG_UST_SYM_NAME_LEN - 1;
311 }
312 hash = jhash(name, name_len, 0);
f99be407 313 head = &tracepoint_table[hash & (TRACEPOINT_TABLE_SIZE - 1)];
10c56168 314 cds_hlist_for_each_entry(e, node, head, hlist) {
ff412fb5 315 if (!strncmp(name, e->name, LTTNG_UST_SYM_NAME_LEN - 1)) {
c1f20530 316 DBG("tracepoint %s busy", name);
f99be407
PMF
317 return ERR_PTR(-EEXIST); /* Already there */
318 }
319 }
2c05c691 320
f99be407 321 /*
2c05c691
FD
322 * Using zmalloc here to allocate a variable length elements: name and
323 * signature. Could cause some memory fragmentation if overused.
f99be407 324 */
2c05c691
FD
325 name_off = sizeof(struct tracepoint_entry);
326 sig_off = name_off + name_len + 1;
327
328 e = zmalloc(sizeof(struct tracepoint_entry) + name_len + 1 + sig_len + 1);
f99be407
PMF
329 if (!e)
330 return ERR_PTR(-ENOMEM);
2c05c691
FD
331 e->name = (char *) e + name_off;
332 memcpy(e->name, name, name_len + 1);
ff412fb5 333 e->name[name_len] = '\0';
2c05c691
FD
334
335 e->signature = (char *) e + sig_off;
336 memcpy(e->signature, signature, sig_len + 1);
337 e->signature[sig_len] = '\0';
338
9dec086e 339 e->probes = NULL;
f99be407 340 e->refcount = 0;
8a7ad54b 341 e->callsite_refcount = 0;
2c05c691 342
10c56168 343 cds_hlist_add_head(&e->hlist, head);
f99be407
PMF
344 return e;
345}
346
347/*
348 * Remove the tracepoint from the tracepoint hash table. Must be called with
8792fbae 349 * tracepoint mutex held.
f99be407 350 */
efa2c591 351static void remove_tracepoint(struct tracepoint_entry *e)
f99be407 352{
10c56168 353 cds_hlist_del(&e->hlist);
909bc43f 354 free(e);
f99be407
PMF
355}
356
357/*
358 * Sets the probe callback corresponding to one tracepoint.
359 */
360static void set_tracepoint(struct tracepoint_entry **entry,
1a206094 361 struct lttng_ust_tracepoint *elem, int active)
f99be407 362{
ff412fb5 363 WARN_ON(strncmp((*entry)->name, elem->name, LTTNG_UST_SYM_NAME_LEN - 1) != 0);
67e5f391
MD
364 /*
365 * Check that signatures match before connecting a probe to a
366 * tracepoint. Warn the user if they don't.
367 */
368 if (strcmp(elem->signature, (*entry)->signature) != 0) {
369 static int warned = 0;
370
371 /* Only print once, don't flood console. */
372 if (!warned) {
373 WARN("Tracepoint signature mismatch, not enabling one or more tracepoints. Ensure that the tracepoint probes prototypes match the application.");
374 WARN("Tracepoint \"%s\" signatures: call: \"%s\" vs probe: \"%s\".",
375 elem->name, elem->signature, (*entry)->signature);
376 warned = 1;
377 }
378 /* Don't accept connecting non-matching signatures. */
379 return;
380 }
f99be407
PMF
381
382 /*
0222e121 383 * rcu_assign_pointer has a cmm_smp_wmb() which makes sure that the new
f99be407
PMF
384 * probe callbacks array is consistent before setting a pointer to it.
385 * This array is referenced by __DO_TRACE from
0222e121 386 * include/linux/tracepoints.h. A matching cmm_smp_read_barrier_depends()
f99be407
PMF
387 * is used.
388 */
9dec086e 389 rcu_assign_pointer(elem->probes, (*entry)->probes);
c082d14b 390 CMM_STORE_SHARED(elem->state, active);
f99be407
PMF
391}
392
393/*
394 * Disable a tracepoint and its probe callback.
395 * Note: only waiting an RCU period after setting elem->call to the empty
396 * function insures that the original callback is not used anymore. This insured
397 * by preempt_disable around the call site.
398 */
1a206094 399static void disable_tracepoint(struct lttng_ust_tracepoint *elem)
f99be407 400{
c082d14b 401 CMM_STORE_SHARED(elem->state, 0);
9dec086e 402 rcu_assign_pointer(elem->probes, NULL);
f99be407
PMF
403}
404
33f8ed87
MD
405/*
406 * Add the callsite to the callsite hash table. Must be called with
407 * tracepoint mutex held.
408 */
1a206094 409static void add_callsite(struct tracepoint_lib * lib, struct lttng_ust_tracepoint *tp)
33f8ed87
MD
410{
411 struct cds_hlist_head *head;
412 struct callsite_entry *e;
413 const char *name = tp->name;
414 size_t name_len = strlen(name);
415 uint32_t hash;
8a7ad54b 416 struct tracepoint_entry *tp_entry;
33f8ed87
MD
417
418 if (name_len > LTTNG_UST_SYM_NAME_LEN - 1) {
419 WARN("Truncating tracepoint name %s which exceeds size limits of %u chars", name, LTTNG_UST_SYM_NAME_LEN - 1);
420 name_len = LTTNG_UST_SYM_NAME_LEN - 1;
421 }
422 hash = jhash(name, name_len, 0);
423 head = &callsite_table[hash & (CALLSITE_TABLE_SIZE - 1)];
424 e = zmalloc(sizeof(struct callsite_entry));
d6297168
MD
425 if (!e) {
426 PERROR("Unable to add callsite for tracepoint \"%s\"", name);
427 return;
428 }
33f8ed87
MD
429 cds_hlist_add_head(&e->hlist, head);
430 e->tp = tp;
431 cds_list_add(&e->node, &lib->callsites);
8a7ad54b
IJ
432
433 tp_entry = get_tracepoint(name);
434 if (!tp_entry)
435 return;
436 tp_entry->callsite_refcount++;
2c05c691 437 e->tp_entry_callsite_ref = true;
33f8ed87
MD
438}
439
440/*
441 * Remove the callsite from the callsite hash table and from lib
442 * callsite list. Must be called with tracepoint mutex held.
443 */
444static void remove_callsite(struct callsite_entry *e)
445{
8a7ad54b
IJ
446 struct tracepoint_entry *tp_entry;
447
448 tp_entry = get_tracepoint(e->tp->name);
449 if (tp_entry) {
2c05c691
FD
450 if (e->tp_entry_callsite_ref)
451 tp_entry->callsite_refcount--;
8a7ad54b
IJ
452 if (tp_entry->callsite_refcount == 0)
453 disable_tracepoint(e->tp);
454 }
33f8ed87
MD
455 cds_hlist_del(&e->hlist);
456 cds_list_del(&e->node);
457 free(e);
458}
459
3469bbbe
MD
460/*
461 * Enable/disable all callsites based on the state of a specific
462 * tracepoint entry.
463 * Must be called with tracepoint mutex held.
464 */
465static void tracepoint_sync_callsites(const char *name)
466{
467 struct cds_hlist_head *head;
468 struct cds_hlist_node *node;
469 struct callsite_entry *e;
470 size_t name_len = strlen(name);
471 uint32_t hash;
472 struct tracepoint_entry *tp_entry;
473
474 tp_entry = get_tracepoint(name);
475 if (name_len > LTTNG_UST_SYM_NAME_LEN - 1) {
476 WARN("Truncating tracepoint name %s which exceeds size limits of %u chars", name, LTTNG_UST_SYM_NAME_LEN - 1);
477 name_len = LTTNG_UST_SYM_NAME_LEN - 1;
478 }
479 hash = jhash(name, name_len, 0);
480 head = &callsite_table[hash & (CALLSITE_TABLE_SIZE - 1)];
481 cds_hlist_for_each_entry(e, node, head, hlist) {
1a206094 482 struct lttng_ust_tracepoint *tp = e->tp;
3469bbbe
MD
483
484 if (strncmp(name, tp->name, LTTNG_UST_SYM_NAME_LEN - 1))
485 continue;
486 if (tp_entry) {
2c05c691
FD
487 if (!e->tp_entry_callsite_ref) {
488 tp_entry->callsite_refcount++;
489 e->tp_entry_callsite_ref = true;
490 }
3469bbbe
MD
491 set_tracepoint(&tp_entry, tp,
492 !!tp_entry->refcount);
493 } else {
494 disable_tracepoint(tp);
2c05c691 495 e->tp_entry_callsite_ref = false;
3469bbbe
MD
496 }
497 }
498}
499
f99be407
PMF
500/**
501 * tracepoint_update_probe_range - Update a probe range
502 * @begin: beginning of the range
503 * @end: end of the range
504 *
505 * Updates the probe callback corresponding to a range of tracepoints.
506 */
b27f8e75 507static
1a206094
SM
508void tracepoint_update_probe_range(struct lttng_ust_tracepoint * const *begin,
509 struct lttng_ust_tracepoint * const *end)
f99be407 510{
1a206094 511 struct lttng_ust_tracepoint * const *iter;
f99be407
PMF
512 struct tracepoint_entry *mark_entry;
513
f99be407 514 for (iter = begin; iter < end; iter++) {
f08ebbe2
MD
515 if (!*iter)
516 continue; /* skip dummy */
f218ff28
MD
517 if (!(*iter)->name) {
518 disable_tracepoint(*iter);
9dec086e
NC
519 continue;
520 }
f218ff28 521 mark_entry = get_tracepoint((*iter)->name);
f99be407 522 if (mark_entry) {
f218ff28 523 set_tracepoint(&mark_entry, *iter,
f99be407
PMF
524 !!mark_entry->refcount);
525 } else {
f218ff28 526 disable_tracepoint(*iter);
f99be407
PMF
527 }
528 }
f99be407
PMF
529}
530
5da10905 531static void lib_update_tracepoints(struct tracepoint_lib *lib)
772030fe 532{
5da10905
MD
533 tracepoint_update_probe_range(lib->tracepoints_start,
534 lib->tracepoints_start + lib->tracepoints_count);
772030fe
PMF
535}
536
3469bbbe
MD
537static void lib_register_callsites(struct tracepoint_lib *lib)
538{
1a206094
SM
539 struct lttng_ust_tracepoint * const *begin;
540 struct lttng_ust_tracepoint * const *end;
541 struct lttng_ust_tracepoint * const *iter;
3469bbbe
MD
542
543 begin = lib->tracepoints_start;
544 end = lib->tracepoints_start + lib->tracepoints_count;
545
546 for (iter = begin; iter < end; iter++) {
547 if (!*iter)
548 continue; /* skip dummy */
549 if (!(*iter)->name) {
550 continue;
551 }
60d87029 552 add_callsite(lib, *iter);
3469bbbe
MD
553 }
554}
555
556static void lib_unregister_callsites(struct tracepoint_lib *lib)
557{
558 struct callsite_entry *callsite, *tmp;
559
560 cds_list_for_each_entry_safe(callsite, tmp, &lib->callsites, node)
561 remove_callsite(callsite);
562}
563
f99be407
PMF
564/*
565 * Update probes, removing the faulty probes.
566 */
567static void tracepoint_update_probes(void)
568{
5da10905
MD
569 struct tracepoint_lib *lib;
570
b27f8e75 571 /* tracepoints registered from libraries and executable. */
5da10905
MD
572 cds_list_for_each_entry(lib, &libs, list)
573 lib_update_tracepoints(lib);
f99be407
PMF
574}
575
1a206094 576static struct lttng_ust_tracepoint_probe *
fbdeb5ec 577tracepoint_add_probe(const char *name, void (*probe)(void), void *data,
67e5f391 578 const char *signature)
f99be407
PMF
579{
580 struct tracepoint_entry *entry;
1a206094 581 struct lttng_ust_tracepoint_probe *old;
f99be407
PMF
582
583 entry = get_tracepoint(name);
2c05c691
FD
584 if (entry) {
585 if (strcmp(entry->signature, signature) != 0) {
586 ERR("Tracepoint and probe signature do not match.");
587 return ERR_PTR(-EINVAL);
588 }
589 } else {
67e5f391 590 entry = add_tracepoint(name, signature);
f99be407 591 if (IS_ERR(entry))
1a206094 592 return (struct lttng_ust_tracepoint_probe *)entry;
f99be407 593 }
9dec086e 594 old = tracepoint_entry_add_probe(entry, probe, data);
f99be407
PMF
595 if (IS_ERR(old) && !entry->refcount)
596 remove_tracepoint(entry);
597 return old;
598}
599
baa1e0bc
MD
600static void tracepoint_release_queue_add_old_probes(void *old)
601{
602 release_queue_need_update = 1;
603 if (old) {
604 struct tp_probes *tp_probes = caa_container_of(old,
605 struct tp_probes, probes[0]);
606 cds_list_add(&tp_probes->u.list, &release_queue);
607 }
608}
609
f99be407 610/**
81614639 611 * __tracepoint_probe_register - Connect a probe to a tracepoint
f99be407
PMF
612 * @name: tracepoint name
613 * @probe: probe handler
614 *
615 * Returns 0 if ok, error value on error.
616 * The probe address must at least be aligned on the architecture pointer size.
8792fbae 617 * Called with the tracepoint mutex held.
f99be407 618 */
fbdeb5ec
MD
619int __tracepoint_probe_register(const char *name, void (*probe)(void),
620 void *data, const char *signature)
f99be407
PMF
621{
622 void *old;
8792fbae 623 int ret = 0;
f99be407 624
05780d81
MD
625 DBG("Registering probe to tracepoint %s", name);
626
8792fbae 627 pthread_mutex_lock(&tracepoint_mutex);
67e5f391 628 old = tracepoint_add_probe(name, probe, data, signature);
8792fbae
MD
629 if (IS_ERR(old)) {
630 ret = PTR_ERR(old);
631 goto end;
632 }
f99be407 633
3469bbbe 634 tracepoint_sync_callsites(name);
f99be407 635 release_probes(old);
8792fbae
MD
636end:
637 pthread_mutex_unlock(&tracepoint_mutex);
638 return ret;
f99be407 639}
f99be407 640
baa1e0bc
MD
641/*
642 * Caller needs to invoke __tracepoint_probe_release_queue() after
643 * calling __tracepoint_probe_register_queue_release() one or multiple
644 * times to ensure it does not leak memory.
645 */
646int __tracepoint_probe_register_queue_release(const char *name,
647 void (*probe)(void), void *data, const char *signature)
648{
649 void *old;
650 int ret = 0;
651
652 DBG("Registering probe to tracepoint %s. Queuing release.", name);
653
654 pthread_mutex_lock(&tracepoint_mutex);
655 old = tracepoint_add_probe(name, probe, data, signature);
656 if (IS_ERR(old)) {
657 ret = PTR_ERR(old);
658 goto end;
659 }
660
661 tracepoint_sync_callsites(name);
662 tracepoint_release_queue_add_old_probes(old);
663end:
664 pthread_mutex_unlock(&tracepoint_mutex);
665 return ret;
666}
667
fbdeb5ec
MD
668static void *tracepoint_remove_probe(const char *name, void (*probe)(void),
669 void *data)
f99be407
PMF
670{
671 struct tracepoint_entry *entry;
672 void *old;
673
674 entry = get_tracepoint(name);
675 if (!entry)
676 return ERR_PTR(-ENOENT);
9dec086e 677 old = tracepoint_entry_remove_probe(entry, probe, data);
f99be407
PMF
678 if (IS_ERR(old))
679 return old;
680 if (!entry->refcount)
681 remove_tracepoint(entry);
682 return old;
683}
684
685/**
686 * tracepoint_probe_unregister - Disconnect a probe from a tracepoint
687 * @name: tracepoint name
688 * @probe: probe function pointer
9dec086e 689 * @probe: probe data pointer
f99be407 690 */
fbdeb5ec
MD
691int __tracepoint_probe_unregister(const char *name, void (*probe)(void),
692 void *data)
f99be407
PMF
693{
694 void *old;
8792fbae 695 int ret = 0;
f99be407 696
05780d81
MD
697 DBG("Un-registering probe from tracepoint %s", name);
698
8792fbae 699 pthread_mutex_lock(&tracepoint_mutex);
9dec086e 700 old = tracepoint_remove_probe(name, probe, data);
8792fbae
MD
701 if (IS_ERR(old)) {
702 ret = PTR_ERR(old);
703 goto end;
704 }
3469bbbe 705 tracepoint_sync_callsites(name);
f99be407 706 release_probes(old);
8792fbae
MD
707end:
708 pthread_mutex_unlock(&tracepoint_mutex);
709 return ret;
f99be407 710}
f99be407 711
baa1e0bc
MD
712/*
713 * Caller needs to invoke __tracepoint_probe_release_queue() after
714 * calling __tracepoint_probe_unregister_queue_release() one or multiple
715 * times to ensure it does not leak memory.
716 */
717int __tracepoint_probe_unregister_queue_release(const char *name,
718 void (*probe)(void), void *data)
719{
720 void *old;
721 int ret = 0;
722
723 DBG("Un-registering probe from tracepoint %s. Queuing release.", name);
724
725 pthread_mutex_lock(&tracepoint_mutex);
726 old = tracepoint_remove_probe(name, probe, data);
727 if (IS_ERR(old)) {
728 ret = PTR_ERR(old);
729 goto end;
730 }
731 tracepoint_sync_callsites(name);
732 tracepoint_release_queue_add_old_probes(old);
733end:
734 pthread_mutex_unlock(&tracepoint_mutex);
735 return ret;
736}
737
738void __tracepoint_probe_prune_release_queue(void)
739{
740 CDS_LIST_HEAD(release_probes);
741 struct tp_probes *pos, *next;
742
743 DBG("Release queue of unregistered tracepoint probes.");
744
745 pthread_mutex_lock(&tracepoint_mutex);
746 if (!release_queue_need_update)
747 goto end;
748 if (!cds_list_empty(&release_queue))
749 cds_list_replace_init(&release_queue, &release_probes);
750 release_queue_need_update = 0;
751
752 /* Wait for grace period between all sync_callsites and free. */
d6ddec3f 753 urcu_bp_synchronize_rcu();
baa1e0bc
MD
754
755 cds_list_for_each_entry_safe(pos, next, &release_probes, u.list) {
756 cds_list_del(&pos->u.list);
757 free(pos);
758 }
759end:
760 pthread_mutex_unlock(&tracepoint_mutex);
761}
762
f99be407
PMF
763static void tracepoint_add_old_probes(void *old)
764{
765 need_update = 1;
766 if (old) {
b728d87e 767 struct tp_probes *tp_probes = caa_container_of(old,
f99be407 768 struct tp_probes, probes[0]);
0222e121 769 cds_list_add(&tp_probes->u.list, &old_probes);
f99be407
PMF
770 }
771}
772
773/**
774 * tracepoint_probe_register_noupdate - register a probe but not connect
775 * @name: tracepoint name
776 * @probe: probe handler
777 *
778 * caller must call tracepoint_probe_update_all()
779 */
fbdeb5ec 780int tracepoint_probe_register_noupdate(const char *name, void (*probe)(void),
67e5f391 781 void *data, const char *signature)
f99be407
PMF
782{
783 void *old;
8792fbae 784 int ret = 0;
f99be407 785
8792fbae 786 pthread_mutex_lock(&tracepoint_mutex);
67e5f391 787 old = tracepoint_add_probe(name, probe, data, signature);
f99be407 788 if (IS_ERR(old)) {
8792fbae
MD
789 ret = PTR_ERR(old);
790 goto end;
f99be407
PMF
791 }
792 tracepoint_add_old_probes(old);
8792fbae
MD
793end:
794 pthread_mutex_unlock(&tracepoint_mutex);
795 return ret;
f99be407 796}
f99be407
PMF
797
798/**
799 * tracepoint_probe_unregister_noupdate - remove a probe but not disconnect
800 * @name: tracepoint name
801 * @probe: probe function pointer
802 *
803 * caller must call tracepoint_probe_update_all()
8792fbae 804 * Called with the tracepoint mutex held.
f99be407 805 */
fbdeb5ec 806int tracepoint_probe_unregister_noupdate(const char *name, void (*probe)(void),
9dec086e 807 void *data)
f99be407
PMF
808{
809 void *old;
8792fbae 810 int ret = 0;
f99be407 811
05780d81
MD
812 DBG("Un-registering probe from tracepoint %s", name);
813
8792fbae 814 pthread_mutex_lock(&tracepoint_mutex);
9dec086e 815 old = tracepoint_remove_probe(name, probe, data);
f99be407 816 if (IS_ERR(old)) {
8792fbae
MD
817 ret = PTR_ERR(old);
818 goto end;
f99be407
PMF
819 }
820 tracepoint_add_old_probes(old);
8792fbae
MD
821end:
822 pthread_mutex_unlock(&tracepoint_mutex);
823 return ret;
f99be407 824}
f99be407
PMF
825
826/**
827 * tracepoint_probe_update_all - update tracepoints
828 */
829void tracepoint_probe_update_all(void)
830{
0222e121 831 CDS_LIST_HEAD(release_probes);
f99be407
PMF
832 struct tp_probes *pos, *next;
833
8792fbae 834 pthread_mutex_lock(&tracepoint_mutex);
f99be407 835 if (!need_update) {
8792fbae 836 goto end;
f99be407 837 }
0222e121
MD
838 if (!cds_list_empty(&old_probes))
839 cds_list_replace_init(&old_probes, &release_probes);
f99be407 840 need_update = 0;
f99be407
PMF
841
842 tracepoint_update_probes();
baa1e0bc 843 /* Wait for grace period between update_probes and free. */
d6ddec3f 844 urcu_bp_synchronize_rcu();
0222e121
MD
845 cds_list_for_each_entry_safe(pos, next, &release_probes, u.list) {
846 cds_list_del(&pos->u.list);
909bc43f 847 free(pos);
f99be407 848 }
8792fbae
MD
849end:
850 pthread_mutex_unlock(&tracepoint_mutex);
f99be407 851}
f99be407 852
1a206094 853void tracepoint_set_new_tracepoint_cb(void (*cb)(struct lttng_ust_tracepoint *))
474d745f
PMF
854{
855 new_tracepoint_cb = cb;
856}
f99be407 857
1a206094
SM
858static void new_tracepoints(struct lttng_ust_tracepoint * const *start,
859 struct lttng_ust_tracepoint * const *end)
f99be407 860{
f218ff28 861 if (new_tracepoint_cb) {
1a206094 862 struct lttng_ust_tracepoint * const *t;
f08ebbe2 863
b27f8e75 864 for (t = start; t < end; t++) {
f08ebbe2
MD
865 if (*t)
866 new_tracepoint_cb(*t);
474d745f
PMF
867 }
868 }
f99be407 869}
f99be407 870
1a206094 871int tracepoint_register_lib(struct lttng_ust_tracepoint * const *tracepoints_start,
b27f8e75 872 int tracepoints_count)
474d745f 873{
b467f7a7 874 struct tracepoint_lib *pl, *iter;
474d745f 875
edaa1431
MD
876 init_tracepoint();
877
1dba3e6c 878 pl = (struct tracepoint_lib *) zmalloc(sizeof(struct tracepoint_lib));
d6297168
MD
879 if (!pl) {
880 PERROR("Unable to register tracepoint lib");
881 return -1;
882 }
474d745f
PMF
883 pl->tracepoints_start = tracepoints_start;
884 pl->tracepoints_count = tracepoints_count;
3469bbbe 885 CDS_INIT_LIST_HEAD(&pl->callsites);
474d745f 886
8792fbae 887 pthread_mutex_lock(&tracepoint_mutex);
b467f7a7
MD
888 /*
889 * We sort the libs by struct lib pointer address.
890 */
891 cds_list_for_each_entry_reverse(iter, &libs, list) {
892 BUG_ON(iter == pl); /* Should never be in the list twice */
893 if (iter < pl) {
894 /* We belong to the location right after iter. */
895 cds_list_add(&pl->list, &iter->list);
896 goto lib_added;
897 }
898 }
899 /* We should be added at the head of the list */
0222e121 900 cds_list_add(&pl->list, &libs);
b467f7a7 901lib_added:
474d745f 902 new_tracepoints(tracepoints_start, tracepoints_start + tracepoints_count);
3469bbbe 903 lib_register_callsites(pl);
5da10905 904 lib_update_tracepoints(pl);
8792fbae 905 pthread_mutex_unlock(&tracepoint_mutex);
474d745f 906
1fcf7ad7
MD
907 DBG("just registered a tracepoints section from %p and having %d tracepoints",
908 tracepoints_start, tracepoints_count);
05780d81
MD
909 if (ust_debug()) {
910 int i;
911
912 for (i = 0; i < tracepoints_count; i++) {
913 DBG("registered tracepoint: %s", tracepoints_start[i]->name);
914 }
915 }
9dec086e 916
474d745f
PMF
917 return 0;
918}
919
1a206094 920int tracepoint_unregister_lib(struct lttng_ust_tracepoint * const *tracepoints_start)
474d745f 921{
24b6668c
PMF
922 struct tracepoint_lib *lib;
923
8792fbae 924 pthread_mutex_lock(&tracepoint_mutex);
0222e121 925 cds_list_for_each_entry(lib, &libs, list) {
3469bbbe
MD
926 if (lib->tracepoints_start != tracepoints_start)
927 continue;
1622ba22 928
3469bbbe
MD
929 cds_list_del(&lib->list);
930 /*
8a7ad54b
IJ
931 * Unregistering a callsite also decreases the
932 * callsite reference count of the corresponding
933 * tracepoint, and disables the tracepoint if
934 * the reference count drops to zero.
3469bbbe 935 */
3469bbbe
MD
936 lib_unregister_callsites(lib);
937 DBG("just unregistered a tracepoints section from %p",
938 lib->tracepoints_start);
939 free(lib);
940 break;
24b6668c 941 }
8792fbae 942 pthread_mutex_unlock(&tracepoint_mutex);
474d745f
PMF
943 return 0;
944}
b27f8e75 945
5517d34d
MD
946/*
947 * Report in debug message whether the compiler correctly supports weak
948 * hidden symbols. This test checks that the address associated with two
949 * weak symbols with hidden visibility is the same when declared within
950 * two compile units part of the same module.
951 */
952static void check_weak_hidden(void)
953{
b0e63efd
MD
954 DBG("Your compiler treats weak symbols with hidden visibility for integer objects as %s between compile units part of the same module.",
955 &__tracepoint_test_symbol1 == lttng_ust_tp_check_weak_hidden1() ?
956 "SAME address" :
957 "DIFFERENT addresses");
958 DBG("Your compiler treats weak symbols with hidden visibility for pointer objects as %s between compile units part of the same module.",
959 &__tracepoint_test_symbol2 == lttng_ust_tp_check_weak_hidden2() ?
960 "SAME address" :
961 "DIFFERENT addresses");
962 DBG("Your compiler treats weak symbols with hidden visibility for 24-byte structure objects as %s between compile units part of the same module.",
963 &__tracepoint_test_symbol3 == lttng_ust_tp_check_weak_hidden3() ?
964 "SAME address" :
965 "DIFFERENT addresses");
5517d34d
MD
966}
967
edaa1431 968void init_tracepoint(void)
b27f8e75 969{
edaa1431
MD
970 if (uatomic_xchg(&initialized, 1) == 1)
971 return;
5e96a467 972 init_usterr();
5517d34d 973 check_weak_hidden();
b27f8e75
MD
974}
975
edaa1431 976void exit_tracepoint(void)
b27f8e75 977{
17dfb34b 978 initialized = 0;
b27f8e75 979}
40b2b5a4
MD
980
981/*
982 * Create the wrapper symbols.
983 */
984#undef tp_rcu_read_lock_bp
985#undef tp_rcu_read_unlock_bp
986#undef tp_rcu_dereference_bp
987
988void tp_rcu_read_lock_bp(void)
989{
d6ddec3f 990 urcu_bp_read_lock();
40b2b5a4
MD
991}
992
993void tp_rcu_read_unlock_bp(void)
994{
d6ddec3f 995 urcu_bp_read_unlock();
40b2b5a4
MD
996}
997
998void *tp_rcu_dereference_sym_bp(void *p)
999{
d6ddec3f 1000 return urcu_bp_dereference(p);
40b2b5a4 1001}
0fd0de10
FD
1002
1003/*
1004 * Programs that have threads that survive after they exit, and therefore call
1005 * library destructors, should disable the tracepoint destructors by calling
1006 * tp_disable_destructors(). This will leak the tracepoint
1007 * instrumentation library shared object, leaving its teardown to the operating
1008 * system process teardown.
1009 *
1010 * To access and/or modify this value, users need to use a combination of
1011 * dlopen(3) and dlsym(3) to get an handle on the
1012 * tp_disable_destructors and tp_get_destructors_state symbols below.
1013 */
1014void tp_disable_destructors(void)
1015{
1016 uatomic_set(&tracepoint_destructors_state, 0);
1017}
1018
1019/*
1020 * Returns 1 if the destructors are enabled and should be executed.
1021 * Returns 0 if the destructors are disabled.
1022 */
1023int tp_get_destructors_state(void)
1024{
1025 return uatomic_read(&tracepoint_destructors_state);
1026}
This page took 0.086345 seconds and 4 git commands to generate.