Fix: context alignment not properly handled
[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
e92f3e28 23
4318ae1b
MD
24#include <lttng/ust-events.h>
25#include <lttng/ust-tracer.h>
a0a3bef9 26#include <usterr-signal-safe.h>
35897f8b 27#include <helper.h>
8d8a24c8 28#include <string.h>
8173ec7c
MD
29#include <assert.h>
30
77aa5901
MD
31/*
32 * The filter implementation requires that two consecutive "get" for the
33 * same context performed by the same thread return the same result.
34 */
35
a0a3bef9
MD
36/*
37 * Static array of contexts, for $ctx filters.
38 */
39struct lttng_ctx *lttng_static_ctx;
40
8173ec7c
MD
41int lttng_find_context(struct lttng_ctx *ctx, const char *name)
42{
43 unsigned int i;
44
45 for (i = 0; i < ctx->nr_fields; i++) {
46 /* Skip allocated (but non-initialized) contexts */
47 if (!ctx->fields[i].event_field.name)
48 continue;
49 if (!strcmp(ctx->fields[i].event_field.name, name))
50 return 1;
51 }
52 return 0;
53}
8020ceb5 54
77aa5901
MD
55int lttng_get_context_index(struct lttng_ctx *ctx, const char *name)
56{
57 unsigned int i;
58
59 if (!ctx)
60 return -1;
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;
65 if (!strcmp(ctx->fields[i].event_field.name, name))
66 return i;
67 }
68 return -1;
69}
70
a0a748b8
MD
71/*
72 * Note: as we append context information, the pointer location may change.
73 */
8020ceb5
MD
74struct lttng_ctx_field *lttng_append_context(struct lttng_ctx **ctx_p)
75{
76 struct lttng_ctx_field *field;
77 struct lttng_ctx *ctx;
78
79 if (!*ctx_p) {
8d8a24c8 80 *ctx_p = zmalloc(sizeof(struct lttng_ctx));
8020ceb5
MD
81 if (!*ctx_p)
82 return NULL;
7a6e8f36 83 (*ctx_p)->largest_align = 1;
8020ceb5
MD
84 }
85 ctx = *ctx_p;
86 if (ctx->nr_fields + 1 > ctx->allocated_fields) {
87 struct lttng_ctx_field *new_fields;
88
89 ctx->allocated_fields = max_t(size_t, 1, 2 * ctx->allocated_fields);
8d8a24c8 90 new_fields = zmalloc(ctx->allocated_fields * sizeof(struct lttng_ctx_field));
8020ceb5
MD
91 if (!new_fields)
92 return NULL;
93 if (ctx->fields)
94 memcpy(new_fields, ctx->fields, sizeof(*ctx->fields) * ctx->nr_fields);
8d8a24c8 95 free(ctx->fields);
8020ceb5
MD
96 ctx->fields = new_fields;
97 }
98 field = &ctx->fields[ctx->nr_fields];
99 ctx->nr_fields++;
100 return field;
101}
8020ceb5 102
7a6e8f36
MD
103/*
104 * lttng_context_update() should be called at least once between context
105 * modification and trace start.
106 */
107void lttng_context_update(struct lttng_ctx *ctx)
108{
109 int i;
110 size_t largest_align = 8; /* in bits */
111
112 for (i = 0; i < ctx->nr_fields; i++) {
113 struct lttng_type *type;
114 size_t field_align = 8;
115
116 type = &ctx->fields[i].event_field.type;
117 switch (type->atype) {
118 case atype_integer:
119 field_align = type->u.basic.integer.alignment;
120 break;
121 case atype_array:
122 {
123 struct lttng_basic_type *btype;
124
125 btype = &type->u.array.elem_type;
126 switch (btype->atype) {
127 case atype_integer:
128 field_align = btype->u.basic.integer.alignment;
129 break;
130 case atype_string:
131 break;
132
133 case atype_array:
134 case atype_sequence:
135 default:
136 WARN_ON_ONCE(1);
137 break;
138 }
139 break;
140 }
141 case atype_sequence:
142 {
143 struct lttng_basic_type *btype;
144
145 btype = &type->u.sequence.length_type;
146 switch (btype->atype) {
147 case atype_integer:
148 field_align = btype->u.basic.integer.alignment;
149 break;
150
151 case atype_string:
152 case atype_array:
153 case atype_sequence:
154 default:
155 WARN_ON_ONCE(1);
156 break;
157 }
158
159 btype = &type->u.sequence.elem_type;
160 switch (btype->atype) {
161 case atype_integer:
162 field_align = max_t(size_t,
163 field_align,
164 btype->u.basic.integer.alignment);
165 break;
166
167 case atype_string:
168 break;
169
170 case atype_array:
171 case atype_sequence:
172 default:
173 WARN_ON_ONCE(1);
174 break;
175 }
176 break;
177 }
178 case atype_string:
179 break;
180
181 case atype_enum:
182 default:
183 WARN_ON_ONCE(1);
184 break;
185 }
186 largest_align = max_t(size_t, largest_align, field_align);
187 }
188 ctx->largest_align = largest_align >> 3; /* bits to bytes */
189}
190
b13d13b1
MD
191/*
192 * Remove last context field.
193 */
8020ceb5
MD
194void lttng_remove_context_field(struct lttng_ctx **ctx_p,
195 struct lttng_ctx_field *field)
196{
197 struct lttng_ctx *ctx;
198
199 ctx = *ctx_p;
200 ctx->nr_fields--;
8173ec7c 201 assert(&ctx->fields[ctx->nr_fields] == field);
8020ceb5
MD
202 memset(&ctx->fields[ctx->nr_fields], 0, sizeof(struct lttng_ctx_field));
203}
8020ceb5
MD
204
205void lttng_destroy_context(struct lttng_ctx *ctx)
206{
207 int i;
208
209 if (!ctx)
210 return;
211 for (i = 0; i < ctx->nr_fields; i++) {
212 if (ctx->fields[i].destroy)
213 ctx->fields[i].destroy(&ctx->fields[i]);
214 }
8d8a24c8
MD
215 free(ctx->fields);
216 free(ctx);
8020ceb5 217}
a0a3bef9
MD
218
219void lttng_context_init(void)
220{
221 int ret;
222
223 ret = lttng_add_pthread_id_to_ctx(&lttng_static_ctx);
224 if (ret) {
225 WARN("Cannot add context lttng_add_pthread_id_to_ctx");
226 }
227 ret = lttng_add_vtid_to_ctx(&lttng_static_ctx);
228 if (ret) {
229 WARN("Cannot add context lttng_add_vtid_to_ctx");
230 }
231 ret = lttng_add_vpid_to_ctx(&lttng_static_ctx);
232 if (ret) {
233 WARN("Cannot add context lttng_add_vpid_to_ctx");
234 }
235 ret = lttng_add_procname_to_ctx(&lttng_static_ctx);
236 if (ret) {
237 WARN("Cannot add context lttng_add_procname_to_ctx");
238 }
239}
240
241void lttng_context_exit(void)
242{
243 lttng_destroy_context(lttng_static_ctx);
244 lttng_static_ctx = NULL;
245}
This page took 0.03967 seconds and 4 git commands to generate.