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