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