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