1 // Copyright 2020 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 //==============================================================================
15 //
16 
17 #pragma once
18 
19 #include <stdbool.h>
20 #include <stddef.h>
21 #include <stdint.h>
22 
23 #include "pw_preprocessor/arguments.h"
24 #include "pw_preprocessor/util.h"
25 
26 // Because __FUNCTION__ is not a string literal to the preprocessor it can't be
27 // tokenized. So this backend redefines the implementation to instead use the
28 // file name and line number.
29 // TODO(rgoliver): A build step could be added which checks the token dictionary
30 // for these and uses add2line to replace the database with the function names.
31 #define PW_TRACE_FUNCTION_LABEL_FILE_LINE(file, line) \
32   "[" PW_STRINGIFY(file) ":" PW_STRINGIFY(line) "]"
33 #define PW_TRACE_FUNCTION_LABEL \
34   PW_TRACE_FUNCTION_LABEL_FILE_LINE(__FILE__, __LINE__)
35 
36 // Enable these trace types
37 #define PW_TRACE_TYPE_INSTANT PW_TRACE_EVENT_TYPE_INSTANT
38 #define PW_TRACE_TYPE_INSTANT_GROUP PW_TRACE_EVENT_TYPE_INSTANT_GROUP
39 
40 #define PW_TRACE_TYPE_DURATION_START PW_TRACE_EVENT_TYPE_DURATION_START
41 #define PW_TRACE_TYPE_DURATION_END PW_TRACE_EVENT_TYPE_DURATION_END
42 
43 #define PW_TRACE_TYPE_DURATION_GROUP_START \
44   PW_TRACE_EVENT_TYPE_DURATION_GROUP_START
45 #define PW_TRACE_TYPE_DURATION_GROUP_END PW_TRACE_EVENT_TYPE_DURATION_GROUP_END
46 
47 #define PW_TRACE_TYPE_ASYNC_START PW_TRACE_EVENT_TYPE_ASYNC_START
48 #define PW_TRACE_TYPE_ASYNC_INSTANT PW_TRACE_EVENT_TYPE_ASYNC_STEP
49 #define PW_TRACE_TYPE_ASYNC_END PW_TRACE_EVENT_TYPE_ASYNC_END
50 
51 PW_EXTERN_C_START
52 
53 typedef enum {
54   PW_TRACE_EVENT_TYPE_INVALID = 0,
55   PW_TRACE_EVENT_TYPE_INSTANT = 1,
56   PW_TRACE_EVENT_TYPE_INSTANT_GROUP = 2,
57   PW_TRACE_EVENT_TYPE_ASYNC_START = 3,
58   PW_TRACE_EVENT_TYPE_ASYNC_STEP = 4,
59   PW_TRACE_EVENT_TYPE_ASYNC_END = 5,
60   PW_TRACE_EVENT_TYPE_DURATION_START = 6,
61   PW_TRACE_EVENT_TYPE_DURATION_END = 7,
62   PW_TRACE_EVENT_TYPE_DURATION_GROUP_START = 8,
63   PW_TRACE_EVENT_TYPE_DURATION_GROUP_END = 9,
64 } pw_trace_EventType;
65 
66 typedef struct {
67   uint32_t trace_token;
68   pw_trace_EventType event_type;
69   const char* module;
70   uint8_t flags;
71   uint32_t trace_id;
72   size_t data_size;
73   const void* data_buffer;
74 } pw_trace_tokenized_TraceEvent;
75 
76 // This should not be called directly, instead use the PW_TRACE_* macros.
77 void pw_trace_TraceEvent(uint32_t trace_token,
78                          pw_trace_EventType event_type,
79                          const char* module,
80                          uint32_t trace_id,
81                          uint8_t flags,
82                          const void* data_buffer,
83                          size_t data_size);
84 
85 // This should not be called directly, insted: PW_TRACE_SET_ENABLED
86 void pw_trace_Enable(bool enabled);
87 
88 // Returns true if tracing is currently enabled.
89 bool pw_trace_IsEnabled(void);
90 
91 PW_EXTERN_C_END
92 
93 // These are what the facade actually calls.
94 #define PW_TRACE(event_type, flags, label, group, trace_id)                  \
95   do {                                                                       \
96     static const uint32_t kLabelToken =                                      \
97         PW_TRACE_REF(event_type, PW_TRACE_MODULE_NAME, label, flags, group); \
98     pw_trace_TraceEvent(kLabelToken,                                         \
99                         event_type,                                          \
100                         PW_TRACE_MODULE_NAME,                                \
101                         trace_id,                                            \
102                         flags,                                               \
103                         NULL,                                                \
104                         0);                                                  \
105   } while (0)
106 
107 #define PW_TRACE_DATA(                                                \
108     event_type, flags, label, group, trace_id, type, data, size)      \
109   do {                                                                \
110     static const uint32_t kLabelToken = PW_TRACE_REF_DATA(            \
111         event_type, PW_TRACE_MODULE_NAME, label, flags, group, type); \
112     pw_trace_TraceEvent(kLabelToken,                                  \
113                         event_type,                                   \
114                         PW_TRACE_MODULE_NAME,                         \
115                         trace_id,                                     \
116                         flags,                                        \
117                         data,                                         \
118                         size);                                        \
119   } while (0)
120