1bf215546Sopenharmony_ci#
2bf215546Sopenharmony_ci# Copyright (C) 2020 Google, Inc.
3bf215546Sopenharmony_ci#
4bf215546Sopenharmony_ci# Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci# copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci# to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci# the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci# and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci# Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci#
11bf215546Sopenharmony_ci# The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci# paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci# Software.
14bf215546Sopenharmony_ci#
15bf215546Sopenharmony_ci# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18bf215546Sopenharmony_ci# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bf215546Sopenharmony_ci# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20bf215546Sopenharmony_ci# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21bf215546Sopenharmony_ci# IN THE SOFTWARE.
22bf215546Sopenharmony_ci#
23bf215546Sopenharmony_ci
24bf215546Sopenharmony_cifrom mako.template import Template
25bf215546Sopenharmony_cifrom collections import namedtuple
26bf215546Sopenharmony_cifrom enum import IntEnum
27bf215546Sopenharmony_ciimport os
28bf215546Sopenharmony_ci
29bf215546Sopenharmony_ciTRACEPOINTS = {}
30bf215546Sopenharmony_ciTRACEPOINTS_TOGGLES = {}
31bf215546Sopenharmony_ci
32bf215546Sopenharmony_ciclass Tracepoint(object):
33bf215546Sopenharmony_ci    """Class that represents all the information about a tracepoint
34bf215546Sopenharmony_ci    """
35bf215546Sopenharmony_ci    def __init__(self, name, args=[], toggle_name=None,
36bf215546Sopenharmony_ci                 tp_struct=None, tp_print=None, tp_perfetto=None,
37bf215546Sopenharmony_ci                 end_of_pipe=False):
38bf215546Sopenharmony_ci        """Parameters:
39bf215546Sopenharmony_ci
40bf215546Sopenharmony_ci        - name: the tracepoint name, a tracepoint function with the given
41bf215546Sopenharmony_ci          name (prefixed by 'trace_') will be generated with the specied
42bf215546Sopenharmony_ci          args (following a u_trace ptr).  Calling this tracepoint will
43bf215546Sopenharmony_ci          emit a trace, if tracing is enabled.
44bf215546Sopenharmony_ci        - args: the tracepoint func args, an array of TracepointArg
45bf215546Sopenharmony_ci        - tp_print: (optional) array of format string followed by expressions
46bf215546Sopenharmony_ci        - tp_perfetto: (optional) driver provided callback which can generate
47bf215546Sopenharmony_ci          perfetto events
48bf215546Sopenharmony_ci        """
49bf215546Sopenharmony_ci        assert isinstance(name, str)
50bf215546Sopenharmony_ci        assert isinstance(args, list)
51bf215546Sopenharmony_ci        assert name not in TRACEPOINTS
52bf215546Sopenharmony_ci
53bf215546Sopenharmony_ci        self.name = name
54bf215546Sopenharmony_ci        self.args = args
55bf215546Sopenharmony_ci        if tp_struct is None:
56bf215546Sopenharmony_ci           tp_struct = args
57bf215546Sopenharmony_ci        self.tp_struct = tp_struct
58bf215546Sopenharmony_ci        self.tp_print = tp_print
59bf215546Sopenharmony_ci        self.tp_perfetto = tp_perfetto
60bf215546Sopenharmony_ci        self.end_of_pipe = end_of_pipe
61bf215546Sopenharmony_ci        self.toggle_name = toggle_name
62bf215546Sopenharmony_ci
63bf215546Sopenharmony_ci        TRACEPOINTS[name] = self
64bf215546Sopenharmony_ci        if toggle_name is not None and toggle_name not in TRACEPOINTS_TOGGLES:
65bf215546Sopenharmony_ci            TRACEPOINTS_TOGGLES[toggle_name] = len(TRACEPOINTS_TOGGLES)
66bf215546Sopenharmony_ci
67bf215546Sopenharmony_ci    def can_generate_print(self):
68bf215546Sopenharmony_ci        return self.args is not None and len(self.args) > 0
69bf215546Sopenharmony_ci
70bf215546Sopenharmony_ci    def enabled_expr(self, trace_toggle_name):
71bf215546Sopenharmony_ci        if trace_toggle_name is None:
72bf215546Sopenharmony_ci            return "true"
73bf215546Sopenharmony_ci        assert self.toggle_name is not None
74bf215546Sopenharmony_ci        return "({0} & {1}_{2})".format(trace_toggle_name,
75bf215546Sopenharmony_ci                                        trace_toggle_name.upper(),
76bf215546Sopenharmony_ci                                        self.toggle_name.upper())
77bf215546Sopenharmony_ci
78bf215546Sopenharmony_ciclass TracepointArgStruct():
79bf215546Sopenharmony_ci    """Represents struct that is being passed as an argument
80bf215546Sopenharmony_ci    """
81bf215546Sopenharmony_ci    def __init__(self, type, var):
82bf215546Sopenharmony_ci        """Parameters:
83bf215546Sopenharmony_ci
84bf215546Sopenharmony_ci        - type: argument's C type.
85bf215546Sopenharmony_ci        - var: name of the argument
86bf215546Sopenharmony_ci        """
87bf215546Sopenharmony_ci        assert isinstance(type, str)
88bf215546Sopenharmony_ci        assert isinstance(var, str)
89bf215546Sopenharmony_ci
90bf215546Sopenharmony_ci        self.type = type
91bf215546Sopenharmony_ci        self.var = var
92bf215546Sopenharmony_ci
93bf215546Sopenharmony_ciclass TracepointArg(object):
94bf215546Sopenharmony_ci    """Class that represents either an argument being passed or a field in a struct
95bf215546Sopenharmony_ci    """
96bf215546Sopenharmony_ci    def __init__(self, type, var, c_format, name=None, to_prim_type=None):
97bf215546Sopenharmony_ci        """Parameters:
98bf215546Sopenharmony_ci
99bf215546Sopenharmony_ci        - type: argument's C type.
100bf215546Sopenharmony_ci        - var: either an argument name or a field in the struct
101bf215546Sopenharmony_ci        - c_format: printf format to print the value.
102bf215546Sopenharmony_ci        - name: (optional) name that will be used in intermidiate structs and will
103bf215546Sopenharmony_ci          be displayed in output or perfetto, otherwise var will be used.
104bf215546Sopenharmony_ci        - to_prim_type: (optional) C function to convert from arg's type to a type
105bf215546Sopenharmony_ci          compatible with c_format.
106bf215546Sopenharmony_ci        """
107bf215546Sopenharmony_ci        assert isinstance(type, str)
108bf215546Sopenharmony_ci        assert isinstance(var, str)
109bf215546Sopenharmony_ci        assert isinstance(c_format, str)
110bf215546Sopenharmony_ci
111bf215546Sopenharmony_ci        self.type = type
112bf215546Sopenharmony_ci        self.var = var
113bf215546Sopenharmony_ci        self.c_format = c_format
114bf215546Sopenharmony_ci        if name is None:
115bf215546Sopenharmony_ci           name = var
116bf215546Sopenharmony_ci        self.name = name
117bf215546Sopenharmony_ci        self.to_prim_type = to_prim_type
118bf215546Sopenharmony_ci
119bf215546Sopenharmony_ci
120bf215546Sopenharmony_ciHEADERS = []
121bf215546Sopenharmony_ci
122bf215546Sopenharmony_ciclass HeaderScope(IntEnum):
123bf215546Sopenharmony_ci   HEADER = (1 << 0)
124bf215546Sopenharmony_ci   SOURCE = (1 << 1)
125bf215546Sopenharmony_ci
126bf215546Sopenharmony_ciclass Header(object):
127bf215546Sopenharmony_ci    """Class that represents a header file dependency of generated tracepoints
128bf215546Sopenharmony_ci    """
129bf215546Sopenharmony_ci    def __init__(self, hdr, scope=HeaderScope.HEADER|HeaderScope.SOURCE):
130bf215546Sopenharmony_ci        """Parameters:
131bf215546Sopenharmony_ci
132bf215546Sopenharmony_ci        - hdr: the required header path
133bf215546Sopenharmony_ci        """
134bf215546Sopenharmony_ci        assert isinstance(hdr, str)
135bf215546Sopenharmony_ci        self.hdr = hdr
136bf215546Sopenharmony_ci        self.scope = scope
137bf215546Sopenharmony_ci
138bf215546Sopenharmony_ci        HEADERS.append(self)
139bf215546Sopenharmony_ci
140bf215546Sopenharmony_ci
141bf215546Sopenharmony_ciFORWARD_DECLS = []
142bf215546Sopenharmony_ci
143bf215546Sopenharmony_ciclass ForwardDecl(object):
144bf215546Sopenharmony_ci   """Class that represents a forward declaration
145bf215546Sopenharmony_ci   """
146bf215546Sopenharmony_ci   def __init__(self, decl):
147bf215546Sopenharmony_ci        assert isinstance(decl, str)
148bf215546Sopenharmony_ci        self.decl = decl
149bf215546Sopenharmony_ci
150bf215546Sopenharmony_ci        FORWARD_DECLS.append(self)
151bf215546Sopenharmony_ci
152bf215546Sopenharmony_ci
153bf215546Sopenharmony_cihdr_template = """\
154bf215546Sopenharmony_ci/* Copyright (C) 2020 Google, Inc.
155bf215546Sopenharmony_ci *
156bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
157bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
158bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
159bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
160bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
161bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
162bf215546Sopenharmony_ci *
163bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
164bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
165bf215546Sopenharmony_ci * Software.
166bf215546Sopenharmony_ci *
167bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
168bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
169bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
170bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
171bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
172bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
173bf215546Sopenharmony_ci * IN THE SOFTWARE.
174bf215546Sopenharmony_ci */
175bf215546Sopenharmony_ci
176bf215546Sopenharmony_ci<% guard_name = '_' + hdrname + '_H' %>
177bf215546Sopenharmony_ci#ifndef ${guard_name}
178bf215546Sopenharmony_ci#define ${guard_name}
179bf215546Sopenharmony_ci
180bf215546Sopenharmony_ci% for header in HEADERS:
181bf215546Sopenharmony_ci#include "${header.hdr}"
182bf215546Sopenharmony_ci% endfor
183bf215546Sopenharmony_ci
184bf215546Sopenharmony_ci#include "util/perf/u_trace.h"
185bf215546Sopenharmony_ci
186bf215546Sopenharmony_ci#ifdef __cplusplus
187bf215546Sopenharmony_ciextern "C" {
188bf215546Sopenharmony_ci#endif
189bf215546Sopenharmony_ci
190bf215546Sopenharmony_ci% for declaration in FORWARD_DECLS:
191bf215546Sopenharmony_ci${declaration.decl};
192bf215546Sopenharmony_ci% endfor
193bf215546Sopenharmony_ci
194bf215546Sopenharmony_ci% if trace_toggle_name is not None:
195bf215546Sopenharmony_cienum ${trace_toggle_name.lower()} {
196bf215546Sopenharmony_ci%    for toggle_name, config_id in TRACEPOINTS_TOGGLES.items():
197bf215546Sopenharmony_ci   ${trace_toggle_name.upper()}_${toggle_name.upper()} = 1ull << ${config_id},
198bf215546Sopenharmony_ci%    endfor
199bf215546Sopenharmony_ci};
200bf215546Sopenharmony_ci
201bf215546Sopenharmony_ciextern uint64_t ${trace_toggle_name};
202bf215546Sopenharmony_ci
203bf215546Sopenharmony_civoid ${trace_toggle_name}_config_variable(void);
204bf215546Sopenharmony_ci% endif
205bf215546Sopenharmony_ci
206bf215546Sopenharmony_ci% for trace_name, trace in TRACEPOINTS.items():
207bf215546Sopenharmony_ci
208bf215546Sopenharmony_ci/*
209bf215546Sopenharmony_ci * ${trace_name}
210bf215546Sopenharmony_ci */
211bf215546Sopenharmony_cistruct trace_${trace_name} {
212bf215546Sopenharmony_ci%    for arg in trace.tp_struct:
213bf215546Sopenharmony_ci   ${arg.type} ${arg.name};
214bf215546Sopenharmony_ci%    endfor
215bf215546Sopenharmony_ci%    if len(trace.args) == 0:
216bf215546Sopenharmony_ci#ifdef __cplusplus
217bf215546Sopenharmony_ci   /* avoid warnings about empty struct size mis-match in C vs C++..
218bf215546Sopenharmony_ci    * the size mis-match is harmless because (a) nothing will deref
219bf215546Sopenharmony_ci    * the empty struct, and (b) the code that cares about allocating
220bf215546Sopenharmony_ci    * sizeof(struct trace_${trace_name}) (and wants this to be zero
221bf215546Sopenharmony_ci    * if there is no payload) is C
222bf215546Sopenharmony_ci    */
223bf215546Sopenharmony_ci   uint8_t dummy;
224bf215546Sopenharmony_ci#endif
225bf215546Sopenharmony_ci%    endif
226bf215546Sopenharmony_ci};
227bf215546Sopenharmony_ci%    if trace.tp_perfetto is not None:
228bf215546Sopenharmony_ci#ifdef HAVE_PERFETTO
229bf215546Sopenharmony_civoid ${trace.tp_perfetto}(
230bf215546Sopenharmony_ci   ${ctx_param},
231bf215546Sopenharmony_ci   uint64_t ts_ns,
232bf215546Sopenharmony_ci   const void *flush_data,
233bf215546Sopenharmony_ci   const struct trace_${trace_name} *payload);
234bf215546Sopenharmony_ci#endif
235bf215546Sopenharmony_ci%    endif
236bf215546Sopenharmony_civoid __trace_${trace_name}(
237bf215546Sopenharmony_ci       struct u_trace *ut
238bf215546Sopenharmony_ci%    if need_cs_param:
239bf215546Sopenharmony_ci     , void *cs
240bf215546Sopenharmony_ci%    endif
241bf215546Sopenharmony_ci%    for arg in trace.args:
242bf215546Sopenharmony_ci     , ${arg.type} ${arg.var}
243bf215546Sopenharmony_ci%    endfor
244bf215546Sopenharmony_ci);
245bf215546Sopenharmony_cistatic inline void trace_${trace_name}(
246bf215546Sopenharmony_ci     struct u_trace *ut
247bf215546Sopenharmony_ci%    if need_cs_param:
248bf215546Sopenharmony_ci   , void *cs
249bf215546Sopenharmony_ci%    endif
250bf215546Sopenharmony_ci%    for arg in trace.args:
251bf215546Sopenharmony_ci   , ${arg.type} ${arg.var}
252bf215546Sopenharmony_ci%    endfor
253bf215546Sopenharmony_ci) {
254bf215546Sopenharmony_ci%    if trace.tp_perfetto is not None:
255bf215546Sopenharmony_ci   if (!unlikely((ut->enabled || ut_trace_instrument || ut_perfetto_enabled) &&
256bf215546Sopenharmony_ci                 ${trace.enabled_expr(trace_toggle_name)}))
257bf215546Sopenharmony_ci%    else:
258bf215546Sopenharmony_ci   if (!unlikely((ut->enabled || ut_trace_instrument) &&
259bf215546Sopenharmony_ci                 ${trace.enabled_expr(trace_toggle_name)}))
260bf215546Sopenharmony_ci%    endif
261bf215546Sopenharmony_ci      return;
262bf215546Sopenharmony_ci   __trace_${trace_name}(
263bf215546Sopenharmony_ci        ut
264bf215546Sopenharmony_ci%    if need_cs_param:
265bf215546Sopenharmony_ci      , cs
266bf215546Sopenharmony_ci%    endif
267bf215546Sopenharmony_ci%    for arg in trace.args:
268bf215546Sopenharmony_ci      , ${arg.var}
269bf215546Sopenharmony_ci%    endfor
270bf215546Sopenharmony_ci   );
271bf215546Sopenharmony_ci}
272bf215546Sopenharmony_ci% endfor
273bf215546Sopenharmony_ci
274bf215546Sopenharmony_ci#ifdef __cplusplus
275bf215546Sopenharmony_ci}
276bf215546Sopenharmony_ci#endif
277bf215546Sopenharmony_ci
278bf215546Sopenharmony_ci#endif /* ${guard_name} */
279bf215546Sopenharmony_ci"""
280bf215546Sopenharmony_ci
281bf215546Sopenharmony_cisrc_template = """\
282bf215546Sopenharmony_ci/* Copyright (C) 2020 Google, Inc.
283bf215546Sopenharmony_ci *
284bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
285bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
286bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
287bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
288bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
289bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
290bf215546Sopenharmony_ci *
291bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
292bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
293bf215546Sopenharmony_ci * Software.
294bf215546Sopenharmony_ci *
295bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
296bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
297bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
298bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
299bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
300bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
301bf215546Sopenharmony_ci * IN THE SOFTWARE.
302bf215546Sopenharmony_ci */
303bf215546Sopenharmony_ci
304bf215546Sopenharmony_ci% for header in HEADERS:
305bf215546Sopenharmony_ci#include "${header.hdr}"
306bf215546Sopenharmony_ci% endfor
307bf215546Sopenharmony_ci
308bf215546Sopenharmony_ci#include "${hdr}"
309bf215546Sopenharmony_ci
310bf215546Sopenharmony_ci#define __NEEDS_TRACE_PRIV
311bf215546Sopenharmony_ci#include "util/debug.h"
312bf215546Sopenharmony_ci#include "util/perf/u_trace_priv.h"
313bf215546Sopenharmony_ci
314bf215546Sopenharmony_ci% if trace_toggle_name is not None:
315bf215546Sopenharmony_cistatic const struct debug_control config_control[] = {
316bf215546Sopenharmony_ci%    for toggle_name in TRACEPOINTS_TOGGLES.keys():
317bf215546Sopenharmony_ci   { "${toggle_name}", ${trace_toggle_name.upper()}_${toggle_name.upper()}, },
318bf215546Sopenharmony_ci%    endfor
319bf215546Sopenharmony_ci   { NULL, 0, },
320bf215546Sopenharmony_ci};
321bf215546Sopenharmony_ciuint64_t ${trace_toggle_name} = 0;
322bf215546Sopenharmony_ci
323bf215546Sopenharmony_cistatic void
324bf215546Sopenharmony_ci${trace_toggle_name}_variable_once(void)
325bf215546Sopenharmony_ci{
326bf215546Sopenharmony_ci   uint64_t default_value = 0
327bf215546Sopenharmony_ci%    for name in trace_toggle_defaults:
328bf215546Sopenharmony_ci     | ${trace_toggle_name.upper()}_${name.upper()}
329bf215546Sopenharmony_ci%    endfor
330bf215546Sopenharmony_ci     ;
331bf215546Sopenharmony_ci
332bf215546Sopenharmony_ci   ${trace_toggle_name} =
333bf215546Sopenharmony_ci      parse_enable_string(getenv("${trace_toggle_name.upper()}"),
334bf215546Sopenharmony_ci                          default_value,
335bf215546Sopenharmony_ci                          config_control);
336bf215546Sopenharmony_ci}
337bf215546Sopenharmony_ci
338bf215546Sopenharmony_civoid
339bf215546Sopenharmony_ci${trace_toggle_name}_config_variable(void)
340bf215546Sopenharmony_ci{
341bf215546Sopenharmony_ci   static once_flag process_${trace_toggle_name}_variable_flag = ONCE_FLAG_INIT;
342bf215546Sopenharmony_ci
343bf215546Sopenharmony_ci   call_once(&process_${trace_toggle_name}_variable_flag,
344bf215546Sopenharmony_ci             ${trace_toggle_name}_variable_once);
345bf215546Sopenharmony_ci}
346bf215546Sopenharmony_ci% endif
347bf215546Sopenharmony_ci
348bf215546Sopenharmony_ci% for trace_name, trace in TRACEPOINTS.items():
349bf215546Sopenharmony_ci/*
350bf215546Sopenharmony_ci * ${trace_name}
351bf215546Sopenharmony_ci */
352bf215546Sopenharmony_ci % if trace.can_generate_print():
353bf215546Sopenharmony_cistatic void __print_${trace_name}(FILE *out, const void *arg) {
354bf215546Sopenharmony_ci   const struct trace_${trace_name} *__entry =
355bf215546Sopenharmony_ci      (const struct trace_${trace_name} *)arg;
356bf215546Sopenharmony_ci  % if trace.tp_print is not None:
357bf215546Sopenharmony_ci   fprintf(out, "${trace.tp_print[0]}\\n"
358bf215546Sopenharmony_ci   % for arg in trace.tp_print[1:]:
359bf215546Sopenharmony_ci           , ${arg}
360bf215546Sopenharmony_ci   % endfor
361bf215546Sopenharmony_ci  % else:
362bf215546Sopenharmony_ci   fprintf(out, ""
363bf215546Sopenharmony_ci   % for arg in trace.tp_struct:
364bf215546Sopenharmony_ci      "${arg.name}=${arg.c_format}, "
365bf215546Sopenharmony_ci   % endfor
366bf215546Sopenharmony_ci         "\\n"
367bf215546Sopenharmony_ci   % for arg in trace.tp_struct:
368bf215546Sopenharmony_ci    % if arg.to_prim_type:
369bf215546Sopenharmony_ci   ,${arg.to_prim_type.format('__entry->' + arg.name)}
370bf215546Sopenharmony_ci    % else:
371bf215546Sopenharmony_ci   ,__entry->${arg.name}
372bf215546Sopenharmony_ci    % endif
373bf215546Sopenharmony_ci   % endfor
374bf215546Sopenharmony_ci  % endif
375bf215546Sopenharmony_ci   );
376bf215546Sopenharmony_ci}
377bf215546Sopenharmony_ci
378bf215546Sopenharmony_cistatic void __print_json_${trace_name}(FILE *out, const void *arg) {
379bf215546Sopenharmony_ci   const struct trace_${trace_name} *__entry =
380bf215546Sopenharmony_ci      (const struct trace_${trace_name} *)arg;
381bf215546Sopenharmony_ci  % if trace.tp_print is not None:
382bf215546Sopenharmony_ci   fprintf(out, "\\"unstructured\\": \\"${trace.tp_print[0]}\\""
383bf215546Sopenharmony_ci   % for arg in trace.tp_print[1:]:
384bf215546Sopenharmony_ci           , ${arg}
385bf215546Sopenharmony_ci   % endfor
386bf215546Sopenharmony_ci  % else:
387bf215546Sopenharmony_ci   fprintf(out, ""
388bf215546Sopenharmony_ci   % for arg in trace.tp_struct:
389bf215546Sopenharmony_ci      "\\"${arg.name}\\": \\"${arg.c_format}\\""
390bf215546Sopenharmony_ci      % if arg != trace.tp_struct[-1]:
391bf215546Sopenharmony_ci         ", "
392bf215546Sopenharmony_ci      % endif
393bf215546Sopenharmony_ci   % endfor
394bf215546Sopenharmony_ci   % for arg in trace.tp_struct:
395bf215546Sopenharmony_ci    % if arg.to_prim_type:
396bf215546Sopenharmony_ci   ,${arg.to_prim_type.format('__entry->' + arg.name)}
397bf215546Sopenharmony_ci    % else:
398bf215546Sopenharmony_ci   ,__entry->${arg.name}
399bf215546Sopenharmony_ci    % endif
400bf215546Sopenharmony_ci   % endfor
401bf215546Sopenharmony_ci  % endif
402bf215546Sopenharmony_ci   );
403bf215546Sopenharmony_ci}
404bf215546Sopenharmony_ci
405bf215546Sopenharmony_ci % else:
406bf215546Sopenharmony_ci#define __print_${trace_name} NULL
407bf215546Sopenharmony_ci#define __print_json_${trace_name} NULL
408bf215546Sopenharmony_ci % endif
409bf215546Sopenharmony_cistatic const struct u_tracepoint __tp_${trace_name} = {
410bf215546Sopenharmony_ci    ALIGN_POT(sizeof(struct trace_${trace_name}), 8),   /* keep size 64b aligned */
411bf215546Sopenharmony_ci    "${trace_name}",
412bf215546Sopenharmony_ci    ${"true" if trace.end_of_pipe else "false"},
413bf215546Sopenharmony_ci    __print_${trace_name},
414bf215546Sopenharmony_ci    __print_json_${trace_name},
415bf215546Sopenharmony_ci % if trace.tp_perfetto is not None:
416bf215546Sopenharmony_ci#ifdef HAVE_PERFETTO
417bf215546Sopenharmony_ci    (void (*)(void *pctx, uint64_t, const void *, const void *))${trace.tp_perfetto},
418bf215546Sopenharmony_ci#endif
419bf215546Sopenharmony_ci % endif
420bf215546Sopenharmony_ci};
421bf215546Sopenharmony_civoid __trace_${trace_name}(
422bf215546Sopenharmony_ci     struct u_trace *ut
423bf215546Sopenharmony_ci % if need_cs_param:
424bf215546Sopenharmony_ci   , void *cs
425bf215546Sopenharmony_ci % endif
426bf215546Sopenharmony_ci % for arg in trace.args:
427bf215546Sopenharmony_ci   , ${arg.type} ${arg.var}
428bf215546Sopenharmony_ci % endfor
429bf215546Sopenharmony_ci) {
430bf215546Sopenharmony_ci   struct trace_${trace_name} *__entry =
431bf215546Sopenharmony_ci      (struct trace_${trace_name} *)u_trace_append(ut, ${cs_param_value + ","} &__tp_${trace_name});
432bf215546Sopenharmony_ci % if len(trace.tp_struct) == 0:
433bf215546Sopenharmony_ci   (void)__entry;
434bf215546Sopenharmony_ci % endif
435bf215546Sopenharmony_ci % for arg in trace.tp_struct:
436bf215546Sopenharmony_ci   __entry->${arg.name} = ${arg.var};
437bf215546Sopenharmony_ci % endfor
438bf215546Sopenharmony_ci}
439bf215546Sopenharmony_ci
440bf215546Sopenharmony_ci% endfor
441bf215546Sopenharmony_ci"""
442bf215546Sopenharmony_ci
443bf215546Sopenharmony_cidef utrace_generate(cpath, hpath, ctx_param, need_cs_param=True,
444bf215546Sopenharmony_ci                    trace_toggle_name=None, trace_toggle_defaults=[]):
445bf215546Sopenharmony_ci    """Parameters:
446bf215546Sopenharmony_ci
447bf215546Sopenharmony_ci    - cpath: c file to generate.
448bf215546Sopenharmony_ci    - hpath: h file to generate.
449bf215546Sopenharmony_ci    - ctx_param: type of the first parameter to the perfetto vfuncs.
450bf215546Sopenharmony_ci    - need_cs_param: whether tracepoint functions need an additional cs
451bf215546Sopenharmony_ci      parameter.
452bf215546Sopenharmony_ci    - trace_toggle_name: (optional) name of the environment variable
453bf215546Sopenharmony_ci      enabling/disabling tracepoints.
454bf215546Sopenharmony_ci    - trace_toggle_defaults: (optional) list of tracepoints enabled by default.
455bf215546Sopenharmony_ci    """
456bf215546Sopenharmony_ci    cs_param_value = 'NULL'
457bf215546Sopenharmony_ci    if need_cs_param:
458bf215546Sopenharmony_ci        cs_param_value = 'cs'
459bf215546Sopenharmony_ci    if cpath is not None:
460bf215546Sopenharmony_ci        hdr = os.path.basename(cpath).rsplit('.', 1)[0] + '.h'
461bf215546Sopenharmony_ci        with open(cpath, 'w') as f:
462bf215546Sopenharmony_ci            f.write(Template(src_template).render(
463bf215546Sopenharmony_ci                hdr=hdr,
464bf215546Sopenharmony_ci                ctx_param=ctx_param,
465bf215546Sopenharmony_ci                need_cs_param=need_cs_param,
466bf215546Sopenharmony_ci                cs_param_value=cs_param_value,
467bf215546Sopenharmony_ci                trace_toggle_name=trace_toggle_name,
468bf215546Sopenharmony_ci                trace_toggle_defaults=trace_toggle_defaults,
469bf215546Sopenharmony_ci                HEADERS=[h for h in HEADERS if h.scope & HeaderScope.SOURCE],
470bf215546Sopenharmony_ci                TRACEPOINTS=TRACEPOINTS,
471bf215546Sopenharmony_ci                TRACEPOINTS_TOGGLES=TRACEPOINTS_TOGGLES))
472bf215546Sopenharmony_ci
473bf215546Sopenharmony_ci    if hpath is not None:
474bf215546Sopenharmony_ci        hdr = os.path.basename(hpath)
475bf215546Sopenharmony_ci        with open(hpath, 'w') as f:
476bf215546Sopenharmony_ci            f.write(Template(hdr_template).render(
477bf215546Sopenharmony_ci                hdrname=hdr.rstrip('.h').upper(),
478bf215546Sopenharmony_ci                ctx_param=ctx_param,
479bf215546Sopenharmony_ci                need_cs_param=need_cs_param,
480bf215546Sopenharmony_ci                trace_toggle_name=trace_toggle_name,
481bf215546Sopenharmony_ci                HEADERS=[h for h in HEADERS if h.scope & HeaderScope.HEADER],
482bf215546Sopenharmony_ci                FORWARD_DECLS=FORWARD_DECLS,
483bf215546Sopenharmony_ci                TRACEPOINTS=TRACEPOINTS,
484bf215546Sopenharmony_ci                TRACEPOINTS_TOGGLES=TRACEPOINTS_TOGGLES))
485bf215546Sopenharmony_ci
486bf215546Sopenharmony_ci
487bf215546Sopenharmony_ciperfetto_utils_hdr_template = """\
488bf215546Sopenharmony_ci/*
489bf215546Sopenharmony_ci * Copyright © 2021 Igalia S.L.
490bf215546Sopenharmony_ci *
491bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
492bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
493bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
494bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
495bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
496bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
497bf215546Sopenharmony_ci *
498bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
499bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
500bf215546Sopenharmony_ci * Software.
501bf215546Sopenharmony_ci *
502bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
503bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
504bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
505bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
506bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
507bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
508bf215546Sopenharmony_ci * SOFTWARE.
509bf215546Sopenharmony_ci */
510bf215546Sopenharmony_ci
511bf215546Sopenharmony_ci<% guard_name = '_' + hdrname + '_H' %>
512bf215546Sopenharmony_ci#ifndef ${guard_name}
513bf215546Sopenharmony_ci#define ${guard_name}
514bf215546Sopenharmony_ci
515bf215546Sopenharmony_ci#include <perfetto.h>
516bf215546Sopenharmony_ci
517bf215546Sopenharmony_ci% for trace_name, trace in TRACEPOINTS.items():
518bf215546Sopenharmony_cistatic void UNUSED
519bf215546Sopenharmony_citrace_payload_as_extra_${trace_name}(perfetto::protos::pbzero::GpuRenderStageEvent *event,
520bf215546Sopenharmony_ci                                     const struct trace_${trace_name} *payload)
521bf215546Sopenharmony_ci{
522bf215546Sopenharmony_ci % if all([trace.tp_perfetto, trace.tp_struct]) and len(trace.tp_struct) > 0:
523bf215546Sopenharmony_ci   char buf[128];
524bf215546Sopenharmony_ci
525bf215546Sopenharmony_ci  % for arg in trace.tp_struct:
526bf215546Sopenharmony_ci   {
527bf215546Sopenharmony_ci      auto data = event->add_extra_data();
528bf215546Sopenharmony_ci      data->set_name("${arg.name}");
529bf215546Sopenharmony_ci
530bf215546Sopenharmony_ci   % if arg.to_prim_type:
531bf215546Sopenharmony_ci      sprintf(buf, "${arg.c_format}", ${arg.to_prim_type.format('payload->' + arg.name)});
532bf215546Sopenharmony_ci   % else:
533bf215546Sopenharmony_ci      sprintf(buf, "${arg.c_format}", payload->${arg.name});
534bf215546Sopenharmony_ci   % endif
535bf215546Sopenharmony_ci
536bf215546Sopenharmony_ci      data->set_value(buf);
537bf215546Sopenharmony_ci   }
538bf215546Sopenharmony_ci  % endfor
539bf215546Sopenharmony_ci
540bf215546Sopenharmony_ci % endif
541bf215546Sopenharmony_ci}
542bf215546Sopenharmony_ci% endfor
543bf215546Sopenharmony_ci
544bf215546Sopenharmony_ci#endif /* ${guard_name} */
545bf215546Sopenharmony_ci"""
546bf215546Sopenharmony_ci
547bf215546Sopenharmony_cidef utrace_generate_perfetto_utils(hpath):
548bf215546Sopenharmony_ci    if hpath is not None:
549bf215546Sopenharmony_ci        hdr = os.path.basename(hpath)
550bf215546Sopenharmony_ci        with open(hpath, 'wb') as f:
551bf215546Sopenharmony_ci            f.write(Template(perfetto_utils_hdr_template, output_encoding='utf-8').render(
552bf215546Sopenharmony_ci                hdrname=hdr.rstrip('.h').upper(),
553bf215546Sopenharmony_ci                TRACEPOINTS=TRACEPOINTS))
554