Remove lttng_ust_synchronize_trace public symbol
[lttng-ust.git] / liblttng-ust / lttng-context.c
CommitLineData
8020ceb5 1/*
c0c0989a 2 * SPDX-License-Identifier: LGPL-2.1-only
8020ceb5 3 *
e92f3e28
MD
4 * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
5 *
c0c0989a 6 * LTTng UST trace/channel/event context management.
8020ceb5
MD
7 */
8
3fbec7dc 9#define _LGPL_SOURCE
4318ae1b
MD
10#include <lttng/ust-events.h>
11#include <lttng/ust-tracer.h>
ae4b659d 12#include <ust-context-provider.h>
10544ee8 13#include <lttng/urcu/pointer.h>
b653ddc1 14#include <lttng/urcu/urcu-ust.h>
a0a3bef9 15#include <usterr-signal-safe.h>
864a1eda 16#include <ust-helper.h>
b4051ad8 17#include <stddef.h>
8d8a24c8 18#include <string.h>
8173ec7c 19#include <assert.h>
10544ee8 20#include "tracepoint-internal.h"
8173ec7c 21
51f804ec
FD
22#include "context-internal.h"
23
77aa5901
MD
24/*
25 * The filter implementation requires that two consecutive "get" for the
26 * same context performed by the same thread return the same result.
27 */
28
8173ec7c
MD
29int lttng_find_context(struct lttng_ctx *ctx, const char *name)
30{
31 unsigned int i;
53569322 32 const char *subname;
8173ec7c 33
53569322
MD
34 if (strncmp(name, "$ctx.", strlen("$ctx.")) == 0) {
35 subname = name + strlen("$ctx.");
36 } else {
37 subname = name;
38 }
8173ec7c
MD
39 for (i = 0; i < ctx->nr_fields; i++) {
40 /* Skip allocated (but non-initialized) contexts */
41 if (!ctx->fields[i].event_field.name)
42 continue;
53569322 43 if (!strcmp(ctx->fields[i].event_field.name, subname))
8173ec7c
MD
44 return 1;
45 }
46 return 0;
47}
8020ceb5 48
77aa5901
MD
49int lttng_get_context_index(struct lttng_ctx *ctx, const char *name)
50{
51 unsigned int i;
53569322 52 const char *subname;
77aa5901
MD
53
54 if (!ctx)
55 return -1;
53569322
MD
56 if (strncmp(name, "$ctx.", strlen("$ctx.")) == 0) {
57 subname = name + strlen("$ctx.");
58 } else {
59 subname = name;
60 }
77aa5901
MD
61 for (i = 0; i < ctx->nr_fields; i++) {
62 /* Skip allocated (but non-initialized) contexts */
63 if (!ctx->fields[i].event_field.name)
64 continue;
53569322 65 if (!strcmp(ctx->fields[i].event_field.name, subname))
77aa5901
MD
66 return i;
67 }
68 return -1;
69}
70
53569322
MD
71static int lttng_find_context_provider(struct lttng_ctx *ctx, const char *name)
72{
73 unsigned int i;
74
75 for (i = 0; i < ctx->nr_fields; i++) {
76 /* Skip allocated (but non-initialized) contexts */
77 if (!ctx->fields[i].event_field.name)
78 continue;
79 if (!strncmp(ctx->fields[i].event_field.name, name,
80 strlen(name)))
81 return 1;
82 }
83 return 0;
84}
85
a0a748b8
MD
86/*
87 * Note: as we append context information, the pointer location may change.
88 */
8020ceb5
MD
89struct lttng_ctx_field *lttng_append_context(struct lttng_ctx **ctx_p)
90{
91 struct lttng_ctx_field *field;
92 struct lttng_ctx *ctx;
93
94 if (!*ctx_p) {
8d8a24c8 95 *ctx_p = zmalloc(sizeof(struct lttng_ctx));
8020ceb5
MD
96 if (!*ctx_p)
97 return NULL;
b2cc986a 98 (*ctx_p)->largest_align = 1;
8020ceb5
MD
99 }
100 ctx = *ctx_p;
101 if (ctx->nr_fields + 1 > ctx->allocated_fields) {
102 struct lttng_ctx_field *new_fields;
103
104 ctx->allocated_fields = max_t(size_t, 1, 2 * ctx->allocated_fields);
8d8a24c8 105 new_fields = zmalloc(ctx->allocated_fields * sizeof(struct lttng_ctx_field));
8020ceb5
MD
106 if (!new_fields)
107 return NULL;
108 if (ctx->fields)
109 memcpy(new_fields, ctx->fields, sizeof(*ctx->fields) * ctx->nr_fields);
8d8a24c8 110 free(ctx->fields);
8020ceb5
MD
111 ctx->fields = new_fields;
112 }
113 field = &ctx->fields[ctx->nr_fields];
114 ctx->nr_fields++;
115 return field;
116}
8020ceb5 117
53569322
MD
118int lttng_context_add_rcu(struct lttng_ctx **ctx_p,
119 const struct lttng_ctx_field *f)
120{
121 struct lttng_ctx *old_ctx = *ctx_p, *new_ctx = NULL;
122 struct lttng_ctx_field *new_fields = NULL;
123 struct lttng_ctx_field *nf;
124
125 if (old_ctx) {
126 new_ctx = zmalloc(sizeof(struct lttng_ctx));
127 if (!new_ctx)
128 return -ENOMEM;
129 *new_ctx = *old_ctx;
130 new_fields = zmalloc(new_ctx->allocated_fields
131 * sizeof(struct lttng_ctx_field));
132 if (!new_fields) {
133 free(new_ctx);
134 return -ENOMEM;
135 }
136 memcpy(new_fields, old_ctx->fields,
137 sizeof(*old_ctx->fields) * old_ctx->nr_fields);
138 new_ctx->fields = new_fields;
139 }
140 nf = lttng_append_context(&new_ctx);
141 if (!nf) {
142 free(new_fields);
143 free(new_ctx);
144 return -ENOMEM;
145 }
146 *nf = *f;
147 lttng_context_update(new_ctx);
10544ee8 148 lttng_ust_rcu_assign_pointer(*ctx_p, new_ctx);
b653ddc1 149 lttng_ust_urcu_synchronize_rcu();
53569322
MD
150 if (old_ctx) {
151 free(old_ctx->fields);
152 free(old_ctx);
153 }
154 return 0;
155}
156
b2cc986a
MD
157/*
158 * lttng_context_update() should be called at least once between context
159 * modification and trace start.
160 */
161void lttng_context_update(struct lttng_ctx *ctx)
162{
163 int i;
164 size_t largest_align = 8; /* in bits */
165
166 for (i = 0; i < ctx->nr_fields; i++) {
167 struct lttng_type *type;
168 size_t field_align = 8;
169
170 type = &ctx->fields[i].event_field.type;
171 switch (type->atype) {
172 case atype_integer:
218deb69 173 field_align = type->u.integer.alignment;
b2cc986a
MD
174 break;
175 case atype_array:
176 {
177 struct lttng_basic_type *btype;
178
218deb69 179 btype = &type->u.legacy.array.elem_type;
b2cc986a
MD
180 switch (btype->atype) {
181 case atype_integer:
182 field_align = btype->u.basic.integer.alignment;
183 break;
184 case atype_string:
185 break;
186
187 case atype_array:
218deb69 188 case atype_array_nestable:
b2cc986a 189 case atype_sequence:
218deb69 190 case atype_sequence_nestable:
b2cc986a
MD
191 default:
192 WARN_ON_ONCE(1);
193 break;
194 }
195 break;
196 }
218deb69
MD
197 case atype_array_nestable:
198 {
199 const struct lttng_type *nested_type;
200
201 nested_type = type->u.array_nestable.elem_type;
202 switch (nested_type->atype) {
203 case atype_integer:
204 field_align = nested_type->u.integer.alignment;
205 break;
206 case atype_string:
207 break;
208
209 case atype_array:
210 case atype_array_nestable:
211 case atype_sequence:
212 case atype_sequence_nestable:
213 default:
214 WARN_ON_ONCE(1);
215 break;
216 }
217 field_align = max_t(size_t, field_align,
218 type->u.array_nestable.alignment);
219 break;
220 }
b2cc986a
MD
221 case atype_sequence:
222 {
223 struct lttng_basic_type *btype;
224
218deb69 225 btype = &type->u.legacy.sequence.length_type;
b2cc986a
MD
226 switch (btype->atype) {
227 case atype_integer:
228 field_align = btype->u.basic.integer.alignment;
229 break;
230
231 case atype_string:
232 case atype_array:
218deb69 233 case atype_array_nestable:
b2cc986a 234 case atype_sequence:
218deb69 235 case atype_sequence_nestable:
b2cc986a
MD
236 default:
237 WARN_ON_ONCE(1);
238 break;
239 }
240
218deb69 241 btype = &type->u.legacy.sequence.elem_type;
b2cc986a
MD
242 switch (btype->atype) {
243 case atype_integer:
244 field_align = max_t(size_t,
245 field_align,
246 btype->u.basic.integer.alignment);
247 break;
248
249 case atype_string:
250 break;
251
252 case atype_array:
218deb69
MD
253 case atype_array_nestable:
254 case atype_sequence:
255 case atype_sequence_nestable:
256 default:
257 WARN_ON_ONCE(1);
258 break;
259 }
260 break;
261 }
262 case atype_sequence_nestable:
263 {
264 const struct lttng_type *nested_type;
265
266 nested_type = type->u.sequence_nestable.elem_type;
267 switch (nested_type->atype) {
268 case atype_integer:
269 field_align = nested_type->u.integer.alignment;
270 break;
271
272 case atype_string:
273 break;
274
275 case atype_array:
276 case atype_array_nestable:
b2cc986a 277 case atype_sequence:
218deb69 278 case atype_sequence_nestable:
b2cc986a
MD
279 default:
280 WARN_ON_ONCE(1);
281 break;
282 }
218deb69
MD
283 field_align = max_t(size_t, field_align,
284 type->u.sequence_nestable.alignment);
b2cc986a
MD
285 break;
286 }
287 case atype_string:
288 break;
53569322
MD
289 case atype_dynamic:
290 break;
b2cc986a 291 case atype_enum:
218deb69 292 case atype_enum_nestable:
b2cc986a
MD
293 default:
294 WARN_ON_ONCE(1);
295 break;
296 }
297 largest_align = max_t(size_t, largest_align, field_align);
298 }
299 ctx->largest_align = largest_align >> 3; /* bits to bytes */
300}
301
b13d13b1
MD
302/*
303 * Remove last context field.
304 */
8020ceb5
MD
305void lttng_remove_context_field(struct lttng_ctx **ctx_p,
306 struct lttng_ctx_field *field)
307{
308 struct lttng_ctx *ctx;
309
310 ctx = *ctx_p;
311 ctx->nr_fields--;
8173ec7c 312 assert(&ctx->fields[ctx->nr_fields] == field);
53569322 313 assert(field->field_name == NULL);
8020ceb5
MD
314 memset(&ctx->fields[ctx->nr_fields], 0, sizeof(struct lttng_ctx_field));
315}
8020ceb5
MD
316
317void lttng_destroy_context(struct lttng_ctx *ctx)
318{
319 int i;
320
321 if (!ctx)
322 return;
323 for (i = 0; i < ctx->nr_fields; i++) {
324 if (ctx->fields[i].destroy)
325 ctx->fields[i].destroy(&ctx->fields[i]);
53569322 326 free(ctx->fields[i].field_name);
8020ceb5 327 }
8d8a24c8
MD
328 free(ctx->fields);
329 free(ctx);
8020ceb5 330}
a0a3bef9 331
53569322
MD
332/*
333 * Can be safely performed concurrently with tracing using the struct
334 * lttng_ctx. Using RCU update. Needs to match RCU read-side handling of
335 * contexts.
336 *
337 * This does not allow adding, removing, or changing typing of the
338 * contexts, since this needs to stay invariant for metadata. However,
339 * it allows updating the handlers associated with all contexts matching
340 * a provider (by name) while tracing is using it, in a way that ensures
341 * a single RCU read-side critical section see either all old, or all
342 * new handlers.
343 */
344int lttng_ust_context_set_provider_rcu(struct lttng_ctx **_ctx,
345 const char *name,
346 size_t (*get_size)(struct lttng_ctx_field *field, size_t offset),
347 void (*record)(struct lttng_ctx_field *field,
348 struct lttng_ust_lib_ring_buffer_ctx *ctx,
349 struct lttng_channel *chan),
350 void (*get_value)(struct lttng_ctx_field *field,
351 struct lttng_ctx_value *value))
352{
353 int i, ret;
354 struct lttng_ctx *ctx = *_ctx, *new_ctx;
355 struct lttng_ctx_field *new_fields;
356
357 if (!ctx || !lttng_find_context_provider(ctx, name))
358 return 0;
359 /*
360 * We have at least one instance of context for the provider.
361 */
362 new_ctx = zmalloc(sizeof(*new_ctx));
363 if (!new_ctx)
364 return -ENOMEM;
365 *new_ctx = *ctx;
366 new_fields = zmalloc(sizeof(*new_fields) * ctx->allocated_fields);
367 if (!new_fields) {
368 ret = -ENOMEM;
369 goto field_error;
370 }
371 memcpy(new_fields, ctx->fields,
372 sizeof(*new_fields) * ctx->allocated_fields);
373 for (i = 0; i < ctx->nr_fields; i++) {
374 if (strncmp(new_fields[i].event_field.name,
375 name, strlen(name)) != 0)
376 continue;
377 new_fields[i].get_size = get_size;
378 new_fields[i].record = record;
379 new_fields[i].get_value = get_value;
380 }
381 new_ctx->fields = new_fields;
10544ee8 382 lttng_ust_rcu_assign_pointer(*_ctx, new_ctx);
b653ddc1 383 lttng_ust_urcu_synchronize_rcu();
53569322
MD
384 free(ctx->fields);
385 free(ctx);
386 return 0;
387
388field_error:
389 free(new_ctx);
390 return ret;
391}
392
51f804ec 393int lttng_context_init_all(struct lttng_ctx **ctx)
a0a3bef9
MD
394{
395 int ret;
396
53569322 397 ret = lttng_add_pthread_id_to_ctx(ctx);
a0a3bef9
MD
398 if (ret) {
399 WARN("Cannot add context lttng_add_pthread_id_to_ctx");
53569322 400 goto error;
a0a3bef9 401 }
53569322 402 ret = lttng_add_vtid_to_ctx(ctx);
a0a3bef9
MD
403 if (ret) {
404 WARN("Cannot add context lttng_add_vtid_to_ctx");
53569322 405 goto error;
a0a3bef9 406 }
53569322 407 ret = lttng_add_vpid_to_ctx(ctx);
a0a3bef9
MD
408 if (ret) {
409 WARN("Cannot add context lttng_add_vpid_to_ctx");
53569322 410 goto error;
a0a3bef9 411 }
53569322 412 ret = lttng_add_procname_to_ctx(ctx);
a0a3bef9
MD
413 if (ret) {
414 WARN("Cannot add context lttng_add_procname_to_ctx");
53569322 415 goto error;
a0a3bef9 416 }
53569322 417 ret = lttng_add_cpu_id_to_ctx(ctx);
c7ea8487
MD
418 if (ret) {
419 WARN("Cannot add context lttng_add_cpu_id_to_ctx");
53569322 420 goto error;
c7ea8487 421 }
735bef47
MJ
422 ret = lttng_add_cgroup_ns_to_ctx(ctx);
423 if (ret) {
424 WARN("Cannot add context lttng_add_cgroup_ns_to_ctx");
425 goto error;
426 }
427 ret = lttng_add_ipc_ns_to_ctx(ctx);
428 if (ret) {
429 WARN("Cannot add context lttng_add_ipc_ns_to_ctx");
430 goto error;
431 }
432 ret = lttng_add_mnt_ns_to_ctx(ctx);
433 if (ret) {
434 WARN("Cannot add context lttng_add_mnt_ns_to_ctx");
435 goto error;
436 }
437 ret = lttng_add_net_ns_to_ctx(ctx);
438 if (ret) {
439 WARN("Cannot add context lttng_add_net_ns_to_ctx");
440 goto error;
441 }
442 ret = lttng_add_pid_ns_to_ctx(ctx);
443 if (ret) {
444 WARN("Cannot add context lttng_add_pid_ns_to_ctx");
445 goto error;
446 }
cefef7a7
MJ
447 ret = lttng_add_time_ns_to_ctx(ctx);
448 if (ret) {
449 WARN("Cannot add context lttng_add_time_ns_to_ctx");
450 goto error;
451 }
735bef47
MJ
452 ret = lttng_add_user_ns_to_ctx(ctx);
453 if (ret) {
454 WARN("Cannot add context lttng_add_user_ns_to_ctx");
455 goto error;
456 }
457 ret = lttng_add_uts_ns_to_ctx(ctx);
458 if (ret) {
459 WARN("Cannot add context lttng_add_uts_ns_to_ctx");
460 goto error;
461 }
fca2f191
MJ
462 ret = lttng_add_vuid_to_ctx(ctx);
463 if (ret) {
464 WARN("Cannot add context lttng_add_vuid_to_ctx");
465 goto error;
466 }
467 ret = lttng_add_veuid_to_ctx(ctx);
468 if (ret) {
469 WARN("Cannot add context lttng_add_veuid_to_ctx");
470 goto error;
471 }
472 ret = lttng_add_vsuid_to_ctx(ctx);
473 if (ret) {
474 WARN("Cannot add context lttng_add_vsuid_to_ctx");
475 goto error;
476 }
477 ret = lttng_add_vgid_to_ctx(ctx);
478 if (ret) {
479 WARN("Cannot add context lttng_add_vgid_to_ctx");
480 goto error;
481 }
482 ret = lttng_add_vegid_to_ctx(ctx);
483 if (ret) {
484 WARN("Cannot add context lttng_add_vegid_to_ctx");
485 goto error;
486 }
487 ret = lttng_add_vsgid_to_ctx(ctx);
488 if (ret) {
489 WARN("Cannot add context lttng_add_vsgid_to_ctx");
490 goto error;
491 }
53569322
MD
492 lttng_context_update(*ctx);
493 return 0;
a0a3bef9 494
53569322
MD
495error:
496 lttng_destroy_context(*ctx);
497 return ret;
a0a3bef9 498}
This page took 0.054293 seconds and 4 git commands to generate.