Fix: futex wait: handle spurious futex wakeups
[lttng-tools.git] / src / bin / lttng-sessiond / field.hpp
1 /*
2 * Copyright (C) 2022 Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 */
7
8 #ifndef LTTNG_FIELD_H
9 #define LTTNG_FIELD_H
10
11 #include "trace-class.hpp"
12
13 #include <memory>
14 #include <string>
15 #include <type_traits>
16 #include <vector>
17
18 #include <vendor/optional.hpp>
19
20 namespace lttng {
21 namespace sessiond {
22 namespace trace {
23
24 class field_visitor;
25 class type_visitor;
26
27 /*
28 * Field, and the various field types, represents fields as exposed by the
29 * LTTng tracers. These classes do not attempt to describe the complete spectrum of the CTF
30 * specification.
31 */
32
33 class type {
34 public:
35 using cuptr = std::unique_ptr<const type>;
36
37 static byte_order reverse_byte_order(byte_order byte_order) noexcept;
38
39 bool operator==(const type& other) const noexcept;
40 bool operator!=(const type& other) const noexcept;
41 virtual ~type();
42 virtual void accept(type_visitor& visitor) const = 0;
43
44 const unsigned int alignment;
45
46 protected:
47 type(unsigned int alignment);
48
49 private:
50 virtual bool _is_equal(const type& rhs) const noexcept = 0;
51 };
52
53 class field {
54 public:
55 using cuptr = std::unique_ptr<const field>;
56
57 field(std::string name, type::cuptr type);
58 void accept(field_visitor& visitor) const;
59 bool operator==(const field& other) const noexcept;
60
61 const std::string name;
62 const type::cuptr _type;
63 };
64
65 class integer_type : public type {
66 public:
67 enum class signedness {
68 SIGNED,
69 UNSIGNED,
70 };
71
72 enum class base {
73 BINARY = 2,
74 OCTAL = 8,
75 DECIMAL = 10,
76 HEXADECIMAL = 16,
77 };
78
79 integer_type(unsigned int alignment,
80 byte_order byte_order,
81 unsigned int size,
82 signedness signedness,
83 base base);
84
85 virtual void accept(type_visitor& visitor) const override;
86
87 const enum byte_order byte_order;
88 const unsigned int size;
89 /*
90 * signedness and base are suffixed with '_' to work-around a bug in older
91 * GCCs (before 6) that do not recognize hidden/shadowed enumeration as valid
92 * nested-name-specifiers.
93 */
94 const signedness signedness_;
95 const base base_;
96
97 protected:
98 virtual bool _is_equal(const type& other) const noexcept override;
99 };
100
101 class floating_point_type : public type {
102 public:
103 floating_point_type(unsigned int alignment,
104 byte_order byte_order,
105 unsigned int exponent_digits,
106 unsigned int mantissa_digits);
107
108 virtual void accept(type_visitor& visitor) const override final;
109
110 const enum byte_order byte_order;
111 const unsigned int exponent_digits;
112 const unsigned int mantissa_digits;
113
114 private:
115 virtual bool _is_equal(const type& other) const noexcept override final;
116 };
117
118 class enumeration_type : public integer_type {
119 protected:
120 enumeration_type(unsigned int alignment,
121 enum byte_order byte_order,
122 unsigned int size,
123 enum signedness signedness,
124 enum base base);
125
126 virtual void accept(type_visitor& visitor) const = 0;
127 };
128
129 namespace details {
130 template <class MappingIntegerType>
131 class enumeration_mapping_range {
132 public:
133 using range_integer_t = MappingIntegerType;
134
135 enumeration_mapping_range(MappingIntegerType in_begin, MappingIntegerType in_end) :
136 begin{in_begin}, end{in_end}
137 {
138 }
139
140 const range_integer_t begin, end;
141 };
142
143 template <class MappingIntegerType>
144 bool operator==(const enumeration_mapping_range<MappingIntegerType>& lhs,
145 const enumeration_mapping_range<MappingIntegerType>& rhs) noexcept
146 {
147 return lhs.begin == rhs.begin && lhs.end == rhs.end;
148 }
149
150 template <class MappingIntegerType>
151 class enumeration_mapping {
152 public:
153 using range_t = enumeration_mapping_range<MappingIntegerType>;
154
155 enumeration_mapping(const enumeration_mapping<MappingIntegerType>& other) = delete;
156 enumeration_mapping(const enumeration_mapping<MappingIntegerType>&& other) :
157 name{std::move(other.name)}, range{other.range}
158 {
159 }
160
161 /* Mapping with an implicit value. */
162 enumeration_mapping(std::string in_name) : name{std::move(in_name)}
163 {
164 }
165
166 enumeration_mapping(std::string in_name, range_t in_range) : name{std::move(in_name)}, range{in_range}
167 {
168 }
169
170 const std::string name;
171 const nonstd::optional<range_t> range;
172 };
173
174 template <class MappingIntegerType>
175 bool operator==(const enumeration_mapping<MappingIntegerType>& lhs,
176 const enumeration_mapping<MappingIntegerType>& rhs) noexcept
177 {
178 return lhs.name == rhs.name && lhs.range == rhs.range;
179 }
180 } /* namespace details */
181
182 template <class MappingIntegerType>
183 class typed_enumeration_type : public enumeration_type {
184 public:
185 using mapping = details::enumeration_mapping<MappingIntegerType>;
186 using mappings = std::vector<mapping>;
187
188 static_assert(std::is_integral<MappingIntegerType>::value &&
189 sizeof(MappingIntegerType) == 8,
190 "MappingIntegerType must be either int64_t or uint64_t");
191
192 typed_enumeration_type(unsigned int in_alignment,
193 enum byte_order in_byte_order,
194 unsigned int in_size,
195 enum signedness in_signedness,
196 enum base in_base,
197 const std::shared_ptr<const mappings>& in_mappings) :
198 enumeration_type(in_alignment,
199 in_byte_order,
200 in_size,
201 in_signedness,
202 in_base),
203 _mappings{std::move(in_mappings)}
204 {
205 }
206
207 virtual void accept(type_visitor& visitor) const override final;
208
209 const std::shared_ptr<const mappings> _mappings;
210
211 private:
212 virtual bool _is_equal(const type& base_other) const noexcept override final
213 {
214 const auto& other = static_cast<const typed_enumeration_type<MappingIntegerType>&>(
215 base_other);
216
217 return integer_type::_is_equal(base_other) && *this->_mappings == *other._mappings;
218 }
219 };
220
221 /* Aliases for all allowed enumeration mapping types. */
222 using signed_enumeration_type = typed_enumeration_type<int64_t>;
223 using unsigned_enumeration_type = typed_enumeration_type<uint64_t>;
224
225 class array_type : public type {
226 public:
227 array_type(unsigned int alignment, type::cuptr element_type);
228
229 const type::cuptr element_type;
230
231 protected:
232 virtual bool _is_equal(const type& base_other) const noexcept override;
233 };
234
235 class static_length_array_type : public array_type {
236 public:
237 static_length_array_type(unsigned int alignment,
238 type::cuptr element_type,
239 uint64_t in_length);
240
241 virtual void accept(type_visitor& visitor) const override final;
242
243 const uint64_t length;
244
245 private:
246 virtual bool _is_equal(const type& base_other) const noexcept override final;
247 };
248
249 class dynamic_length_array_type : public array_type {
250 public:
251 dynamic_length_array_type(unsigned int alignment,
252 type::cuptr element_type,
253 std::string length_field_name);
254
255 virtual void accept(type_visitor& visitor) const override final;
256
257 const std::string length_field_name;
258
259 private:
260 virtual bool _is_equal(const type& base_other) const noexcept override final;
261 };
262
263 class string_type : public type {
264 public:
265 enum class encoding {
266 ASCII,
267 UTF8,
268 };
269
270 string_type(unsigned int alignment, enum encoding encoding);
271
272 /*
273 * encoding is suffixed with '_' to work-around a bug in older
274 * GCCs (before 6) that do not recognize hidden/shadowed enumeration as valid
275 * nested-name-specifiers.
276 */
277 const encoding encoding_;
278
279 protected:
280 virtual bool _is_equal(const type& base_other) const noexcept override;
281 };
282
283 class static_length_string_type : public string_type {
284 public:
285 static_length_string_type(
286 unsigned int alignment, enum encoding in_encoding, uint64_t length);
287 virtual void accept(type_visitor& visitor) const override final;
288
289 const uint64_t length;
290
291 private:
292 virtual bool _is_equal(const type& base_other) const noexcept override final;
293 };
294
295 class dynamic_length_string_type : public string_type {
296 public:
297 dynamic_length_string_type(unsigned int alignment,
298 enum encoding in_encoding,
299 std::string length_field_name);
300 virtual void accept(type_visitor& visitor) const override final;
301
302 const std::string length_field_name;
303
304 private:
305 virtual bool _is_equal(const type& base_other) const noexcept override final;
306 };
307
308 class null_terminated_string_type : public string_type {
309 public:
310 null_terminated_string_type(unsigned int alignment, enum encoding in_encoding);
311 virtual void accept(type_visitor& visitor) const override final;
312 };
313
314 class structure_type : public type {
315 public:
316 using fields = std::vector<field::cuptr>;
317
318 structure_type(unsigned int alignment, fields in_fields);
319
320 virtual void accept(type_visitor& visitor) const override final;
321
322 const fields _fields;
323
324 private:
325 virtual bool _is_equal(const type& base_other) const noexcept override final;
326 };
327
328 class variant_type : public type {
329 public:
330 using choices = std::vector<field::cuptr>;
331
332 variant_type(unsigned int alignment, std::string tag_name, choices in_choices);
333
334 virtual void accept(type_visitor& visitor) const override final;
335
336 const std::string tag_name;
337 const choices _choices;
338
339 private:
340 virtual bool _is_equal(const type& base_other) const noexcept override final;
341 };
342
343 class field_visitor {
344 public:
345 virtual ~field_visitor() = default;
346 virtual void visit(const field& field) = 0;
347
348 protected:
349 field_visitor() = default;
350 };
351
352 class type_visitor {
353 public:
354 virtual ~type_visitor() = default;
355 virtual void visit(const integer_type& type) = 0;
356 virtual void visit(const floating_point_type& type) = 0;
357 virtual void visit(const signed_enumeration_type& type) = 0;
358 virtual void visit(const unsigned_enumeration_type& type) = 0;
359 virtual void visit(const static_length_array_type& type) = 0;
360 virtual void visit(const dynamic_length_array_type& type) = 0;
361 virtual void visit(const null_terminated_string_type& type) = 0;
362 virtual void visit(const static_length_string_type& type) = 0;
363 virtual void visit(const dynamic_length_string_type& type) = 0;
364 virtual void visit(const structure_type& type) = 0;
365 virtual void visit(const variant_type& type) = 0;
366
367 protected:
368 type_visitor() = default;
369 };
370
371 } /* namespace trace */
372 } /* namespace sessiond */
373 } /* namespace lttng */
374
375 #endif /* LTTNG_FIELD_H */
This page took 0.036593 seconds and 4 git commands to generate.