lttng-ust(3): fix alignment and indentation
[lttng-ust.git] / liblttng-ust / lttng-context.c
CommitLineData
8020ceb5 1/*
e92f3e28 2 * lttng-context.c
8020ceb5 3 *
8173ec7c 4 * LTTng UST trace/channel/event context management.
8020ceb5 5 *
e92f3e28
MD
6 * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; only
11 * version 2.1 of the License.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
8020ceb5
MD
21 */
22
3fbec7dc 23#define _LGPL_SOURCE
4318ae1b
MD
24#include <lttng/ust-events.h>
25#include <lttng/ust-tracer.h>
53569322
MD
26#include <lttng/ust-context-provider.h>
27#include <urcu-pointer.h>
a0a3bef9 28#include <usterr-signal-safe.h>
35897f8b 29#include <helper.h>
8d8a24c8 30#include <string.h>
8173ec7c
MD
31#include <assert.h>
32
77aa5901
MD
33/*
34 * The filter implementation requires that two consecutive "get" for the
35 * same context performed by the same thread return the same result.
36 */
37
8173ec7c
MD
38int lttng_find_context(struct lttng_ctx *ctx, const char *name)
39{
40 unsigned int i;
53569322 41 const char *subname;
8173ec7c 42
53569322
MD
43 if (strncmp(name, "$ctx.", strlen("$ctx.")) == 0) {
44 subname = name + strlen("$ctx.");
45 } else {
46 subname = name;
47 }
8173ec7c
MD
48 for (i = 0; i < ctx->nr_fields; i++) {
49 /* Skip allocated (but non-initialized) contexts */
50 if (!ctx->fields[i].event_field.name)
51 continue;
53569322 52 if (!strcmp(ctx->fields[i].event_field.name, subname))
8173ec7c
MD
53 return 1;
54 }
55 return 0;
56}
8020ceb5 57
77aa5901
MD
58int lttng_get_context_index(struct lttng_ctx *ctx, const char *name)
59{
60 unsigned int i;
53569322 61 const char *subname;
77aa5901
MD
62
63 if (!ctx)
64 return -1;
53569322
MD
65 if (strncmp(name, "$ctx.", strlen("$ctx.")) == 0) {
66 subname = name + strlen("$ctx.");
67 } else {
68 subname = name;
69 }
77aa5901
MD
70 for (i = 0; i < ctx->nr_fields; i++) {
71 /* Skip allocated (but non-initialized) contexts */
72 if (!ctx->fields[i].event_field.name)
73 continue;
53569322 74 if (!strcmp(ctx->fields[i].event_field.name, subname))
77aa5901
MD
75 return i;
76 }
77 return -1;
78}
79
53569322
MD
80static int lttng_find_context_provider(struct lttng_ctx *ctx, const char *name)
81{
82 unsigned int i;
83
84 for (i = 0; i < ctx->nr_fields; i++) {
85 /* Skip allocated (but non-initialized) contexts */
86 if (!ctx->fields[i].event_field.name)
87 continue;
88 if (!strncmp(ctx->fields[i].event_field.name, name,
89 strlen(name)))
90 return 1;
91 }
92 return 0;
93}
94
a0a748b8
MD
95/*
96 * Note: as we append context information, the pointer location may change.
97 */
8020ceb5
MD
98struct lttng_ctx_field *lttng_append_context(struct lttng_ctx **ctx_p)
99{
100 struct lttng_ctx_field *field;
101 struct lttng_ctx *ctx;
102
103 if (!*ctx_p) {
8d8a24c8 104 *ctx_p = zmalloc(sizeof(struct lttng_ctx));
8020ceb5
MD
105 if (!*ctx_p)
106 return NULL;
b2cc986a 107 (*ctx_p)->largest_align = 1;
8020ceb5
MD
108 }
109 ctx = *ctx_p;
110 if (ctx->nr_fields + 1 > ctx->allocated_fields) {
111 struct lttng_ctx_field *new_fields;
112
113 ctx->allocated_fields = max_t(size_t, 1, 2 * ctx->allocated_fields);
8d8a24c8 114 new_fields = zmalloc(ctx->allocated_fields * sizeof(struct lttng_ctx_field));
8020ceb5
MD
115 if (!new_fields)
116 return NULL;
117 if (ctx->fields)
118 memcpy(new_fields, ctx->fields, sizeof(*ctx->fields) * ctx->nr_fields);
8d8a24c8 119 free(ctx->fields);
8020ceb5
MD
120 ctx->fields = new_fields;
121 }
122 field = &ctx->fields[ctx->nr_fields];
123 ctx->nr_fields++;
124 return field;
125}
8020ceb5 126
53569322
MD
127int lttng_context_add_rcu(struct lttng_ctx **ctx_p,
128 const struct lttng_ctx_field *f)
129{
130 struct lttng_ctx *old_ctx = *ctx_p, *new_ctx = NULL;
131 struct lttng_ctx_field *new_fields = NULL;
132 struct lttng_ctx_field *nf;
133
134 if (old_ctx) {
135 new_ctx = zmalloc(sizeof(struct lttng_ctx));
136 if (!new_ctx)
137 return -ENOMEM;
138 *new_ctx = *old_ctx;
139 new_fields = zmalloc(new_ctx->allocated_fields
140 * sizeof(struct lttng_ctx_field));
141 if (!new_fields) {
142 free(new_ctx);
143 return -ENOMEM;
144 }
145 memcpy(new_fields, old_ctx->fields,
146 sizeof(*old_ctx->fields) * old_ctx->nr_fields);
147 new_ctx->fields = new_fields;
148 }
149 nf = lttng_append_context(&new_ctx);
150 if (!nf) {
151 free(new_fields);
152 free(new_ctx);
153 return -ENOMEM;
154 }
155 *nf = *f;
156 lttng_context_update(new_ctx);
157 rcu_assign_pointer(*ctx_p, new_ctx);
158 synchronize_trace();
159 if (old_ctx) {
160 free(old_ctx->fields);
161 free(old_ctx);
162 }
163 return 0;
164}
165
b2cc986a
MD
166/*
167 * lttng_context_update() should be called at least once between context
168 * modification and trace start.
169 */
170void lttng_context_update(struct lttng_ctx *ctx)
171{
172 int i;
173 size_t largest_align = 8; /* in bits */
174
175 for (i = 0; i < ctx->nr_fields; i++) {
176 struct lttng_type *type;
177 size_t field_align = 8;
178
179 type = &ctx->fields[i].event_field.type;
180 switch (type->atype) {
181 case atype_integer:
182 field_align = type->u.basic.integer.alignment;
183 break;
184 case atype_array:
185 {
186 struct lttng_basic_type *btype;
187
188 btype = &type->u.array.elem_type;
189 switch (btype->atype) {
190 case atype_integer:
191 field_align = btype->u.basic.integer.alignment;
192 break;
193 case atype_string:
194 break;
195
196 case atype_array:
197 case atype_sequence:
198 default:
199 WARN_ON_ONCE(1);
200 break;
201 }
202 break;
203 }
204 case atype_sequence:
205 {
206 struct lttng_basic_type *btype;
207
208 btype = &type->u.sequence.length_type;
209 switch (btype->atype) {
210 case atype_integer:
211 field_align = btype->u.basic.integer.alignment;
212 break;
213
214 case atype_string:
215 case atype_array:
216 case atype_sequence:
217 default:
218 WARN_ON_ONCE(1);
219 break;
220 }
221
222 btype = &type->u.sequence.elem_type;
223 switch (btype->atype) {
224 case atype_integer:
225 field_align = max_t(size_t,
226 field_align,
227 btype->u.basic.integer.alignment);
228 break;
229
230 case atype_string:
231 break;
232
233 case atype_array:
234 case atype_sequence:
235 default:
236 WARN_ON_ONCE(1);
237 break;
238 }
239 break;
240 }
241 case atype_string:
242 break;
53569322
MD
243 case atype_dynamic:
244 break;
b2cc986a
MD
245 case atype_enum:
246 default:
247 WARN_ON_ONCE(1);
248 break;
249 }
250 largest_align = max_t(size_t, largest_align, field_align);
251 }
252 ctx->largest_align = largest_align >> 3; /* bits to bytes */
253}
254
b13d13b1
MD
255/*
256 * Remove last context field.
257 */
8020ceb5
MD
258void lttng_remove_context_field(struct lttng_ctx **ctx_p,
259 struct lttng_ctx_field *field)
260{
261 struct lttng_ctx *ctx;
262
263 ctx = *ctx_p;
264 ctx->nr_fields--;
8173ec7c 265 assert(&ctx->fields[ctx->nr_fields] == field);
53569322 266 assert(field->field_name == NULL);
8020ceb5
MD
267 memset(&ctx->fields[ctx->nr_fields], 0, sizeof(struct lttng_ctx_field));
268}
8020ceb5
MD
269
270void lttng_destroy_context(struct lttng_ctx *ctx)
271{
272 int i;
273
274 if (!ctx)
275 return;
276 for (i = 0; i < ctx->nr_fields; i++) {
277 if (ctx->fields[i].destroy)
278 ctx->fields[i].destroy(&ctx->fields[i]);
53569322 279 free(ctx->fields[i].field_name);
8020ceb5 280 }
8d8a24c8
MD
281 free(ctx->fields);
282 free(ctx);
8020ceb5 283}
a0a3bef9 284
53569322
MD
285/*
286 * Can be safely performed concurrently with tracing using the struct
287 * lttng_ctx. Using RCU update. Needs to match RCU read-side handling of
288 * contexts.
289 *
290 * This does not allow adding, removing, or changing typing of the
291 * contexts, since this needs to stay invariant for metadata. However,
292 * it allows updating the handlers associated with all contexts matching
293 * a provider (by name) while tracing is using it, in a way that ensures
294 * a single RCU read-side critical section see either all old, or all
295 * new handlers.
296 */
297int lttng_ust_context_set_provider_rcu(struct lttng_ctx **_ctx,
298 const char *name,
299 size_t (*get_size)(struct lttng_ctx_field *field, size_t offset),
300 void (*record)(struct lttng_ctx_field *field,
301 struct lttng_ust_lib_ring_buffer_ctx *ctx,
302 struct lttng_channel *chan),
303 void (*get_value)(struct lttng_ctx_field *field,
304 struct lttng_ctx_value *value))
305{
306 int i, ret;
307 struct lttng_ctx *ctx = *_ctx, *new_ctx;
308 struct lttng_ctx_field *new_fields;
309
310 if (!ctx || !lttng_find_context_provider(ctx, name))
311 return 0;
312 /*
313 * We have at least one instance of context for the provider.
314 */
315 new_ctx = zmalloc(sizeof(*new_ctx));
316 if (!new_ctx)
317 return -ENOMEM;
318 *new_ctx = *ctx;
319 new_fields = zmalloc(sizeof(*new_fields) * ctx->allocated_fields);
320 if (!new_fields) {
321 ret = -ENOMEM;
322 goto field_error;
323 }
324 memcpy(new_fields, ctx->fields,
325 sizeof(*new_fields) * ctx->allocated_fields);
326 for (i = 0; i < ctx->nr_fields; i++) {
327 if (strncmp(new_fields[i].event_field.name,
328 name, strlen(name)) != 0)
329 continue;
330 new_fields[i].get_size = get_size;
331 new_fields[i].record = record;
332 new_fields[i].get_value = get_value;
333 }
334 new_ctx->fields = new_fields;
335 rcu_assign_pointer(*_ctx, new_ctx);
336 synchronize_trace();
337 free(ctx->fields);
338 free(ctx);
339 return 0;
340
341field_error:
342 free(new_ctx);
343 return ret;
344}
345
346int lttng_session_context_init(struct lttng_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 }
53569322
MD
375 lttng_context_update(*ctx);
376 return 0;
a0a3bef9 377
53569322
MD
378error:
379 lttng_destroy_context(*ctx);
380 return ret;
a0a3bef9 381}
4a1f7569
MD
382
383/* For backward compatibility. Leave those exported symbols in place. */
384struct lttng_ctx *lttng_static_ctx;
385
386void lttng_context_init(void)
387{
388}
389
390void lttng_context_exit(void)
391{
392}
This page took 0.046797 seconds and 4 git commands to generate.