util/u_trace: auto-generation of serialization funcs for tracepoints
Add ability to auto-generate: - printing of args for "GPU_TRACE=1", still could be overriden with tp_print. - population of extra data for perfetto event. Signed-off-by: Danylo Piliaiev <dpiliaiev@igalia.com> Reviewed-by: Rob Clark <robdclark@chromium.org> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10969>
This commit is contained in:
@@ -27,6 +27,8 @@
|
||||
#include "pipe/p_context.h"
|
||||
#include "pipe/p_screen.h"
|
||||
|
||||
#include "u_tracepoints.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -71,23 +73,21 @@ u_trace_pipe_context_init(struct u_trace_context *utctx,
|
||||
delete_flush_data);
|
||||
}
|
||||
|
||||
void __trace_surface(struct u_trace *ut, const struct pipe_surface *psurf);
|
||||
void __trace_framebuffer(struct u_trace *ut, const struct pipe_framebuffer_state *pfb);
|
||||
|
||||
inline void
|
||||
trace_framebuffer_state(struct u_trace *ut, const struct pipe_framebuffer_state *pfb)
|
||||
{
|
||||
if (likely(!ut->enabled))
|
||||
return;
|
||||
|
||||
__trace_framebuffer(ut, pfb);
|
||||
trace_framebuffer(ut, pfb);
|
||||
|
||||
for (unsigned i = 0; i < pfb->nr_cbufs; i++) {
|
||||
if (pfb->cbufs[i]) {
|
||||
__trace_surface(ut, pfb->cbufs[i]);
|
||||
trace_surface(ut, pfb->cbufs[i]);
|
||||
}
|
||||
}
|
||||
if (pfb->zsbuf) {
|
||||
__trace_surface(ut, pfb->zsbuf);
|
||||
trace_surface(ut, pfb->zsbuf);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -37,6 +37,8 @@ sys.path.insert(0, args.import_path)
|
||||
|
||||
from u_trace import Header
|
||||
from u_trace import Tracepoint
|
||||
from u_trace import TracepointArg as Arg
|
||||
from u_trace import TracepointArgStruct as ArgStruct
|
||||
from u_trace import utrace_generate
|
||||
|
||||
#
|
||||
@@ -47,11 +49,11 @@ Header('pipe/p_state.h')
|
||||
Header('util/format/u_format.h')
|
||||
|
||||
Tracepoint('surface',
|
||||
args=[['const struct pipe_surface *', 'psurf']],
|
||||
tp_struct=[['uint16_t', 'width', 'psurf->width'],
|
||||
['uint16_t', 'height', 'psurf->height'],
|
||||
['uint8_t', 'nr_samples', 'psurf->nr_samples'],
|
||||
['const char *', 'format', 'util_format_short_name(psurf->format)']],
|
||||
args=[ArgStruct(type='const struct pipe_surface *', var='psurf')],
|
||||
tp_struct=[Arg(type='uint16_t', name='width', var='psurf->width', c_format='%u'),
|
||||
Arg(type='uint16_t', name='height', var='psurf->height', c_format='%u'),
|
||||
Arg(type='uint8_t', name='nr_samples', var='psurf->nr_samples', c_format='%u'),
|
||||
Arg(type='const char *', name='format', var='util_format_short_name(psurf->format)', c_format='%s')],
|
||||
tp_print=['%ux%u@%u, fmt=%s',
|
||||
'__entry->width',
|
||||
'__entry->height',
|
||||
@@ -61,12 +63,12 @@ Tracepoint('surface',
|
||||
|
||||
# Note: called internally from trace_framebuffer_state()
|
||||
Tracepoint('framebuffer',
|
||||
args=[['const struct pipe_framebuffer_state *', 'pfb']],
|
||||
tp_struct=[['uint16_t', 'width', 'pfb->width'],
|
||||
['uint16_t', 'height', 'pfb->height'],
|
||||
['uint8_t', 'layers', 'pfb->layers'],
|
||||
['uint8_t', 'samples', 'pfb->samples'],
|
||||
['uint8_t', 'nr_cbufs', 'pfb->nr_cbufs']],
|
||||
args=[ArgStruct(type='const struct pipe_framebuffer_state *', var='pfb')],
|
||||
tp_struct=[Arg(type='uint16_t', name='width', var='pfb->width', c_format='%u'),
|
||||
Arg(type='uint16_t', name='height', var='pfb->height', c_format='%u'),
|
||||
Arg(type='uint8_t', name='layers', var='pfb->layers', c_format='%u'),
|
||||
Arg(type='uint8_t', name='samples', var='pfb->samples', c_format='%u'),
|
||||
Arg(type='uint8_t', name='nr_cbufs', var='pfb->nr_cbufs', c_format='%u')],
|
||||
tp_print=['%ux%ux%u@%u, nr_cbufs: %u',
|
||||
'__entry->width',
|
||||
'__entry->height',
|
||||
@@ -76,14 +78,14 @@ Tracepoint('framebuffer',
|
||||
)
|
||||
|
||||
Tracepoint('grid_info',
|
||||
args=[['const struct pipe_grid_info *', 'pgrid']],
|
||||
tp_struct=[['uint8_t', 'work_dim', 'pgrid->work_dim'],
|
||||
['uint16_t', 'block_x', 'pgrid->block[0]'],
|
||||
['uint16_t', 'block_y', 'pgrid->block[1]'],
|
||||
['uint16_t', 'block_z', 'pgrid->block[2]'],
|
||||
['uint16_t', 'grid_x', 'pgrid->grid[0]'],
|
||||
['uint16_t', 'grid_y', 'pgrid->grid[1]'],
|
||||
['uint16_t', 'grid_z', 'pgrid->grid[2]']],
|
||||
args=[ArgStruct(type='const struct pipe_grid_info *', var='pgrid')],
|
||||
tp_struct=[Arg(type='uint8_t', name='work_dim', var='pgrid->work_dim', c_format='%u'),
|
||||
Arg(type='uint16_t', name='block_x', var='pgrid->block[0]', c_format='%u'),
|
||||
Arg(type='uint16_t', name='block_y', var='pgrid->block[1]', c_format='%u'),
|
||||
Arg(type='uint16_t', name='block_z', var='pgrid->block[2]', c_format='%u'),
|
||||
Arg(type='uint16_t', name='grid_x', var='pgrid->grid[0]', c_format='%u'),
|
||||
Arg(type='uint16_t', name='grid_y', var='pgrid->grid[1]', c_format='%u'),
|
||||
Arg(type='uint16_t', name='grid_z', var='pgrid->grid[2]', c_format='%u')],
|
||||
tp_print=['work_dim=%u, block=%ux%ux%u, grid=%ux%ux%u', '__entry->work_dim',
|
||||
'__entry->block_x', '__entry->block_y', '__entry->block_z',
|
||||
'__entry->grid_x', '__entry->grid_y', '__entry->grid_z'],
|
||||
|
@@ -37,6 +37,7 @@ sys.path.insert(0, args.import_path)
|
||||
|
||||
from u_trace import Header
|
||||
from u_trace import Tracepoint
|
||||
from u_trace import TracepointArg
|
||||
from u_trace import utrace_generate
|
||||
|
||||
#
|
||||
@@ -50,19 +51,19 @@ Tracepoint('start_state_restore')
|
||||
Tracepoint('end_state_restore')
|
||||
|
||||
Tracepoint('flush_batch',
|
||||
args=[['struct fd_batch *', 'batch'],
|
||||
['uint16_t', 'cleared'],
|
||||
['uint16_t', 'gmem_reason'],
|
||||
['uint16_t', 'num_draws']],
|
||||
args=[TracepointArg(type='struct fd_batch *', var='batch', c_format='%x'),
|
||||
TracepointArg(type='uint16_t', var='cleared', c_format='%x'),
|
||||
TracepointArg(type='uint16_t', var='gmem_reason', c_format='%x'),
|
||||
TracepointArg(type='uint16_t', var='num_draws', c_format='%u')],
|
||||
tp_print=['%p: cleared=%x, gmem_reason=%x, num_draws=%u', '__entry->batch',
|
||||
'__entry->cleared', '__entry->gmem_reason', '__entry->num_draws'],
|
||||
)
|
||||
|
||||
Tracepoint('render_gmem',
|
||||
args=[['uint16_t', 'nbins_x'],
|
||||
['uint16_t', 'nbins_y'],
|
||||
['uint16_t', 'bin_w'],
|
||||
['uint16_t', 'bin_h']],
|
||||
args=[TracepointArg(type='uint16_t', var='nbins_x', c_format='%u'),
|
||||
TracepointArg(type='uint16_t', var='nbins_y', c_format='%u'),
|
||||
TracepointArg(type='uint16_t', var='bin_w', c_format='%u'),
|
||||
TracepointArg(type='uint16_t', var='bin_h', c_format='%u')],
|
||||
tp_print=['%ux%u bins of %ux%u',
|
||||
'__entry->nbins_x', '__entry->nbins_y', '__entry->bin_w', '__entry->bin_h'],
|
||||
)
|
||||
@@ -72,16 +73,16 @@ Tracepoint('render_sysmem')
|
||||
# Note that this doesn't include full information about all of the MRTs
|
||||
# but seems to roughly match what I see with a blob trace
|
||||
Tracepoint('start_render_pass',
|
||||
args=[['uint32_t', 'submit_id'],
|
||||
['enum pipe_format', 'cbuf0_format'],
|
||||
['enum pipe_format', 'zs_format'],
|
||||
['uint16_t', 'width'],
|
||||
['uint16_t', 'height'],
|
||||
['uint8_t', 'mrts'],
|
||||
['uint8_t', 'samples'],
|
||||
['uint16_t', 'nbins'],
|
||||
['uint16_t', 'binw'],
|
||||
['uint16_t', 'binh']],
|
||||
args=[TracepointArg(type='uint32_t', var='submit_id', c_format='%u'),
|
||||
TracepointArg(type='enum pipe_format', var='cbuf0_format', c_format='%s', to_prim_type='util_format_description({})->short_name'),
|
||||
TracepointArg(type='enum pipe_format', var='zs_format', c_format='%s', to_prim_type='util_format_description({})->short_name'),
|
||||
TracepointArg(type='uint16_t', var='width', c_format='%u'),
|
||||
TracepointArg(type='uint16_t', var='height', c_format='%u'),
|
||||
TracepointArg(type='uint8_t', var='mrts', c_format='%u'),
|
||||
TracepointArg(type='uint8_t', var='samples', c_format='%u'),
|
||||
TracepointArg(type='uint16_t', var='nbins', c_format='%u'),
|
||||
TracepointArg(type='uint16_t', var='binw', c_format='%u'),
|
||||
TracepointArg(type='uint16_t', var='binh', c_format='%u')],
|
||||
tp_perfetto='fd_start_render_pass'
|
||||
)
|
||||
Tracepoint('end_render_pass',
|
||||
@@ -100,7 +101,7 @@ Tracepoint('end_prologue')
|
||||
|
||||
# For GMEM pass, where this could either be a clear or resolve
|
||||
Tracepoint('start_clear_restore',
|
||||
args=[['uint16_t', 'fast_cleared']],
|
||||
args=[TracepointArg(type='uint16_t', var='fast_cleared', c_format='0x%x')],
|
||||
tp_print=['fast_cleared: 0x%x', '__entry->fast_cleared'],
|
||||
tp_perfetto='fd_start_clear_restore',
|
||||
)
|
||||
@@ -113,10 +114,10 @@ Tracepoint('end_resolve',
|
||||
tp_perfetto='fd_end_resolve')
|
||||
|
||||
Tracepoint('start_tile',
|
||||
args=[['uint16_t', 'bin_h'],
|
||||
['uint16_t', 'yoff'],
|
||||
['uint16_t', 'bin_w'],
|
||||
['uint16_t', 'xoff']],
|
||||
args=[TracepointArg(type='uint16_t', var='bin_h', c_format='%u'),
|
||||
TracepointArg(type='uint16_t', var='yoff', c_format='%u'),
|
||||
TracepointArg(type='uint16_t', var='bin_w', c_format='%u'),
|
||||
TracepointArg(type='uint16_t', var='xoff', c_format='%u')],
|
||||
tp_print=['bin_h=%d, yoff=%d, bin_w=%d, xoff=%d',
|
||||
'__entry->bin_h', '__entry->yoff', '__entry->bin_w', '__entry->xoff'],
|
||||
)
|
||||
@@ -127,8 +128,8 @@ Tracepoint('end_draw_ib',
|
||||
tp_perfetto='fd_end_draw_ib')
|
||||
|
||||
Tracepoint('start_blit',
|
||||
args=[['enum pipe_texture_target', 'src_target'],
|
||||
['enum pipe_texture_target', 'dst_target']],
|
||||
args=[TracepointArg(type='enum pipe_texture_target', var='src_target', c_format='%s', to_prim_type="util_str_tex_target({}, true)"),
|
||||
TracepointArg(type='enum pipe_texture_target', var='dst_target', c_format='%s', to_prim_type="util_str_tex_target({}, true)")],
|
||||
tp_print=['%s -> %s', 'util_str_tex_target(__entry->src_target, true)',
|
||||
'util_str_tex_target(__entry->dst_target, true)'],
|
||||
tp_perfetto='fd_start_blit',
|
||||
|
@@ -22,6 +22,8 @@
|
||||
#
|
||||
|
||||
from mako.template import Template
|
||||
from collections import namedtuple
|
||||
from enum import Flag, auto
|
||||
import os
|
||||
|
||||
TRACEPOINTS = {}
|
||||
@@ -36,10 +38,7 @@ class Tracepoint(object):
|
||||
name (prefixed by 'trace_') will be generated with the specied
|
||||
args (following a u_trace ptr). Calling this tracepoint will
|
||||
emit a trace, if tracing is enabled.
|
||||
- args: the tracepoint func args, an array of [type, name] pairs
|
||||
- tp_struct: (optional) array of [type, name, expr] tuples to
|
||||
convert from tracepoint args to trace payload. If not specified
|
||||
it will be generated from `args` (ie, [type, name, name])
|
||||
- args: the tracepoint func args, an array of TracepointArg
|
||||
- tp_print: (optional) array of format string followed by expressions
|
||||
- tp_perfetto: (optional) driver provided callback which can generate
|
||||
perfetto events
|
||||
@@ -51,27 +50,72 @@ class Tracepoint(object):
|
||||
self.name = name
|
||||
self.args = args
|
||||
if tp_struct is None:
|
||||
tp_struct = []
|
||||
for arg in args:
|
||||
tp_struct.append([arg[0], arg[1], arg[1]])
|
||||
tp_struct = args
|
||||
self.tp_struct = tp_struct
|
||||
self.tp_print = tp_print
|
||||
self.tp_perfetto = tp_perfetto
|
||||
|
||||
TRACEPOINTS[name] = self
|
||||
|
||||
class TracepointArgStruct():
|
||||
"""Represents struct that is being passed as an argument
|
||||
"""
|
||||
def __init__(self, type, var):
|
||||
"""Parameters:
|
||||
|
||||
- type: argument's C type.
|
||||
- var: name of the argument
|
||||
"""
|
||||
assert isinstance(type, str)
|
||||
assert isinstance(var, str)
|
||||
|
||||
self.type = type
|
||||
self.var = var
|
||||
|
||||
class TracepointArg(object):
|
||||
"""Class that represents either an argument being passed or a field in a struct
|
||||
"""
|
||||
def __init__(self, type, var, c_format, name=None, to_prim_type=None):
|
||||
"""Parameters:
|
||||
|
||||
- type: argument's C type.
|
||||
- var: either an argument name or a field in the struct
|
||||
- c_format: printf format to print the value.
|
||||
- name: (optional) name that will be used in intermidiate structs and will
|
||||
be displayed in output or perfetto, otherwise var will be used.
|
||||
- to_prim_type: (optional) C function to convert from arg's type to a type
|
||||
compatible with c_format.
|
||||
"""
|
||||
assert isinstance(type, str)
|
||||
assert isinstance(var, str)
|
||||
assert isinstance(c_format, str)
|
||||
|
||||
self.type = type
|
||||
self.var = var
|
||||
self.c_format = c_format
|
||||
if name is None:
|
||||
name = var
|
||||
self.name = name
|
||||
self.to_prim_type = to_prim_type
|
||||
|
||||
|
||||
HEADERS = []
|
||||
|
||||
class HeaderScope(Flag):
|
||||
HEADER = auto()
|
||||
SOURCE = auto()
|
||||
|
||||
class Header(object):
|
||||
"""Class that represents a header file dependency of generated tracepoints
|
||||
"""
|
||||
def __init__(self, hdr):
|
||||
def __init__(self, hdr, scope=HeaderScope.HEADER|HeaderScope.SOURCE):
|
||||
"""Parameters:
|
||||
|
||||
- hdr: the required header path
|
||||
"""
|
||||
assert isinstance(hdr, str)
|
||||
self.hdr = hdr
|
||||
self.scope = scope
|
||||
|
||||
HEADERS.append(self)
|
||||
|
||||
@@ -134,10 +178,10 @@ ${declaration.decl};
|
||||
* ${trace_name}
|
||||
*/
|
||||
struct trace_${trace_name} {
|
||||
% for member in trace.tp_struct:
|
||||
${member[0]} ${member[1]};
|
||||
% for arg in trace.tp_struct:
|
||||
${arg.type} ${arg.name};
|
||||
% endfor
|
||||
% if len(trace.tp_struct) == 0:
|
||||
% if len(trace.args) == 0:
|
||||
#ifdef __cplusplus
|
||||
/* avoid warnings about empty struct size mis-match in C vs C++..
|
||||
* the size mis-match is harmless because (a) nothing will deref
|
||||
@@ -156,12 +200,12 @@ void ${trace.tp_perfetto}(${ctx_param}, uint64_t ts_ns, const void *flush_data,
|
||||
% endif
|
||||
void __trace_${trace_name}(struct u_trace *ut
|
||||
% for arg in trace.args:
|
||||
, ${arg[0]} ${arg[1]}
|
||||
, ${arg.type} ${arg.var}
|
||||
% endfor
|
||||
);
|
||||
static inline void trace_${trace_name}(struct u_trace *ut
|
||||
% for arg in trace.args:
|
||||
, ${arg[0]} ${arg[1]}
|
||||
, ${arg.type} ${arg.var}
|
||||
% endfor
|
||||
) {
|
||||
% if trace.tp_perfetto is not None:
|
||||
@@ -172,7 +216,7 @@ static inline void trace_${trace_name}(struct u_trace *ut
|
||||
return;
|
||||
__trace_${trace_name}(ut
|
||||
% for arg in trace.args:
|
||||
, ${arg[1]}
|
||||
, ${arg.var}
|
||||
% endfor
|
||||
);
|
||||
}
|
||||
@@ -221,14 +265,29 @@ src_template = """\
|
||||
/*
|
||||
* ${trace_name}
|
||||
*/
|
||||
% if trace.tp_print is not None:
|
||||
% if trace.args is not None and len(trace.args) > 0:
|
||||
static void __print_${trace_name}(FILE *out, const void *arg) {
|
||||
const struct trace_${trace_name} *__entry =
|
||||
(const struct trace_${trace_name} *)arg;
|
||||
% if trace.tp_print is not None:
|
||||
fprintf(out, "${trace.tp_print[0]}\\n"
|
||||
% for arg in trace.tp_print[1:]:
|
||||
, ${arg}
|
||||
% endfor
|
||||
% else:
|
||||
fprintf(out, ""
|
||||
% for arg in trace.tp_struct:
|
||||
"${arg.name}=${arg.c_format}, "
|
||||
% endfor
|
||||
"\\n"
|
||||
% for arg in trace.tp_struct:
|
||||
% if arg.to_prim_type:
|
||||
,${arg.to_prim_type.format('__entry->' + arg.name)}
|
||||
% else:
|
||||
,__entry->${arg.name}
|
||||
% endif
|
||||
% endfor
|
||||
%endif
|
||||
);
|
||||
}
|
||||
% else:
|
||||
@@ -246,14 +305,14 @@ static const struct u_tracepoint __tp_${trace_name} = {
|
||||
};
|
||||
void __trace_${trace_name}(struct u_trace *ut
|
||||
% for arg in trace.args:
|
||||
, ${arg[0]} ${arg[1]}
|
||||
, ${arg.type} ${arg.var}
|
||||
% endfor
|
||||
) {
|
||||
struct trace_${trace_name} *__entry =
|
||||
(struct trace_${trace_name} *)u_trace_append(ut, &__tp_${trace_name});
|
||||
(void)__entry;
|
||||
% for member in trace.tp_struct:
|
||||
__entry->${member[1]} = ${member[2]};
|
||||
% for arg in trace.tp_struct:
|
||||
__entry->${arg.name} = ${arg.var};
|
||||
% endfor
|
||||
}
|
||||
|
||||
@@ -267,7 +326,7 @@ def utrace_generate(cpath, hpath, ctx_param):
|
||||
f.write(Template(src_template).render(
|
||||
hdr=hdr,
|
||||
ctx_param=ctx_param,
|
||||
HEADERS=HEADERS,
|
||||
HEADERS=[h for h in HEADERS if h.scope & HeaderScope.SOURCE],
|
||||
TRACEPOINTS=TRACEPOINTS))
|
||||
|
||||
if hpath is not None:
|
||||
@@ -276,6 +335,75 @@ def utrace_generate(cpath, hpath, ctx_param):
|
||||
f.write(Template(hdr_template).render(
|
||||
hdrname=hdr.rstrip('.h').upper(),
|
||||
ctx_param=ctx_param,
|
||||
HEADERS=HEADERS,
|
||||
HEADERS=[h for h in HEADERS if h.scope & HeaderScope.HEADER],
|
||||
FORWARD_DECLS=FORWARD_DECLS,
|
||||
TRACEPOINTS=TRACEPOINTS))
|
||||
|
||||
|
||||
perfetto_utils_hdr_template = """\
|
||||
/*
|
||||
* Copyright © 2021 Igalia S.L.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
<% guard_name = '_' + hdrname + '_H' %>
|
||||
#ifndef ${guard_name}
|
||||
#define ${guard_name}
|
||||
|
||||
#include <perfetto.h>
|
||||
|
||||
% for trace_name, trace in TRACEPOINTS.items():
|
||||
static void UNUSED
|
||||
trace_payload_as_extra_${trace_name}(perfetto::protos::pbzero::GpuRenderStageEvent *event,
|
||||
const struct trace_${trace_name} *payload)
|
||||
{
|
||||
% if all([trace.tp_perfetto, trace.tp_struct]) and len(trace.tp_struct) > 0:
|
||||
char buf[128];
|
||||
|
||||
% for arg in trace.tp_struct:
|
||||
{
|
||||
auto data = event->add_extra_data();
|
||||
data->set_name("${arg.name}");
|
||||
|
||||
% if arg.to_prim_type:
|
||||
sprintf(buf, "${arg.c_format}", ${arg.to_prim_type.format('payload->' + arg.name)});
|
||||
% else:
|
||||
sprintf(buf, "${arg.c_format}", payload->${arg.name});
|
||||
% endif
|
||||
|
||||
data->set_value(buf);
|
||||
}
|
||||
% endfor
|
||||
|
||||
% endif
|
||||
}
|
||||
% endfor
|
||||
|
||||
#endif /* ${guard_name} */
|
||||
"""
|
||||
|
||||
def utrace_generate_perfetto_utils(hpath):
|
||||
if hpath is not None:
|
||||
hdr = os.path.basename(hpath)
|
||||
with open(hpath, 'wb') as f:
|
||||
f.write(Template(perfetto_utils_hdr_template, output_encoding='utf-8').render(
|
||||
hdrname=hdr.rstrip('.h').upper(),
|
||||
TRACEPOINTS=TRACEPOINTS))
|
||||
|
Reference in New Issue
Block a user