1 // Copyright 2017 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 //
6 // Field declarations for the trace record format.
7 //
8 
9 #pragma once
10 
11 #include <trace-engine/types.h>
12 
13 #ifdef __cplusplus
14 
15 #include <type_traits>
16 
17 namespace trace {
18 
Pad(size_t size)19 inline constexpr size_t Pad(size_t size) {
20     return size + ((8 - (size & 7)) & 7);
21 }
22 
BytesToWords(size_t num_bytes)23 inline constexpr size_t BytesToWords(size_t num_bytes) {
24     return Pad(num_bytes) / sizeof(uint64_t);
25 }
26 
WordsToBytes(size_t num_words)27 inline constexpr size_t WordsToBytes(size_t num_words) {
28     return num_words * sizeof(uint64_t);
29 }
30 
31 // Casts an enum's value to its underlying type.
32 template <typename T>
ToUnderlyingType(T value)33 inline constexpr typename std::underlying_type<T>::type ToUnderlyingType(T value) {
34     return static_cast<typename std::underlying_type<T>::type>(value);
35 }
36 
37 // Describes the layout of a bit-field packed into a 64-bit word.
38 template <size_t begin, size_t end>
39 struct Field {
40     static_assert(begin < sizeof(uint64_t) * 8, "begin is out of bounds");
41     static_assert(end < sizeof(uint64_t) * 8, "end is out of bounds");
42     static_assert(begin <= end, "begin must not be larger than end");
43     static_assert(end - begin + 1 < 64, "must be a part of a word, not a whole word");
44 
45     static constexpr uint64_t kMask = (uint64_t(1) << (end - begin + 1)) - 1;
46 
MakeField47     static constexpr uint64_t Make(uint64_t value) { return value << begin; }
48 
49     template <typename U>
GetField50     static constexpr U Get(uint64_t word) {
51         return static_cast<U>((word >> begin) & kMask);
52     }
53 
SetField54     static constexpr void Set(uint64_t& word, uint64_t value) {
55         word = (word & ~(kMask << begin)) | (value << begin);
56     }
57 };
58 
59 struct ArgumentFields {
60     using Type = Field<0, 3>;
61     using ArgumentSize = Field<4, 15>;
62     using NameRef = Field<16, 31>;
63 };
64 
65 struct Int32ArgumentFields : ArgumentFields {
66     using Value = Field<32, 63>;
67 };
68 
69 struct Uint32ArgumentFields : ArgumentFields {
70     using Value = Field<32, 63>;
71 };
72 
73 struct StringArgumentFields : ArgumentFields {
74     using Index = Field<32, 47>;
75 };
76 
77 struct RecordFields {
78     static constexpr size_t kMaxRecordSizeWords = 0xfff;
79     static constexpr size_t kMaxRecordSizeBytes = WordsToBytes(kMaxRecordSizeWords);
80 
81     using Type = Field<0, 3>;
82     using RecordSize = Field<4, 15>;
83 };
84 
85 struct MetadataRecordFields : RecordFields {
86     using MetadataType = Field<16, 19>;
87 };
88 
89 struct ProviderInfoMetadataRecordFields : MetadataRecordFields {
90     static constexpr size_t kMaxNameLength = 0xff;
91 
92     using Id = Field<20, 51>;
93     using NameLength = Field<52, 59>;
94 };
95 
96 struct ProviderSectionMetadataRecordFields : MetadataRecordFields {
97     using Id = Field<20, 51>;
98 };
99 
100 struct ProviderEventMetadataRecordFields : MetadataRecordFields {
101     using Id = Field<20, 51>;
102     using Event = Field<52, 55>;
103 };
104 
105 using InitializationRecordFields = RecordFields;
106 
107 struct StringRecordFields : RecordFields {
108     using StringIndex = Field<16, 30>;
109     using StringLength = Field<32, 46>;
110 };
111 
112 struct ThreadRecordFields : RecordFields {
113     using ThreadIndex = Field<16, 23>;
114 };
115 
116 struct EventRecordFields : RecordFields {
117     using EventType = Field<16, 19>;
118     using ArgumentCount = Field<20, 23>;
119     using ThreadRef = Field<24, 31>;
120     using CategoryStringRef = Field<32, 47>;
121     using NameStringRef = Field<48, 63>;
122 };
123 
124 struct BlobRecordFields : RecordFields {
125     using NameStringRef = Field<16, 31>;
126     using BlobSize = Field<32, 46>;
127     using BlobType = Field<48, 55>;
128 };
129 
130 struct KernelObjectRecordFields : RecordFields {
131     using ObjectType = Field<16, 23>;
132     using NameStringRef = Field<24, 39>;
133     using ArgumentCount = Field<40, 43>;
134 };
135 
136 struct ContextSwitchRecordFields : RecordFields {
137     using CpuNumber = Field<16, 23>;
138     using OutgoingThreadState = Field<24, 27>;
139     using OutgoingThreadRef = Field<28, 35>;
140     using IncomingThreadRef = Field<36, 43>;
141     using OutgoingThreadPriority = Field<44, 51>;
142     using IncomingThreadPriority = Field<52, 59>;
143 };
144 
145 struct LogRecordFields : RecordFields {
146     static constexpr size_t kMaxMessageLength = 0x7fff;
147     using LogMessageLength = Field<16, 30>;
148     using ThreadRef = Field<32, 39>;
149 };
150 
151 } // namespace trace
152 
153 #endif // __cplusplus
154