• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 The Dawn Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://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,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 // Trace events are for tracking application performance and resource usage.
16 // Macros are provided to track:
17 //    Begin and end of function calls
18 //    Counters
19 //
20 // Events are issued against categories. Whereas LOG's
21 // categories are statically defined, TRACE categories are created
22 // implicitly with a string. For example:
23 //   TRACE_EVENT_INSTANT0("MY_SUBSYSTEM", "SomeImportantEvent")
24 //
25 // Events can be INSTANT, or can be pairs of BEGIN and END in the same scope:
26 //   TRACE_EVENT_BEGIN0("MY_SUBSYSTEM", "SomethingCostly")
27 //   doSomethingCostly()
28 //   TRACE_EVENT_END0("MY_SUBSYSTEM", "SomethingCostly")
29 // Note: our tools can't always determine the correct BEGIN/END pairs unless
30 // these are used in the same scope. Use ASYNC_BEGIN/ASYNC_END macros if you need them
31 // to be in separate scopes.
32 //
33 // A common use case is to trace entire function scopes. This
34 // issues a trace BEGIN and END automatically:
35 //   void doSomethingCostly() {
36 //     TRACE_EVENT0("MY_SUBSYSTEM", "doSomethingCostly");
37 //     ...
38 //   }
39 //
40 // Additional parameters can be associated with an event:
41 //   void doSomethingCostly2(int howMuch) {
42 //     TRACE_EVENT1("MY_SUBSYSTEM", "doSomethingCostly",
43 //         "howMuch", howMuch);
44 //     ...
45 //   }
46 //
47 // The trace system will automatically add to this information the
48 // current process id, thread id, and a timestamp in microseconds.
49 //
50 // To trace an asynchronous procedure such as an IPC send/receive, use ASYNC_BEGIN and
51 // ASYNC_END:
52 //   [single threaded sender code]
53 //     static int send_count = 0;
54 //     ++send_count;
55 //     TRACE_EVENT_ASYNC_BEGIN0("ipc", "message", send_count);
56 //     Send(new MyMessage(send_count));
57 //   [receive code]
58 //     void OnMyMessage(send_count) {
59 //       TRACE_EVENT_ASYNC_END0("ipc", "message", send_count);
60 //     }
61 // The third parameter is a unique ID to match ASYNC_BEGIN/ASYNC_END pairs.
62 // ASYNC_BEGIN and ASYNC_END can occur on any thread of any traced process. Pointers can
63 // be used for the ID parameter, and they will be mangled internally so that
64 // the same pointer on two different processes will not match. For example:
65 //   class MyTracedClass {
66 //    public:
67 //     MyTracedClass() {
68 //       TRACE_EVENT_ASYNC_BEGIN0("category", "MyTracedClass", this);
69 //     }
70 //     ~MyTracedClass() {
71 //       TRACE_EVENT_ASYNC_END0("category", "MyTracedClass", this);
72 //     }
73 //   }
74 //
75 // Trace event also supports counters, which is a way to track a quantity
76 // as it varies over time. Counters are created with the following macro:
77 //   TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter", g_myCounterValue);
78 //
79 // Counters are process-specific. The macro itself can be issued from any
80 // thread, however.
81 //
82 // Sometimes, you want to track two counters at once. You can do this with two
83 // counter macros:
84 //   TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter0", g_myCounterValue[0]);
85 //   TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter1", g_myCounterValue[1]);
86 // Or you can do it with a combined macro:
87 //   TRACE_COUNTER2("MY_SUBSYSTEM", "myCounter",
88 //       "bytesPinned", g_myCounterValue[0],
89 //       "bytesAllocated", g_myCounterValue[1]);
90 // This indicates to the tracing UI that these counters should be displayed
91 // in a single graph, as a summed area chart.
92 //
93 // Since counters are in a global namespace, you may want to disembiguate with a
94 // unique ID, by using the TRACE_COUNTER_ID* variations.
95 //
96 // By default, trace collection is compiled in, but turned off at runtime.
97 // Collecting trace data is the responsibility of the embedding
98 // application. In Chrome's case, navigating to about:tracing will turn on
99 // tracing and display data collected across all active processes.
100 //
101 //
102 // Memory scoping note:
103 // Tracing copies the pointers, not the string content, of the strings passed
104 // in for category, name, and arg_names. Thus, the following code will
105 // cause problems:
106 //     char* str = strdup("impprtantName");
107 //     TRACE_EVENT_INSTANT0("SUBSYSTEM", str);  // BAD!
108 //     free(str);                   // Trace system now has dangling pointer
109 //
110 // To avoid this issue with the |name| and |arg_name| parameters, use the
111 // TRACE_EVENT_COPY_XXX overloads of the macros at additional runtime overhead.
112 // Notes: The category must always be in a long-lived char* (i.e. static const).
113 //        The |arg_values|, when used, are always deep copied with the _COPY
114 //        macros.
115 //
116 // When are string argument values copied:
117 // const char* arg_values are only referenced by default:
118 //     TRACE_EVENT1("category", "name",
119 //                  "arg1", "literal string is only referenced");
120 // Use TRACE_STR_COPY to force copying of a const char*:
121 //     TRACE_EVENT1("category", "name",
122 //                  "arg1", TRACE_STR_COPY("string will be copied"));
123 // std::string arg_values are always copied:
124 //     TRACE_EVENT1("category", "name",
125 //                  "arg1", std::string("string will be copied"));
126 //
127 //
128 // Thread Safety:
129 // A thread safe singleton and mutex are used for thread safety. Category
130 // enabled flags are used to limit the performance impact when the system
131 // is not enabled.
132 //
133 // TRACE_EVENT macros first cache a pointer to a category. The categories are
134 // statically allocated and safe at all times, even after exit. Fetching a
135 // category is protected by the TraceLog::lock_. Multiple threads initializing
136 // the static variable is safe, as they will be serialized by the lock and
137 // multiple calls will return the same pointer to the category.
138 //
139 // Then the category_enabled flag is checked. This is a unsigned char, and
140 // not intended to be multithread safe. It optimizes access to addTraceEvent
141 // which is threadsafe internally via TraceLog::lock_. The enabled flag may
142 // cause some threads to incorrectly call or skip calling addTraceEvent near
143 // the time of the system being enabled or disabled. This is acceptable as
144 // we tolerate some data loss while the system is being enabled/disabled and
145 // because addTraceEvent is threadsafe internally and checks the enabled state
146 // again under lock.
147 //
148 // Without the use of these static category pointers and enabled flags all
149 // trace points would carry a significant performance cost of aquiring a lock
150 // and resolving the category.
151 
152 #ifndef DAWNPLATFORM_TRACING_TRACEEVENT_H_
153 #define DAWNPLATFORM_TRACING_TRACEEVENT_H_
154 
155 #include <string>
156 
157 #include "dawn_platform/tracing/EventTracer.h"
158 
159 // Records a pair of begin and end events called "name" for the current
160 // scope, with 0, 1 or 2 associated arguments. If the category is not
161 // enabled, then this does nothing.
162 // - category and name strings must have application lifetime (statics or
163 //   literals). They may not include " chars.
164 #define TRACE_EVENT0(platform, category, name) \
165     INTERNAL_TRACE_EVENT_ADD_SCOPED(platform, category, name, 0)
166 #define TRACE_EVENT1(platform, category, name, arg1_name, arg1_val) \
167     INTERNAL_TRACE_EVENT_ADD_SCOPED(platform, category, name, 0, arg1_name, arg1_val)
168 #define TRACE_EVENT2(platform, category, name, arg1_name, arg1_val, arg2_name, arg2_val)         \
169     INTERNAL_TRACE_EVENT_ADD_SCOPED(platform, category, name, 0, arg1_name, arg1_val, arg2_name, \
170                                     arg2_val)
171 
172 // Records a single event called "name" immediately, with 0, 1 or 2
173 // associated arguments. If the category is not enabled, then this
174 // does nothing.
175 // - category and name strings must have application lifetime (statics or
176 //   literals). They may not include " chars.
177 #define TRACE_EVENT_INSTANT0(platform, category, name)                            \
178     INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_INSTANT, category, name, \
179                              TRACE_EVENT_FLAG_NONE, 0)
180 #define TRACE_EVENT_INSTANT1(platform, category, name, arg1_name, arg1_val)       \
181     INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_INSTANT, category, name, \
182                              TRACE_EVENT_FLAG_NONE, 0, arg1_name, arg1_val)
183 #define TRACE_EVENT_INSTANT2(platform, category, name, arg1_name, arg1_val, arg2_name, arg2_val) \
184     INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_INSTANT, category, name,                \
185                              TRACE_EVENT_FLAG_NONE, 0, arg1_name, arg1_val, arg2_name, arg2_val)
186 #define TRACE_EVENT_COPY_INSTANT0(platform, category, name)                       \
187     INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_INSTANT, category, name, \
188                              TRACE_EVENT_FLAG_COPY, 0)
189 #define TRACE_EVENT_COPY_INSTANT1(platform, category, name, arg1_name, arg1_val)  \
190     INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_INSTANT, category, name, \
191                              TRACE_EVENT_FLAG_COPY, 0, arg1_name, arg1_val)
192 #define TRACE_EVENT_COPY_INSTANT2(platform, category, name, arg1_name, arg1_val, arg2_name, \
193                                   arg2_val)                                                 \
194     INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_INSTANT, category, name,           \
195                              TRACE_EVENT_FLAG_COPY, 0, arg1_name, arg1_val, arg2_name, arg2_val)
196 
197 // Records a single BEGIN event called "name" immediately, with 0, 1 or 2
198 // associated arguments. If the category is not enabled, then this
199 // does nothing.
200 // - category and name strings must have application lifetime (statics or
201 //   literals). They may not include " chars.
202 #define TRACE_EVENT_BEGIN0(platform, category, name)                            \
203     INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_BEGIN, category, name, \
204                              TRACE_EVENT_FLAG_NONE, 0)
205 #define TRACE_EVENT_BEGIN1(platform, category, name, arg1_name, arg1_val)       \
206     INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_BEGIN, category, name, \
207                              TRACE_EVENT_FLAG_NONE, 0, arg1_name, arg1_val)
208 #define TRACE_EVENT_BEGIN2(platform, category, name, arg1_name, arg1_val, arg2_name, arg2_val) \
209     INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_BEGIN, category, name,                \
210                              TRACE_EVENT_FLAG_NONE, 0, arg1_name, arg1_val, arg2_name, arg2_val)
211 #define TRACE_EVENT_COPY_BEGIN0(platform, category, name)                       \
212     INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_BEGIN, category, name, \
213                              TRACE_EVENT_FLAG_COPY, 0)
214 #define TRACE_EVENT_COPY_BEGIN1(platform, category, name, arg1_name, arg1_val)  \
215     INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_BEGIN, category, name, \
216                              TRACE_EVENT_FLAG_COPY, 0, arg1_name, arg1_val)
217 #define TRACE_EVENT_COPY_BEGIN2(platform, category, name, arg1_name, arg1_val, arg2_name, \
218                                 arg2_val)                                                 \
219     INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_BEGIN, category, name,           \
220                              TRACE_EVENT_FLAG_COPY, 0, arg1_name, arg1_val, arg2_name, arg2_val)
221 
222 // Records a single END event for "name" immediately. If the category
223 // is not enabled, then this does nothing.
224 // - category and name strings must have application lifetime (statics or
225 //   literals). They may not include " chars.
226 #define TRACE_EVENT_END0(platform, category, name)                            \
227     INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_END, category, name, \
228                              TRACE_EVENT_FLAG_NONE, 0)
229 #define TRACE_EVENT_END1(platform, category, name, arg1_name, arg1_val)       \
230     INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_END, category, name, \
231                              TRACE_EVENT_FLAG_NONE, 0, arg1_name, arg1_val)
232 #define TRACE_EVENT_END2(platform, category, name, arg1_name, arg1_val, arg2_name, arg2_val) \
233     INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_END, category, name,                \
234                              TRACE_EVENT_FLAG_NONE, 0, arg1_name, arg1_val, arg2_name, arg2_val)
235 #define TRACE_EVENT_COPY_END0(platform, category, name) \
236     INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_END, category, name, TRACE_EVENT_FLAG_COPY)
237 #define TRACE_EVENT_COPY_END1(platform, category, name, arg1_name, arg1_val)  \
238     INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_END, category, name, \
239                              TRACE_EVENT_FLAG_COPY, 0, arg1_name, arg1_val)
240 #define TRACE_EVENT_COPY_END2(platform, category, name, arg1_name, arg1_val, arg2_name, arg2_val) \
241     INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_END, category, name,                     \
242                              TRACE_EVENT_FLAG_COPY, 0, arg1_name, arg1_val, arg2_name, arg2_val)
243 
244 // Records the value of a counter called "name" immediately. Value
245 // must be representable as a 32 bit integer.
246 // - category and name strings must have application lifetime (statics or
247 //   literals). They may not include " chars.
248 #define TRACE_COUNTER1(platform, category, name, value)                           \
249     INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_COUNTER, category, name, \
250                              TRACE_EVENT_FLAG_NONE, 0, "value", static_cast<int>(value))
251 #define TRACE_COPY_COUNTER1(platform, category, name, value)                      \
252     INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_COUNTER, category, name, \
253                              TRACE_EVENT_FLAG_COPY, 0, "value", static_cast<int>(value))
254 
255 // Records the values of a multi-parted counter called "name" immediately.
256 // The UI will treat value1 and value2 as parts of a whole, displaying their
257 // values as a stacked-bar chart.
258 // - category and name strings must have application lifetime (statics or
259 //   literals). They may not include " chars.
260 #define TRACE_COUNTER2(platform, category, name, value1_name, value1_val, value2_name, value2_val) \
261     INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_COUNTER, category, name,                  \
262                              TRACE_EVENT_FLAG_NONE, 0, value1_name, static_cast<int>(value1_val),  \
263                              value2_name, static_cast<int>(value2_val))
264 #define TRACE_COPY_COUNTER2(platform, category, name, value1_name, value1_val, value2_name,       \
265                             value2_val)                                                           \
266     INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_COUNTER, category, name,                 \
267                              TRACE_EVENT_FLAG_COPY, 0, value1_name, static_cast<int>(value1_val), \
268                              value2_name, static_cast<int>(value2_val))
269 
270 // Records the value of a counter called "name" immediately. Value
271 // must be representable as a 32 bit integer.
272 // - category and name strings must have application lifetime (statics or
273 //   literals). They may not include " chars.
274 // - |id| is used to disambiguate counters with the same name. It must either
275 //   be a pointer or an integer value up to 64 bits. If it's a pointer, the bits
276 //   will be xored with a hash of the process ID so that the same pointer on
277 //   two different processes will not collide.
278 #define TRACE_COUNTER_ID1(platform, category, name, id, value)                                \
279     INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_COUNTER, category, name, id, \
280                                      TRACE_EVENT_FLAG_NONE, 0, "value", static_cast<int>(value))
281 #define TRACE_COPY_COUNTER_ID1(platform, category, name, id, value)                           \
282     INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_COUNTER, category, name, id, \
283                                      TRACE_EVENT_FLAG_COPY, 0, "value", static_cast<int>(value))
284 
285 // Records the values of a multi-parted counter called "name" immediately.
286 // The UI will treat value1 and value2 as parts of a whole, displaying their
287 // values as a stacked-bar chart.
288 // - category and name strings must have application lifetime (statics or
289 //   literals). They may not include " chars.
290 // - |id| is used to disambiguate counters with the same name. It must either
291 //   be a pointer or an integer value up to 64 bits. If it's a pointer, the bits
292 //   will be xored with a hash of the process ID so that the same pointer on
293 //   two different processes will not collide.
294 #define TRACE_COUNTER_ID2(platform, category, name, id, value1_name, value1_val, value2_name, \
295                           value2_val)                                                         \
296     INTERNAL_TRACE_EVENT_ADD_WITH_ID(                                                         \
297         platform, TRACE_EVENT_PHASE_COUNTER, category, name, id, TRACE_EVENT_FLAG_NONE, 0,    \
298         value1_name, static_cast<int>(value1_val), value2_name, static_cast<int>(value2_val))
299 #define TRACE_COPY_COUNTER_ID2(platform, category, name, id, value1_name, value1_val, value2_name, \
300                                value2_val)                                                         \
301     INTERNAL_TRACE_EVENT_ADD_WITH_ID(                                                              \
302         platform, TRACE_EVENT_PHASE_COUNTER, category, name, id, TRACE_EVENT_FLAG_COPY, 0,         \
303         value1_name, static_cast<int>(value1_val), value2_name, static_cast<int>(value2_val))
304 
305 // Records a single ASYNC_BEGIN event called "name" immediately, with 0, 1 or 2
306 // associated arguments. If the category is not enabled, then this
307 // does nothing.
308 // - category and name strings must have application lifetime (statics or
309 //   literals). They may not include " chars.
310 // - |id| is used to match the ASYNC_BEGIN event with the ASYNC_END event. ASYNC
311 //   events are considered to match if their category, name and id values all
312 //   match. |id| must either be a pointer or an integer value up to 64 bits. If
313 //   it's a pointer, the bits will be xored with a hash of the process ID so
314 //   that the same pointer on two different processes will not collide.
315 // An asynchronous operation can consist of multiple phases. The first phase is
316 // defined by the ASYNC_BEGIN calls. Additional phases can be defined using the
317 // ASYNC_STEP_BEGIN macros. When the operation completes, call ASYNC_END.
318 // An async operation can span threads and processes, but all events in that
319 // operation must use the same |name| and |id|. Each event can have its own
320 // args.
321 #define TRACE_EVENT_ASYNC_BEGIN0(platform, category, name, id)                                    \
322     INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_ASYNC_BEGIN, category, name, id, \
323                                      TRACE_EVENT_FLAG_NONE, 0)
324 #define TRACE_EVENT_ASYNC_BEGIN1(platform, category, name, id, arg1_name, arg1_val)               \
325     INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_ASYNC_BEGIN, category, name, id, \
326                                      TRACE_EVENT_FLAG_NONE, 0, arg1_name, arg1_val)
327 #define TRACE_EVENT_ASYNC_BEGIN2(platform, category, name, id, arg1_name, arg1_val, arg2_name,    \
328                                  arg2_val)                                                        \
329     INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_ASYNC_BEGIN, category, name, id, \
330                                      TRACE_EVENT_FLAG_NONE, 0, arg1_name, arg1_val, arg2_name,    \
331                                      arg2_val)
332 #define TRACE_EVENT_COPY_ASYNC_BEGIN0(platform, category, name, id)                               \
333     INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_ASYNC_BEGIN, category, name, id, \
334                                      TRACE_EVENT_FLAG_COPY, 0)
335 #define TRACE_EVENT_COPY_ASYNC_BEGIN1(platform, category, name, id, arg1_name, arg1_val)          \
336     INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_ASYNC_BEGIN, category, name, id, \
337                                      TRACE_EVENT_FLAG_COPY, 0, arg1_name, arg1_val)
338 #define TRACE_EVENT_COPY_ASYNC_BEGIN2(platform, category, name, id, arg1_name, arg1_val,          \
339                                       arg2_name, arg2_val)                                        \
340     INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_ASYNC_BEGIN, category, name, id, \
341                                      TRACE_EVENT_FLAG_COPY, 0, arg1_name, arg1_val, arg2_name,    \
342                                      arg2_val)
343 
344 // Records a single ASYNC_STEP event for |step| immediately. If the category
345 // is not enabled, then this does nothing. The |name| and |id| must match the
346 // ASYNC_BEGIN event above. The |step| param identifies this step within the
347 // async event. This should be called at the beginning of the next phase of an
348 // asynchronous operation.
349 #define TRACE_EVENT_ASYNC_STEP0(platform, category, name, id, step)                              \
350     INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_ASYNC_STEP, category, name, id, \
351                                      TRACE_EVENT_FLAG_NONE, 0, "step", step)
352 #define TRACE_EVENT_ASYNC_STEP1(platform, category, name, id, step, arg1_name, arg1_val)         \
353     INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_ASYNC_STEP, category, name, id, \
354                                      TRACE_EVENT_FLAG_NONE, 0, "step", step, arg1_name, arg1_val)
355 #define TRACE_EVENT_COPY_ASYNC_STEP0(platform, category, name, id, step)                         \
356     INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_ASYNC_STEP, category, name, id, \
357                                      TRACE_EVENT_FLAG_COPY, 0, "step", step)
358 #define TRACE_EVENT_COPY_ASYNC_STEP1(platform, category, name, id, step, arg1_name, arg1_val)    \
359     INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_ASYNC_STEP, category, name, id, \
360                                      TRACE_EVENT_FLAG_COPY, 0, "step", step, arg1_name, arg1_val)
361 
362 // Records a single ASYNC_END event for "name" immediately. If the category
363 // is not enabled, then this does nothing.
364 #define TRACE_EVENT_ASYNC_END0(platform, category, name, id)                                    \
365     INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_ASYNC_END, category, name, id, \
366                                      TRACE_EVENT_FLAG_NONE, 0)
367 #define TRACE_EVENT_ASYNC_END1(platform, category, name, id, arg1_name, arg1_val)               \
368     INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_ASYNC_END, category, name, id, \
369                                      TRACE_EVENT_FLAG_NONE, 0, arg1_name, arg1_val)
370 #define TRACE_EVENT_ASYNC_END2(platform, category, name, id, arg1_name, arg1_val, arg2_name,    \
371                                arg2_val)                                                        \
372     INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_ASYNC_END, category, name, id, \
373                                      TRACE_EVENT_FLAG_NONE, 0, arg1_name, arg1_val, arg2_name,  \
374                                      arg2_val)
375 #define TRACE_EVENT_COPY_ASYNC_END0(platform, category, name, id)                               \
376     INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_ASYNC_END, category, name, id, \
377                                      TRACE_EVENT_FLAG_COPY, 0)
378 #define TRACE_EVENT_COPY_ASYNC_END1(platform, category, name, id, arg1_name, arg1_val)          \
379     INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_ASYNC_END, category, name, id, \
380                                      TRACE_EVENT_FLAG_COPY, 0, arg1_name, arg1_val)
381 #define TRACE_EVENT_COPY_ASYNC_END2(platform, category, name, id, arg1_name, arg1_val, arg2_name, \
382                                     arg2_val)                                                     \
383     INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_ASYNC_END, category, name, id,   \
384                                      TRACE_EVENT_FLAG_COPY, 0, arg1_name, arg1_val, arg2_name,    \
385                                      arg2_val)
386 
387 // NESTABLE_ASYNC_* APIs are used to describe an async operation, which can
388 // be nested within a NESTABLE_ASYNC event and/or have inner NESTABLE_ASYNC
389 // events.
390 // - category and name strings must have application lifetime (statics or
391 //   literals). They may not include " chars.
392 // - A pair of NESTABLE_ASYNC_BEGIN event and NESTABLE_ASYNC_END event is
393 //   considered as a match if their category_group, name and id all match.
394 // - |id| must either be a pointer or an integer value up to 64 bits.
395 //   If it's a pointer, the bits will be xored with a hash of the process ID so
396 //   that the same pointer on two different processes will not collide.
397 // - |id| is used to match a child NESTABLE_ASYNC event with its parent
398 //   NESTABLE_ASYNC event. Therefore, events in the same nested event tree must
399 //   be logged using the same id and category_group.
400 //
401 // Unmatched NESTABLE_ASYNC_END event will be parsed as an event that starts
402 // at the first NESTABLE_ASYNC event of that id, and unmatched
403 // NESTABLE_ASYNC_BEGIN event will be parsed as an event that ends at the last
404 // NESTABLE_ASYNC event of that id. Corresponding warning messages for
405 // unmatched events will be shown in the analysis view.
406 
407 // Records a single NESTABLE_ASYNC_BEGIN event called "name" immediately, with
408 // 0, 1 or 2 associated arguments. If the category is not enabled, then this
409 // does nothing.
410 #define TRACE_EVENT_NESTABLE_ASYNC_BEGIN0(platform, category_group, name, id)          \
411     INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN, \
412                                      category_group, name, id, TRACE_EVENT_FLAG_NONE, 0)
413 #define TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(platform, category_group, name, id, arg1_name, arg1_val) \
414     INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN,             \
415                                      category_group, name, id, TRACE_EVENT_FLAG_NONE, 0,           \
416                                      arg1_name, arg1_val)
417 #define TRACE_EVENT_NESTABLE_ASYNC_BEGIN2(platform, category_group, name, id, arg1_name, arg1_val, \
418                                           arg2_name, arg2_val)                                     \
419     INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN,             \
420                                      category_group, name, id, TRACE_EVENT_FLAG_NONE, 0,           \
421                                      arg1_name, arg1_val, arg2_name, arg2_val)
422 // Records a single NESTABLE_ASYNC_END event called "name" immediately, with 0
423 // or 2 associated arguments. If the category is not enabled, then this does
424 // nothing.
425 #define TRACE_EVENT_NESTABLE_ASYNC_END0(platform, category_group, name, id)          \
426     INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_NESTABLE_ASYNC_END, \
427                                      category_group, name, id, TRACE_EVENT_FLAG_NONE, 0)
428 // Records a single NESTABLE_ASYNC_END event called "name" immediately, with 1
429 // associated argument. If the category is not enabled, then this does nothing.
430 #define TRACE_EVENT_NESTABLE_ASYNC_END1(platform, category_group, name, id, arg1_name, arg1_val) \
431     INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_NESTABLE_ASYNC_END,             \
432                                      category_group, name, id, TRACE_EVENT_FLAG_NONE, 0,         \
433                                      arg1_name, arg1_val)
434 #define TRACE_EVENT_NESTABLE_ASYNC_END2(platform, category_group, name, id, arg1_name, arg1_val, \
435                                         arg2_name, arg2_val)                                     \
436     INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_NESTABLE_ASYNC_END,             \
437                                      category_group, name, id, TRACE_EVENT_FLAG_NONE, 0,         \
438                                      arg1_name, arg1_val, arg2_name, arg2_val)
439 
440 // Records a single NESTABLE_ASYNC_INSTANT event called "name" immediately,
441 // with none, one or two associated argument. If the category is not enabled,
442 // then this does nothing.
443 #define TRACE_EVENT_NESTABLE_ASYNC_INSTANT0(platform, category_group, name, id)          \
444     INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT, \
445                                      category_group, name, id, TRACE_EVENT_FLAG_NONE, 0)
446 
447 #define TRACE_EVENT_NESTABLE_ASYNC_INSTANT1(platform, category_group, name, id, arg1_name, \
448                                             arg1_val)                                      \
449     INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT,   \
450                                      category_group, name, id, TRACE_EVENT_FLAG_NONE, 0,   \
451                                      arg1_name, arg1_val)
452 
453 #define TRACE_EVENT_NESTABLE_ASYNC_INSTANT2(platform, category_group, name, id, arg1_name, \
454                                             arg1_val, arg2_name, arg2_val)                 \
455     INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT,   \
456                                      category_group, name, id, TRACE_EVENT_FLAG_NONE, 0,   \
457                                      arg1_name, arg1_val, arg2_name, arg2_val)
458 
459 #define TRACE_EVENT_COPY_NESTABLE_ASYNC_BEGIN_WITH_TTS2(platform, category_group, name, id,       \
460                                                         arg1_name, arg1_val, arg2_name, arg2_val) \
461     INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN,            \
462                                      category_group, name, id,                                    \
463                                      TRACE_EVENT_FLAG_ASYNC_TTS | TRACE_EVENT_FLAG_COPY, 0,       \
464                                      arg1_name, arg1_val, arg2_name, arg2_val)
465 #define TRACE_EVENT_COPY_NESTABLE_ASYNC_END_WITH_TTS2(platform, category_group, name, id,       \
466                                                       arg1_name, arg1_val, arg2_name, arg2_val) \
467     INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_NESTABLE_ASYNC_END,            \
468                                      category_group, name, id,                                  \
469                                      TRACE_EVENT_FLAG_ASYNC_TTS | TRACE_EVENT_FLAG_COPY, 0,     \
470                                      arg1_name, arg1_val, arg2_name, arg2_val)
471 
472 // Similar to TRACE_EVENT_NESTABLE_ASYNC_{BEGIN,END}x but with a custom
473 // |timestamp| provided.
474 #define TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0(platform, category_group, name, id, \
475                                                          timestamp)                          \
476     INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP(                                      \
477         platform, TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN, category_group, name, id,          \
478         TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE, 0)
479 #define TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP0(platform, category_group, name, id, \
480                                                        timestamp)                          \
481     INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP(                                    \
482         platform, TRACE_EVENT_PHASE_NESTABLE_ASYNC_END, category_group, name, id,          \
483         TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE, 0)
484 #define TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP1(platform, category_group, name, id, \
485                                                        timestamp, arg1_name, arg1_val)     \
486     INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP(                                    \
487         platform, TRACE_EVENT_PHASE_NESTABLE_ASYNC_END, category_group, name, id,          \
488         TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE, 0, arg1_name, \
489         arg1_val)
490 #define TRACE_EVENT_NESTABLE_ASYNC_INSTANT_WITH_TIMESTAMP0(platform, category_group, name, id, \
491                                                            timestamp)                          \
492     INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP(                                        \
493         platform, TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT, category_group, name, id,          \
494         TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE, 0)
495 #define TRACE_EVENT_COPY_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0(platform, category_group, name, id, \
496                                                               timestamp)                          \
497     INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP(                                           \
498         platform, TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN, category_group, name, id,               \
499         TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_COPY, 0)
500 #define TRACE_EVENT_COPY_NESTABLE_ASYNC_END_WITH_TIMESTAMP0(platform, category_group, name, id, \
501                                                             timestamp)                          \
502     INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP(                                         \
503         platform, TRACE_EVENT_PHASE_NESTABLE_ASYNC_END, category_group, name, id,               \
504         TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_COPY, 0)
505 
506 // Records a single FLOW_BEGIN event called "name" immediately, with 0, 1 or 2
507 // associated arguments. If the category is not enabled, then this
508 // does nothing.
509 // - category and name strings must have application lifetime (statics or
510 //   literals). They may not include " chars.
511 // - |id| is used to match the FLOW_BEGIN event with the FLOW_END event. FLOW
512 //   events are considered to match if their category_group, name and id values
513 //   all match. |id| must either be a pointer or an integer value up to 64 bits.
514 //   If it's a pointer, the bits will be xored with a hash of the process ID so
515 //   that the same pointer on two different processes will not collide.
516 // FLOW events are different from ASYNC events in how they are drawn by the
517 // tracing UI. A FLOW defines asynchronous data flow, such as posting a task
518 // (FLOW_BEGIN) and later executing that task (FLOW_END). Expect FLOWs to be
519 // drawn as lines or arrows from FLOW_BEGIN scopes to FLOW_END scopes. Similar
520 // to ASYNC, a FLOW can consist of multiple phases. The first phase is defined
521 // by the FLOW_BEGIN calls. Additional phases can be defined using the FLOW_STEP
522 // macros. When the operation completes, call FLOW_END. An async operation can
523 // span threads and processes, but all events in that operation must use the
524 // same |name| and |id|. Each event can have its own args.
525 #define TRACE_EVENT_FLOW_BEGIN0(platform, category_group, name, id)                                \
526     INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_FLOW_BEGIN, category_group, name, \
527                                      id, TRACE_EVENT_FLAG_NONE, 0)
528 #define TRACE_EVENT_FLOW_BEGIN1(platform, category_group, name, id, arg1_name, arg1_val)           \
529     INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_FLOW_BEGIN, category_group, name, \
530                                      id, TRACE_EVENT_FLAG_NONE, 0, arg1_name, arg1_val)
531 #define TRACE_EVENT_FLOW_BEGIN2(platform, category_group, name, id, arg1_name, arg1_val,           \
532                                 arg2_name, arg2_val)                                               \
533     INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_FLOW_BEGIN, category_group, name, \
534                                      id, TRACE_EVENT_FLAG_NONE, 0, arg1_name, arg1_val, arg2_name, \
535                                      arg2_val)
536 #define TRACE_EVENT_COPY_FLOW_BEGIN0(platform, category_group, name, id)                           \
537     INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_FLOW_BEGIN, category_group, name, \
538                                      id, TRACE_EVENT_FLAG_COPY, 0)
539 #define TRACE_EVENT_COPY_FLOW_BEGIN1(platform, category_group, name, id, arg1_name, arg1_val)      \
540     INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_FLOW_BEGIN, category_group, name, \
541                                      id, TRACE_EVENT_FLAG_COPY, 0, arg1_name, arg1_val)
542 #define TRACE_EVENT_COPY_FLOW_BEGIN2(platform, category_group, name, id, arg1_name, arg1_val,      \
543                                      arg2_name, arg2_val)                                          \
544     INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_FLOW_BEGIN, category_group, name, \
545                                      id, TRACE_EVENT_FLAG_COPY, 0, arg1_name, arg1_val, arg2_name, \
546                                      arg2_val)
547 
548 // Records a single FLOW_STEP event for |step| immediately. If the category
549 // is not enabled, then this does nothing. The |name| and |id| must match the
550 // FLOW_BEGIN event above. The |step| param identifies this step within the
551 // async event. This should be called at the beginning of the next phase of an
552 // asynchronous operation.
553 #define TRACE_EVENT_FLOW_STEP0(platform, category_group, name, id, step)                          \
554     INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_FLOW_STEP, category_group, name, \
555                                      id, TRACE_EVENT_FLAG_NONE, 0, "step", step)
556 #define TRACE_EVENT_FLOW_STEP1(platform, category_group, name, id, step, arg1_name, arg1_val)     \
557     INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_FLOW_STEP, category_group, name, \
558                                      id, TRACE_EVENT_FLAG_NONE, 0, "step", step, arg1_name,       \
559                                      arg1_val)
560 #define TRACE_EVENT_COPY_FLOW_STEP0(platform, category_group, name, id, step)                     \
561     INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_FLOW_STEP, category_group, name, \
562                                      id, TRACE_EVENT_FLAG_COPY, 0, "step", step)
563 #define TRACE_EVENT_COPY_FLOW_STEP1(platform, category_group, name, id, step, arg1_name, arg1_val) \
564     INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_FLOW_STEP, category_group, name,  \
565                                      id, TRACE_EVENT_FLAG_COPY, 0, "step", step, arg1_name,        \
566                                      arg1_val)
567 
568 // Records a single FLOW_END event for "name" immediately. If the category
569 // is not enabled, then this does nothing.
570 #define TRACE_EVENT_FLOW_END0(platform, category_group, name, id)                                \
571     INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_FLOW_END, category_group, name, \
572                                      id, TRACE_EVENT_FLAG_NONE, 0)
573 #define TRACE_EVENT_FLOW_END_BIND_TO_ENCLOSING0(platform, category_group, name, id)              \
574     INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_FLOW_END, category_group, name, \
575                                      id, TRACE_EVENT_FLAG_BIND_TO_ENCLOSING, 0)
576 #define TRACE_EVENT_FLOW_END1(platform, category_group, name, id, arg1_name, arg1_val)           \
577     INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_FLOW_END, category_group, name, \
578                                      id, TRACE_EVENT_FLAG_NONE, 0, arg1_name, arg1_val)
579 #define TRACE_EVENT_FLOW_END2(platform, category_group, name, id, arg1_name, arg1_val, arg2_name,  \
580                               arg2_val)                                                            \
581     INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_FLOW_END, category_group, name,   \
582                                      id, TRACE_EVENT_FLAG_NONE, 0, arg1_name, arg1_val, arg2_name, \
583                                      arg2_val)
584 #define TRACE_EVENT_COPY_FLOW_END0(platform, category_group, name, id)                           \
585     INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_FLOW_END, category_group, name, \
586                                      id, TRACE_EVENT_FLAG_COPY, 0)
587 #define TRACE_EVENT_COPY_FLOW_END1(platform, category_group, name, id, arg1_name, arg1_val)      \
588     INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_FLOW_END, category_group, name, \
589                                      id, TRACE_EVENT_FLAG_COPY, 0, arg1_name, arg1_val)
590 #define TRACE_EVENT_COPY_FLOW_END2(platform, category_group, name, id, arg1_name, arg1_val,        \
591                                    arg2_name, arg2_val)                                            \
592     INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_FLOW_END, category_group, name,   \
593                                      id, TRACE_EVENT_FLAG_COPY, 0, arg1_name, arg1_val, arg2_name, \
594                                      arg2_val)
595 
596 // Creates a scope of a sampling state with the given category and name (both must
597 // be constant strings). These states are intended for a sampling profiler.
598 // Implementation note: we store category and name together because we don't
599 // want the inconsistency/expense of storing two pointers.
600 // |thread_bucket| is [0..2] and is used to statically isolate samples in one
601 // thread from others.
602 //
603 // {  // The sampling state is set within this scope.
604 //    TRACE_EVENT_SAMPLING_STATE_SCOPE_FOR_BUCKET(0, "category", "name");
605 //    ...;
606 // }
607 #define TRACE_EVENT_SCOPED_SAMPLING_STATE_FOR_BUCKET(bucket_number, category, name) \
608     TraceEvent::SamplingStateScope<bucket_number> traceEventSamplingScope(category "\0" name);
609 
610 // Returns a current sampling state of the given bucket.
611 // The format of the returned string is "category\0name".
612 #define TRACE_EVENT_GET_SAMPLING_STATE_FOR_BUCKET(bucket_number) \
613     TraceEvent::SamplingStateScope<bucket_number>::current()
614 
615 // Sets a current sampling state of the given bucket.
616 // |category| and |name| have to be constant strings.
617 #define TRACE_EVENT_SET_SAMPLING_STATE_FOR_BUCKET(bucket_number, category, name) \
618     TraceEvent::SamplingStateScope<bucket_number>::set(category "\0" name)
619 
620 // Sets a current sampling state of the given bucket.
621 // |categoryAndName| doesn't need to be a constant string.
622 // The format of the string is "category\0name".
623 #define TRACE_EVENT_SET_NONCONST_SAMPLING_STATE_FOR_BUCKET(bucket_number, categoryAndName) \
624     TraceEvent::SamplingStateScope<bucket_number>::set(categoryAndName)
625 
626 // Syntactic sugars for the sampling tracing in the main thread.
627 #define TRACE_EVENT_SCOPED_SAMPLING_STATE(category, name) \
628     TRACE_EVENT_SCOPED_SAMPLING_STATE_FOR_BUCKET(0, category, name)
629 #define TRACE_EVENT_GET_SAMPLING_STATE() TRACE_EVENT_GET_SAMPLING_STATE_FOR_BUCKET(0)
630 #define TRACE_EVENT_SET_SAMPLING_STATE(category, name) \
631     TRACE_EVENT_SET_SAMPLING_STATE_FOR_BUCKET(0, category, name)
632 #define TRACE_EVENT_SET_NONCONST_SAMPLING_STATE(categoryAndName) \
633     TRACE_EVENT_SET_NONCONST_SAMPLING_STATE_FOR_BUCKET(0, categoryAndName)
634 
635 ////////////////////////////////////////////////////////////////////////////////
636 // Implementation specific tracing API definitions.
637 
638 // Get a pointer to the enabled state of the given trace category. Only
639 // long-lived literal strings should be given as the category name. The returned
640 // pointer can be held permanently in a local static for example. If the
641 // unsigned char is non-zero, tracing is enabled. If tracing is enabled,
642 // TRACE_EVENT_API_ADD_TRACE_EVENT can be called. It's OK if tracing is disabled
643 // between the load of the tracing state and the call to
644 // TRACE_EVENT_API_ADD_TRACE_EVENT, because this flag only provides an early out
645 // for best performance when tracing is disabled.
646 // const unsigned char*
647 //     TRACE_EVENT_API_GET_CATEGORY_ENABLED(const char* category_name)
648 #define TRACE_EVENT_API_GET_CATEGORY_ENABLED dawn_platform::tracing::GetTraceCategoryEnabledFlag
649 
650 // Add a trace event to the platform tracing system.
651 // void TRACE_EVENT_API_ADD_TRACE_EVENT(
652 //                    char phase,
653 //                    const unsigned char* category_enabled,
654 //                    const char* name,
655 //                    unsigned long long id,
656 //                    int num_args,
657 //                    const char** arg_names,
658 //                    const unsigned char* arg_types,
659 //                    const unsigned long long* arg_values,
660 //                    unsigned char flags)
661 #define TRACE_EVENT_API_ADD_TRACE_EVENT dawn_platform::tracing::AddTraceEvent
662 
663 ////////////////////////////////////////////////////////////////////////////////
664 
665 // Implementation detail: trace event macros create temporary variables
666 // to keep instrumentation overhead low. These macros give each temporary
667 // variable a unique name based on the line number to prevent name collissions.
668 #define INTERNAL_TRACE_EVENT_UID3(a, b) trace_event_unique_##a##b
669 #define INTERNAL_TRACE_EVENT_UID2(a, b) INTERNAL_TRACE_EVENT_UID3(a, b)
670 #define INTERNALTRACEEVENTUID(name_prefix) INTERNAL_TRACE_EVENT_UID2(name_prefix, __LINE__)
671 
672 // Implementation detail: internal macro to create static category.
673 #define INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(platform, category)    \
674     static const unsigned char* INTERNALTRACEEVENTUID(catstatic) = 0; \
675     if (!INTERNALTRACEEVENTUID(catstatic))                            \
676         INTERNALTRACEEVENTUID(catstatic) = TRACE_EVENT_API_GET_CATEGORY_ENABLED(platform, category);
677 
678 // Implementation detail: internal macro to create static category and add
679 // event if the category is enabled.
680 #define INTERNAL_TRACE_EVENT_ADD(platform, phase, category, name, flags, ...)                      \
681     do {                                                                                           \
682         INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(platform, ::dawn_platform::TraceCategory::category) \
683         if (*INTERNALTRACEEVENTUID(catstatic)) {                                                   \
684             dawn_platform::TraceEvent::addTraceEvent(                                              \
685                 platform, phase, INTERNALTRACEEVENTUID(catstatic), name,                           \
686                 dawn_platform::TraceEvent::noEventId, flags, __VA_ARGS__);                         \
687         }                                                                                          \
688     } while (0)
689 
690 // Implementation detail: internal macro to create static category and add begin
691 // event if the category is enabled. Also adds the end event when the scope
692 // ends.
693 #define INTERNAL_TRACE_EVENT_ADD_SCOPED(platform, category, name, ...)                         \
694     INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(platform, ::dawn_platform::TraceCategory::category) \
695     dawn_platform::TraceEvent::TraceEndOnScopeClose INTERNALTRACEEVENTUID(profileScope);       \
696     do {                                                                                       \
697         if (*INTERNALTRACEEVENTUID(catstatic)) {                                               \
698             dawn_platform::TraceEvent::addTraceEvent(                                          \
699                 platform, TRACE_EVENT_PHASE_BEGIN, INTERNALTRACEEVENTUID(catstatic), name,     \
700                 dawn_platform::TraceEvent::noEventId, TRACE_EVENT_FLAG_NONE, __VA_ARGS__);     \
701             INTERNALTRACEEVENTUID(profileScope)                                                \
702                 .initialize(platform, INTERNALTRACEEVENTUID(catstatic), name);                 \
703         }                                                                                      \
704     } while (0)
705 
706 // Implementation detail: internal macro to create static category and add
707 // event if the category is enabled.
708 #define INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, phase, category, name, id, flags, ...)          \
709     do {                                                                                           \
710         INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(platform, ::dawn_platform::TraceCategory::category) \
711         if (*INTERNALTRACEEVENTUID(catstatic)) {                                                   \
712             unsigned char traceEventFlags = flags | TRACE_EVENT_FLAG_HAS_ID;                       \
713             dawn_platform::TraceEvent::TraceID traceEventTraceID(id, &traceEventFlags);            \
714             dawn_platform::TraceEvent::addTraceEvent(                                              \
715                 platform, phase, INTERNALTRACEEVENTUID(catstatic), name, traceEventTraceID.data(), \
716                 traceEventFlags, __VA_ARGS__);                                                     \
717         }                                                                                          \
718     } while (0)
719 
720 // Notes regarding the following definitions:
721 // New values can be added and propagated to third party libraries, but existing
722 // definitions must never be changed, because third party libraries may use old
723 // definitions.
724 
725 // Phase indicates the nature of an event entry. E.g. part of a begin/end pair.
726 #define TRACE_EVENT_PHASE_BEGIN ('B')
727 #define TRACE_EVENT_PHASE_END ('E')
728 #define TRACE_EVENT_PHASE_INSTANT ('I')
729 #define TRACE_EVENT_PHASE_ASYNC_BEGIN ('S')
730 #define TRACE_EVENT_PHASE_ASYNC_STEP ('T')
731 #define TRACE_EVENT_PHASE_ASYNC_END ('F')
732 #define TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN ('b')
733 #define TRACE_EVENT_PHASE_NESTABLE_ASYNC_END ('e')
734 #define TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT ('n')
735 #define TRACE_EVENT_PHASE_FLOW_BEGIN ('s')
736 #define TRACE_EVENT_PHASE_FLOW_STEP ('t')
737 #define TRACE_EVENT_PHASE_FLOW_END ('f')
738 #define TRACE_EVENT_PHASE_METADATA ('M')
739 #define TRACE_EVENT_PHASE_COUNTER ('C')
740 #define TRACE_EVENT_PHASE_SAMPLE ('P')
741 
742 // Flags for changing the behavior of TRACE_EVENT_API_ADD_TRACE_EVENT.
743 #define TRACE_EVENT_FLAG_NONE (static_cast<unsigned char>(0))
744 #define TRACE_EVENT_FLAG_COPY (static_cast<unsigned char>(1 << 0))
745 #define TRACE_EVENT_FLAG_HAS_ID (static_cast<unsigned char>(1 << 1))
746 #define TRACE_EVENT_FLAG_MANGLE_ID (static_cast<unsigned char>(1 << 2))
747 
748 // Type values for identifying types in the TraceValue union.
749 #define TRACE_VALUE_TYPE_BOOL (static_cast<unsigned char>(1))
750 #define TRACE_VALUE_TYPE_UINT (static_cast<unsigned char>(2))
751 #define TRACE_VALUE_TYPE_INT (static_cast<unsigned char>(3))
752 #define TRACE_VALUE_TYPE_DOUBLE (static_cast<unsigned char>(4))
753 #define TRACE_VALUE_TYPE_POINTER (static_cast<unsigned char>(5))
754 #define TRACE_VALUE_TYPE_STRING (static_cast<unsigned char>(6))
755 #define TRACE_VALUE_TYPE_COPY_STRING (static_cast<unsigned char>(7))
756 
757 namespace dawn_platform { namespace TraceEvent {
758 
759     // Specify these values when the corresponding argument of addTraceEvent is not
760     // used.
761     const int zeroNumArgs = 0;
762     const unsigned long long noEventId = 0;
763 
764     // TraceID encapsulates an ID that can either be an integer or pointer. Pointers
765     // are mangled with the Process ID so that they are unlikely to collide when the
766     // same pointer is used on different processes.
767     class TraceID {
768       public:
TraceID(const void * id,unsigned char * flags)769         explicit TraceID(const void* id, unsigned char* flags)
770             : m_data(static_cast<unsigned long long>(reinterpret_cast<uintptr_t>(id))) {
771             *flags |= TRACE_EVENT_FLAG_MANGLE_ID;
772         }
TraceID(unsigned long long id,unsigned char * flags)773         explicit TraceID(unsigned long long id, unsigned char* flags) : m_data(id) {
774             (void)flags;
775         }
TraceID(unsigned long id,unsigned char * flags)776         explicit TraceID(unsigned long id, unsigned char* flags) : m_data(id) {
777             (void)flags;
778         }
TraceID(unsigned int id,unsigned char * flags)779         explicit TraceID(unsigned int id, unsigned char* flags) : m_data(id) {
780             (void)flags;
781         }
TraceID(unsigned short id,unsigned char * flags)782         explicit TraceID(unsigned short id, unsigned char* flags) : m_data(id) {
783             (void)flags;
784         }
TraceID(unsigned char id,unsigned char * flags)785         explicit TraceID(unsigned char id, unsigned char* flags) : m_data(id) {
786             (void)flags;
787         }
TraceID(long long id,unsigned char * flags)788         explicit TraceID(long long id, unsigned char* flags)
789             : m_data(static_cast<unsigned long long>(id)) {
790             (void)flags;
791         }
TraceID(long id,unsigned char * flags)792         explicit TraceID(long id, unsigned char* flags)
793             : m_data(static_cast<unsigned long long>(id)) {
794             (void)flags;
795         }
TraceID(int id,unsigned char * flags)796         explicit TraceID(int id, unsigned char* flags)
797             : m_data(static_cast<unsigned long long>(id)) {
798             (void)flags;
799         }
TraceID(short id,unsigned char * flags)800         explicit TraceID(short id, unsigned char* flags)
801             : m_data(static_cast<unsigned long long>(id)) {
802             (void)flags;
803         }
TraceID(signed char id,unsigned char * flags)804         explicit TraceID(signed char id, unsigned char* flags)
805             : m_data(static_cast<unsigned long long>(id)) {
806             (void)flags;
807         }
808 
data()809         unsigned long long data() const {
810             return m_data;
811         }
812 
813       private:
814         unsigned long long m_data;
815     };
816 
817     // Simple union to store various types as unsigned long long.
818     union TraceValueUnion {
819         bool m_bool;
820         unsigned long long m_uint;
821         long long m_int;
822         double m_double;
823         const void* m_pointer;
824         const char* m_string;
825     };
826 
827     // Simple container for const char* that should be copied instead of retained.
828     class TraceStringWithCopy {
829       public:
TraceStringWithCopy(const char * str)830         explicit TraceStringWithCopy(const char* str) : m_str(str) {
831         }
832         operator const char*() const {
833             return m_str;
834         }
835 
836       private:
837         const char* m_str;
838     };
839 
840 // Define setTraceValue for each allowed type. It stores the type and
841 // value in the return arguments. This allows this API to avoid declaring any
842 // structures so that it is portable to third_party libraries.
843 #define INTERNAL_DECLARE_SET_TRACE_VALUE(actual_type, union_member, value_type_id)            \
844     static inline void setTraceValue(actual_type arg, unsigned char* type, uint64_t* value) { \
845         TraceValueUnion typeValue;                                                            \
846         typeValue.union_member = arg;                                                         \
847         *type = value_type_id;                                                                \
848         *value = typeValue.m_uint;                                                            \
849     }
850 // Simpler form for int types that can be safely casted.
851 #define INTERNAL_DECLARE_SET_TRACE_VALUE_INT(actual_type, value_type_id)                      \
852     static inline void setTraceValue(actual_type arg, unsigned char* type, uint64_t* value) { \
853         *type = value_type_id;                                                                \
854         *value = static_cast<unsigned long long>(arg);                                        \
855     }
856 
INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned long long,TRACE_VALUE_TYPE_UINT)857         INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned long long, TRACE_VALUE_TYPE_UINT)
858         INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned int, TRACE_VALUE_TYPE_UINT)
859         INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned short, TRACE_VALUE_TYPE_UINT)
860         INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned char, TRACE_VALUE_TYPE_UINT)
861         INTERNAL_DECLARE_SET_TRACE_VALUE_INT(long long, TRACE_VALUE_TYPE_INT)
862         INTERNAL_DECLARE_SET_TRACE_VALUE_INT(int, TRACE_VALUE_TYPE_INT)
863         INTERNAL_DECLARE_SET_TRACE_VALUE_INT(short, TRACE_VALUE_TYPE_INT)
864         INTERNAL_DECLARE_SET_TRACE_VALUE_INT(signed char, TRACE_VALUE_TYPE_INT)
865         INTERNAL_DECLARE_SET_TRACE_VALUE(bool, m_bool, TRACE_VALUE_TYPE_BOOL)
866         INTERNAL_DECLARE_SET_TRACE_VALUE(double, m_double, TRACE_VALUE_TYPE_DOUBLE)
867         INTERNAL_DECLARE_SET_TRACE_VALUE(const void*, m_pointer, TRACE_VALUE_TYPE_POINTER)
868         INTERNAL_DECLARE_SET_TRACE_VALUE(const char*, m_string, TRACE_VALUE_TYPE_STRING)
869         INTERNAL_DECLARE_SET_TRACE_VALUE(const TraceStringWithCopy&,
870                                          m_string,
871                                          TRACE_VALUE_TYPE_COPY_STRING)
872 
873 #undef INTERNAL_DECLARE_SET_TRACE_VALUE
874 #undef INTERNAL_DECLARE_SET_TRACE_VALUE_INT
875 
876         static inline void setTraceValue(const std::string& arg,
877                                          unsigned char* type,
878                                          uint64_t* value) {
879             TraceValueUnion typeValue;
880             typeValue.m_string = arg.data();
881             *type = TRACE_VALUE_TYPE_COPY_STRING;
882             *value = typeValue.m_uint;
883         }
884 
885         // These addTraceEvent template functions are defined here instead of in the
886         // macro, because the arg values could be temporary string objects. In order to
887         // store pointers to the internal c_str and pass through to the tracing API, the
888         // arg values must live throughout these procedures.
889 
addTraceEvent(dawn_platform::Platform * platform,char phase,const unsigned char * categoryEnabled,const char * name,unsigned long long id,unsigned char flags,int)890         static inline dawn_platform::tracing::TraceEventHandle addTraceEvent(
891             dawn_platform::Platform* platform,
892             char phase,
893             const unsigned char* categoryEnabled,
894             const char* name,
895             unsigned long long id,
896             unsigned char flags,
897             int /*unused, helps avoid empty __VA_ARGS__*/) {
898             return TRACE_EVENT_API_ADD_TRACE_EVENT(platform, phase, categoryEnabled, name, id,
899                                                    zeroNumArgs, 0, 0, 0, flags);
900         }
901 
902         template <class ARG1_TYPE>
addTraceEvent(dawn_platform::Platform * platform,char phase,const unsigned char * categoryEnabled,const char * name,unsigned long long id,unsigned char flags,int,const char * arg1Name,const ARG1_TYPE & arg1Val)903         static inline dawn_platform::tracing::TraceEventHandle addTraceEvent(
904             dawn_platform::Platform* platform,
905             char phase,
906             const unsigned char* categoryEnabled,
907             const char* name,
908             unsigned long long id,
909             unsigned char flags,
910             int /*unused, helps avoid empty __VA_ARGS__*/,
911             const char* arg1Name,
912             const ARG1_TYPE& arg1Val) {
913             const int numArgs = 1;
914             unsigned char argTypes[1];
915             uint64_t argValues[1];
916             setTraceValue(arg1Val, &argTypes[0], &argValues[0]);
917             return TRACE_EVENT_API_ADD_TRACE_EVENT(platform, phase, categoryEnabled, name, id,
918                                                    numArgs, &arg1Name, argTypes, argValues, flags);
919         }
920 
921         template <class ARG1_TYPE, class ARG2_TYPE>
addTraceEvent(dawn_platform::Platform * platform,char phase,const unsigned char * categoryEnabled,const char * name,unsigned long long id,unsigned char flags,int,const char * arg1Name,const ARG1_TYPE & arg1Val,const char * arg2Name,const ARG2_TYPE & arg2Val)922         static inline dawn_platform::tracing::TraceEventHandle addTraceEvent(
923             dawn_platform::Platform* platform,
924             char phase,
925             const unsigned char* categoryEnabled,
926             const char* name,
927             unsigned long long id,
928             unsigned char flags,
929             int /*unused, helps avoid empty __VA_ARGS__*/,
930             const char* arg1Name,
931             const ARG1_TYPE& arg1Val,
932             const char* arg2Name,
933             const ARG2_TYPE& arg2Val) {
934             const int numArgs = 2;
935             const char* argNames[2] = {arg1Name, arg2Name};
936             unsigned char argTypes[2];
937             uint64_t argValues[2];
938             setTraceValue(arg1Val, &argTypes[0], &argValues[0]);
939             setTraceValue(arg2Val, &argTypes[1], &argValues[1]);
940             return TRACE_EVENT_API_ADD_TRACE_EVENT(platform, phase, categoryEnabled, name, id,
941                                                    numArgs, argNames, argTypes, argValues, flags);
942         }
943 
944         // Used by TRACE_EVENTx macro. Do not use directly.
945         class TraceEndOnScopeClose {
946           public:
947             // Note: members of m_data intentionally left uninitialized. See initialize.
TraceEndOnScopeClose()948             TraceEndOnScopeClose() : m_pdata(0) {
949             }
~TraceEndOnScopeClose()950             ~TraceEndOnScopeClose() {
951                 if (m_pdata)
952                     addEventIfEnabled();
953             }
954 
initialize(dawn_platform::Platform * platform,const unsigned char * categoryEnabled,const char * name)955             void initialize(dawn_platform::Platform* platform,
956                             const unsigned char* categoryEnabled,
957                             const char* name) {
958                 m_data.platform = platform;
959                 m_data.categoryEnabled = categoryEnabled;
960                 m_data.name = name;
961                 m_pdata = &m_data;
962             }
963 
964           private:
965             // Add the end event if the category is still enabled.
addEventIfEnabled()966             void addEventIfEnabled() {
967                 // Only called when m_pdata is non-null.
968                 if (*m_pdata->categoryEnabled) {
969                     TRACE_EVENT_API_ADD_TRACE_EVENT(
970                         m_pdata->platform, TRACE_EVENT_PHASE_END, m_pdata->categoryEnabled,
971                         m_pdata->name, noEventId, zeroNumArgs, 0, 0, 0, TRACE_EVENT_FLAG_NONE);
972                 }
973             }
974 
975             // This Data struct workaround is to avoid initializing all the members
976             // in Data during construction of this object, since this object is always
977             // constructed, even when tracing is disabled. If the members of Data were
978             // members of this class instead, compiler warnings occur about potential
979             // uninitialized accesses.
980             struct Data {
981                 dawn_platform::Platform* platform;
982                 const unsigned char* categoryEnabled;
983                 const char* name;
984             };
985             Data* m_pdata;
986             Data m_data;
987         };
988 
989 }}  // namespace dawn_platform::TraceEvent
990 
991 #endif  // DAWNPLATFORM_TRACING_TRACEEVENT_H_
992