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