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