Fix: context alignment not properly handled
[lttng-ust.git] / liblttng-ust / lttng-context.c
1 /*
2 * lttng-context.c
3 *
4 * LTTng UST trace/channel/event context management.
5 *
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
21 */
22
23
24 #include <lttng/ust-events.h>
25 #include <lttng/ust-tracer.h>
26 #include <usterr-signal-safe.h>
27 #include <helper.h>
28 #include <string.h>
29 #include <assert.h>
30
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
36 /*
37 * Static array of contexts, for $ctx filters.
38 */
39 struct lttng_ctx *lttng_static_ctx;
40
41 int 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 }
54
55 int 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
71 /*
72 * Note: as we append context information, the pointer location may change.
73 */
74 struct 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) {
80 *ctx_p = zmalloc(sizeof(struct lttng_ctx));
81 if (!*ctx_p)
82 return NULL;
83 (*ctx_p)->largest_align = 1;
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);
90 new_fields = zmalloc(ctx->allocated_fields * sizeof(struct lttng_ctx_field));
91 if (!new_fields)
92 return NULL;
93 if (ctx->fields)
94 memcpy(new_fields, ctx->fields, sizeof(*ctx->fields) * ctx->nr_fields);
95 free(ctx->fields);
96 ctx->fields = new_fields;
97 }
98 field = &ctx->fields[ctx->nr_fields];
99 ctx->nr_fields++;
100 return field;
101 }
102
103 /*
104 * lttng_context_update() should be called at least once between context
105 * modification and trace start.
106 */
107 void 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
191 /*
192 * Remove last context field.
193 */
194 void 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--;
201 assert(&ctx->fields[ctx->nr_fields] == field);
202 memset(&ctx->fields[ctx->nr_fields], 0, sizeof(struct lttng_ctx_field));
203 }
204
205 void 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 }
215 free(ctx->fields);
216 free(ctx);
217 }
218
219 void 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
241 void lttng_context_exit(void)
242 {
243 lttng_destroy_context(lttng_static_ctx);
244 lttng_static_ctx = NULL;
245 }
This page took 0.034229 seconds and 4 git commands to generate.