Fix: context alignment not properly handled
[lttng-modules.git] / lttng-context.c
... / ...
CommitLineData
1/*
2 * lttng-context.c
3 *
4 * LTTng trace/channel/event context management.
5 *
6 * Copyright (C) 2011-2012 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#include <linux/module.h>
24#include <linux/list.h>
25#include <linux/mutex.h>
26#include <linux/slab.h>
27#include "wrapper/vmalloc.h" /* for wrapper_vmalloc_sync_all() */
28#include "lttng-events.h"
29#include "lttng-tracer.h"
30
31int lttng_find_context(struct lttng_ctx *ctx, const char *name)
32{
33 unsigned int i;
34
35 for (i = 0; i < ctx->nr_fields; i++) {
36 /* Skip allocated (but non-initialized) contexts */
37 if (!ctx->fields[i].event_field.name)
38 continue;
39 if (!strcmp(ctx->fields[i].event_field.name, name))
40 return 1;
41 }
42 return 0;
43}
44EXPORT_SYMBOL_GPL(lttng_find_context);
45
46/*
47 * Note: as we append context information, the pointer location may change.
48 */
49struct lttng_ctx_field *lttng_append_context(struct lttng_ctx **ctx_p)
50{
51 struct lttng_ctx_field *field;
52 struct lttng_ctx *ctx;
53
54 if (!*ctx_p) {
55 *ctx_p = kzalloc(sizeof(struct lttng_ctx), GFP_KERNEL);
56 if (!*ctx_p)
57 return NULL;
58 (*ctx_p)->largest_align = 1;
59 }
60 ctx = *ctx_p;
61 if (ctx->nr_fields + 1 > ctx->allocated_fields) {
62 struct lttng_ctx_field *new_fields;
63
64 ctx->allocated_fields = max_t(size_t, 1, 2 * ctx->allocated_fields);
65 new_fields = kzalloc(ctx->allocated_fields * sizeof(struct lttng_ctx_field), GFP_KERNEL);
66 if (!new_fields)
67 return NULL;
68 if (ctx->fields)
69 memcpy(new_fields, ctx->fields, sizeof(*ctx->fields) * ctx->nr_fields);
70 kfree(ctx->fields);
71 ctx->fields = new_fields;
72 }
73 field = &ctx->fields[ctx->nr_fields];
74 ctx->nr_fields++;
75 return field;
76}
77EXPORT_SYMBOL_GPL(lttng_append_context);
78
79/*
80 * lttng_context_update() should be called at least once between context
81 * modification and trace start.
82 */
83void lttng_context_update(struct lttng_ctx *ctx)
84{
85 int i;
86 size_t largest_align = 8; /* in bits */
87
88 for (i = 0; i < ctx->nr_fields; i++) {
89 struct lttng_type *type;
90 size_t field_align = 8;
91
92 type = &ctx->fields[i].event_field.type;
93 switch (type->atype) {
94 case atype_integer:
95 field_align = type->u.basic.integer.alignment;
96 break;
97 case atype_array:
98 {
99 struct lttng_basic_type *btype;
100
101 btype = &type->u.array.elem_type;
102 switch (btype->atype) {
103 case atype_integer:
104 field_align = btype->u.basic.integer.alignment;
105 break;
106 case atype_string:
107 break;
108
109 case atype_array:
110 case atype_sequence:
111 default:
112 WARN_ON_ONCE(1);
113 break;
114 }
115 break;
116 }
117 case atype_sequence:
118 {
119 struct lttng_basic_type *btype;
120
121 btype = &type->u.sequence.length_type;
122 switch (btype->atype) {
123 case atype_integer:
124 field_align = btype->u.basic.integer.alignment;
125 break;
126
127 case atype_string:
128 case atype_array:
129 case atype_sequence:
130 default:
131 WARN_ON_ONCE(1);
132 break;
133 }
134
135 btype = &type->u.sequence.elem_type;
136 switch (btype->atype) {
137 case atype_integer:
138 field_align = max_t(size_t,
139 field_align,
140 btype->u.basic.integer.alignment);
141 break;
142
143 case atype_string:
144 break;
145
146 case atype_array:
147 case atype_sequence:
148 default:
149 WARN_ON_ONCE(1);
150 break;
151 }
152 break;
153 }
154 case atype_string:
155 break;
156
157 case atype_enum:
158 default:
159 WARN_ON_ONCE(1);
160 break;
161 }
162 largest_align = max_t(size_t, largest_align, field_align);
163 }
164 ctx->largest_align = largest_align >> 3; /* bits to bytes */
165}
166
167/*
168 * Remove last context field.
169 */
170void lttng_remove_context_field(struct lttng_ctx **ctx_p,
171 struct lttng_ctx_field *field)
172{
173 struct lttng_ctx *ctx;
174
175 ctx = *ctx_p;
176 ctx->nr_fields--;
177 WARN_ON_ONCE(&ctx->fields[ctx->nr_fields] != field);
178 memset(&ctx->fields[ctx->nr_fields], 0, sizeof(struct lttng_ctx_field));
179}
180EXPORT_SYMBOL_GPL(lttng_remove_context_field);
181
182void lttng_destroy_context(struct lttng_ctx *ctx)
183{
184 int i;
185
186 if (!ctx)
187 return;
188 for (i = 0; i < ctx->nr_fields; i++) {
189 if (ctx->fields[i].destroy)
190 ctx->fields[i].destroy(&ctx->fields[i]);
191 }
192 kfree(ctx->fields);
193 kfree(ctx);
194}
This page took 0.037937 seconds and 4 git commands to generate.