xref: /aosp_15_r20/external/mesa3d/src/util/perf/u_trace.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright © 2020 Google, Inc.
3*61046927SAndroid Build Coastguard Worker  *
4*61046927SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
5*61046927SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
6*61046927SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
7*61046927SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*61046927SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
9*61046927SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
10*61046927SAndroid Build Coastguard Worker  *
11*61046927SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the next
12*61046927SAndroid Build Coastguard Worker  * paragraph) shall be included in all copies or substantial portions of the
13*61046927SAndroid Build Coastguard Worker  * Software.
14*61046927SAndroid Build Coastguard Worker  *
15*61046927SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*61046927SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*61046927SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18*61046927SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*61046927SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*61046927SAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21*61046927SAndroid Build Coastguard Worker  * DEALINGS IN THE SOFTWARE.
22*61046927SAndroid Build Coastguard Worker  */
23*61046927SAndroid Build Coastguard Worker 
24*61046927SAndroid Build Coastguard Worker #include "u_trace.h"
25*61046927SAndroid Build Coastguard Worker 
26*61046927SAndroid Build Coastguard Worker #include <inttypes.h>
27*61046927SAndroid Build Coastguard Worker 
28*61046927SAndroid Build Coastguard Worker #include "util/list.h"
29*61046927SAndroid Build Coastguard Worker #include "util/u_call_once.h"
30*61046927SAndroid Build Coastguard Worker #include "util/u_debug.h"
31*61046927SAndroid Build Coastguard Worker #include "util/u_vector.h"
32*61046927SAndroid Build Coastguard Worker 
33*61046927SAndroid Build Coastguard Worker #define __NEEDS_TRACE_PRIV
34*61046927SAndroid Build Coastguard Worker #include "u_trace_priv.h"
35*61046927SAndroid Build Coastguard Worker 
36*61046927SAndroid Build Coastguard Worker #define PAYLOAD_BUFFER_SIZE 0x100
37*61046927SAndroid Build Coastguard Worker #define TIMESTAMP_BUF_SIZE 0x1000
38*61046927SAndroid Build Coastguard Worker #define TRACES_PER_CHUNK (TIMESTAMP_BUF_SIZE / sizeof(uint64_t))
39*61046927SAndroid Build Coastguard Worker 
40*61046927SAndroid Build Coastguard Worker struct u_trace_state {
41*61046927SAndroid Build Coastguard Worker    util_once_flag once;
42*61046927SAndroid Build Coastguard Worker    FILE *trace_file;
43*61046927SAndroid Build Coastguard Worker    enum u_trace_type enabled_traces;
44*61046927SAndroid Build Coastguard Worker };
45*61046927SAndroid Build Coastguard Worker static struct u_trace_state u_trace_state = { .once = UTIL_ONCE_FLAG_INIT };
46*61046927SAndroid Build Coastguard Worker 
47*61046927SAndroid Build Coastguard Worker #ifdef HAVE_PERFETTO
48*61046927SAndroid Build Coastguard Worker /**
49*61046927SAndroid Build Coastguard Worker  * Global list of contexts, so we can defer starting the queue until
50*61046927SAndroid Build Coastguard Worker  * perfetto tracing is started.
51*61046927SAndroid Build Coastguard Worker  */
52*61046927SAndroid Build Coastguard Worker static struct list_head ctx_list = { &ctx_list, &ctx_list };
53*61046927SAndroid Build Coastguard Worker 
54*61046927SAndroid Build Coastguard Worker static simple_mtx_t ctx_list_mutex = SIMPLE_MTX_INITIALIZER;
55*61046927SAndroid Build Coastguard Worker /* The amount of Perfetto tracers connected */
56*61046927SAndroid Build Coastguard Worker int _u_trace_perfetto_count;
57*61046927SAndroid Build Coastguard Worker #endif
58*61046927SAndroid Build Coastguard Worker 
59*61046927SAndroid Build Coastguard Worker struct u_trace_payload_buf {
60*61046927SAndroid Build Coastguard Worker    uint32_t refcount;
61*61046927SAndroid Build Coastguard Worker 
62*61046927SAndroid Build Coastguard Worker    uint8_t *buf;
63*61046927SAndroid Build Coastguard Worker    uint8_t *next;
64*61046927SAndroid Build Coastguard Worker    uint8_t *end;
65*61046927SAndroid Build Coastguard Worker };
66*61046927SAndroid Build Coastguard Worker 
67*61046927SAndroid Build Coastguard Worker struct u_trace_event {
68*61046927SAndroid Build Coastguard Worker    const struct u_tracepoint *tp;
69*61046927SAndroid Build Coastguard Worker    const void *payload;
70*61046927SAndroid Build Coastguard Worker };
71*61046927SAndroid Build Coastguard Worker 
72*61046927SAndroid Build Coastguard Worker /**
73*61046927SAndroid Build Coastguard Worker  * A "chunk" of trace-events and corresponding timestamp buffer.  As
74*61046927SAndroid Build Coastguard Worker  * trace events are emitted, additional trace chucks will be allocated
75*61046927SAndroid Build Coastguard Worker  * as needed.  When u_trace_flush() is called, they are transferred
76*61046927SAndroid Build Coastguard Worker  * from the u_trace to the u_trace_context queue.
77*61046927SAndroid Build Coastguard Worker  */
78*61046927SAndroid Build Coastguard Worker struct u_trace_chunk {
79*61046927SAndroid Build Coastguard Worker    struct list_head node;
80*61046927SAndroid Build Coastguard Worker 
81*61046927SAndroid Build Coastguard Worker    struct u_trace_context *utctx;
82*61046927SAndroid Build Coastguard Worker 
83*61046927SAndroid Build Coastguard Worker    /* The number of traces this chunk contains so far: */
84*61046927SAndroid Build Coastguard Worker    unsigned num_traces;
85*61046927SAndroid Build Coastguard Worker 
86*61046927SAndroid Build Coastguard Worker    /* table of trace events: */
87*61046927SAndroid Build Coastguard Worker    struct u_trace_event traces[TRACES_PER_CHUNK];
88*61046927SAndroid Build Coastguard Worker 
89*61046927SAndroid Build Coastguard Worker    /* table of driver recorded 64b timestamps, index matches index
90*61046927SAndroid Build Coastguard Worker     * into traces table
91*61046927SAndroid Build Coastguard Worker     */
92*61046927SAndroid Build Coastguard Worker    void *timestamps;
93*61046927SAndroid Build Coastguard Worker 
94*61046927SAndroid Build Coastguard Worker    /* table of indirect data captured by u_trace
95*61046927SAndroid Build Coastguard Worker     */
96*61046927SAndroid Build Coastguard Worker    void *indirects;
97*61046927SAndroid Build Coastguard Worker 
98*61046927SAndroid Build Coastguard Worker    /* Array of u_trace_payload_buf referenced by traces[] elements.
99*61046927SAndroid Build Coastguard Worker     */
100*61046927SAndroid Build Coastguard Worker    struct u_vector payloads;
101*61046927SAndroid Build Coastguard Worker 
102*61046927SAndroid Build Coastguard Worker    /* Current payload buffer being written. */
103*61046927SAndroid Build Coastguard Worker    struct u_trace_payload_buf *payload;
104*61046927SAndroid Build Coastguard Worker 
105*61046927SAndroid Build Coastguard Worker    struct util_queue_fence fence;
106*61046927SAndroid Build Coastguard Worker 
107*61046927SAndroid Build Coastguard Worker    bool has_indirect;
108*61046927SAndroid Build Coastguard Worker    bool last; /* this chunk is last in batch */
109*61046927SAndroid Build Coastguard Worker    bool eof;  /* this chunk is last in frame, unless frame_nr is set */
110*61046927SAndroid Build Coastguard Worker    uint32_t frame_nr; /* frame idx from the driver */
111*61046927SAndroid Build Coastguard Worker 
112*61046927SAndroid Build Coastguard Worker    void *flush_data; /* assigned by u_trace_flush */
113*61046927SAndroid Build Coastguard Worker 
114*61046927SAndroid Build Coastguard Worker    /**
115*61046927SAndroid Build Coastguard Worker     * Several chunks reference a single flush_data instance thus only
116*61046927SAndroid Build Coastguard Worker     * one chunk should be designated to free the data.
117*61046927SAndroid Build Coastguard Worker     */
118*61046927SAndroid Build Coastguard Worker    bool free_flush_data;
119*61046927SAndroid Build Coastguard Worker };
120*61046927SAndroid Build Coastguard Worker 
121*61046927SAndroid Build Coastguard Worker struct u_trace_printer {
122*61046927SAndroid Build Coastguard Worker    void (*start)(struct u_trace_context *utctx);
123*61046927SAndroid Build Coastguard Worker    void (*end)(struct u_trace_context *utctx);
124*61046927SAndroid Build Coastguard Worker    void (*start_of_frame)(struct u_trace_context *utctx);
125*61046927SAndroid Build Coastguard Worker    void (*end_of_frame)(struct u_trace_context *utctx);
126*61046927SAndroid Build Coastguard Worker    void (*start_of_batch)(struct u_trace_context *utctx);
127*61046927SAndroid Build Coastguard Worker    void (*end_of_batch)(struct u_trace_context *utctx);
128*61046927SAndroid Build Coastguard Worker    void (*event)(struct u_trace_context *utctx,
129*61046927SAndroid Build Coastguard Worker                  struct u_trace_chunk *chunk,
130*61046927SAndroid Build Coastguard Worker                  const struct u_trace_event *evt,
131*61046927SAndroid Build Coastguard Worker                  uint64_t ns,
132*61046927SAndroid Build Coastguard Worker                  int32_t delta,
133*61046927SAndroid Build Coastguard Worker                  const void *indirect);
134*61046927SAndroid Build Coastguard Worker };
135*61046927SAndroid Build Coastguard Worker 
136*61046927SAndroid Build Coastguard Worker static void
print_txt_start(struct u_trace_context * utctx)137*61046927SAndroid Build Coastguard Worker print_txt_start(struct u_trace_context *utctx)
138*61046927SAndroid Build Coastguard Worker {
139*61046927SAndroid Build Coastguard Worker }
140*61046927SAndroid Build Coastguard Worker 
141*61046927SAndroid Build Coastguard Worker static void
print_txt_end_of_frame(struct u_trace_context * utctx)142*61046927SAndroid Build Coastguard Worker print_txt_end_of_frame(struct u_trace_context *utctx)
143*61046927SAndroid Build Coastguard Worker {
144*61046927SAndroid Build Coastguard Worker    fprintf(utctx->out, "END OF FRAME %u\n", utctx->frame_nr);
145*61046927SAndroid Build Coastguard Worker }
146*61046927SAndroid Build Coastguard Worker 
147*61046927SAndroid Build Coastguard Worker static void
print_txt_start_of_batch(struct u_trace_context * utctx)148*61046927SAndroid Build Coastguard Worker print_txt_start_of_batch(struct u_trace_context *utctx)
149*61046927SAndroid Build Coastguard Worker {
150*61046927SAndroid Build Coastguard Worker    fprintf(utctx->out, "+----- NS -----+ +-- Δ --+  +----- MSG -----\n");
151*61046927SAndroid Build Coastguard Worker }
152*61046927SAndroid Build Coastguard Worker 
153*61046927SAndroid Build Coastguard Worker static void
print_txt_end_of_batch(struct u_trace_context * utctx)154*61046927SAndroid Build Coastguard Worker print_txt_end_of_batch(struct u_trace_context *utctx)
155*61046927SAndroid Build Coastguard Worker {
156*61046927SAndroid Build Coastguard Worker    uint64_t elapsed = utctx->last_time_ns - utctx->first_time_ns;
157*61046927SAndroid Build Coastguard Worker    fprintf(utctx->out, "ELAPSED: %" PRIu64 " ns\n", elapsed);
158*61046927SAndroid Build Coastguard Worker }
159*61046927SAndroid Build Coastguard Worker 
160*61046927SAndroid Build Coastguard Worker static void
print_txt_event(struct u_trace_context * utctx,struct u_trace_chunk * chunk,const struct u_trace_event * evt,uint64_t ns,int32_t delta,const void * indirect)161*61046927SAndroid Build Coastguard Worker print_txt_event(struct u_trace_context *utctx,
162*61046927SAndroid Build Coastguard Worker                 struct u_trace_chunk *chunk,
163*61046927SAndroid Build Coastguard Worker                 const struct u_trace_event *evt,
164*61046927SAndroid Build Coastguard Worker                 uint64_t ns,
165*61046927SAndroid Build Coastguard Worker                 int32_t delta,
166*61046927SAndroid Build Coastguard Worker                 const void *indirect)
167*61046927SAndroid Build Coastguard Worker {
168*61046927SAndroid Build Coastguard Worker    if (evt->tp->print) {
169*61046927SAndroid Build Coastguard Worker       fprintf(utctx->out, "%016" PRIu64 " %+9d: %s: ", ns, delta,
170*61046927SAndroid Build Coastguard Worker               evt->tp->name);
171*61046927SAndroid Build Coastguard Worker       evt->tp->print(utctx->out, evt->payload, indirect);
172*61046927SAndroid Build Coastguard Worker    } else {
173*61046927SAndroid Build Coastguard Worker       fprintf(utctx->out, "%016" PRIu64 " %+9d: %s\n", ns, delta,
174*61046927SAndroid Build Coastguard Worker               evt->tp->name);
175*61046927SAndroid Build Coastguard Worker    }
176*61046927SAndroid Build Coastguard Worker }
177*61046927SAndroid Build Coastguard Worker 
178*61046927SAndroid Build Coastguard Worker static struct u_trace_printer txt_printer = {
179*61046927SAndroid Build Coastguard Worker    .start = &print_txt_start,
180*61046927SAndroid Build Coastguard Worker    .end = &print_txt_start,
181*61046927SAndroid Build Coastguard Worker    .start_of_frame = &print_txt_start,
182*61046927SAndroid Build Coastguard Worker    .end_of_frame = &print_txt_end_of_frame,
183*61046927SAndroid Build Coastguard Worker    .start_of_batch = &print_txt_start_of_batch,
184*61046927SAndroid Build Coastguard Worker    .end_of_batch = &print_txt_end_of_batch,
185*61046927SAndroid Build Coastguard Worker    .event = &print_txt_event,
186*61046927SAndroid Build Coastguard Worker };
187*61046927SAndroid Build Coastguard Worker 
188*61046927SAndroid Build Coastguard Worker static void
print_csv_start(struct u_trace_context * utctx)189*61046927SAndroid Build Coastguard Worker print_csv_start(struct u_trace_context *utctx)
190*61046927SAndroid Build Coastguard Worker {
191*61046927SAndroid Build Coastguard Worker    fprintf(utctx->out, "frame,batch,time_ns,event,\n");
192*61046927SAndroid Build Coastguard Worker }
193*61046927SAndroid Build Coastguard Worker 
194*61046927SAndroid Build Coastguard Worker static void
print_csv_end(struct u_trace_context * utctx)195*61046927SAndroid Build Coastguard Worker print_csv_end(struct u_trace_context *utctx)
196*61046927SAndroid Build Coastguard Worker {
197*61046927SAndroid Build Coastguard Worker    fprintf(utctx->out, "\n");
198*61046927SAndroid Build Coastguard Worker }
199*61046927SAndroid Build Coastguard Worker 
200*61046927SAndroid Build Coastguard Worker static void
print_csv_start_of_frame(struct u_trace_context * utctx)201*61046927SAndroid Build Coastguard Worker print_csv_start_of_frame(struct u_trace_context *utctx)
202*61046927SAndroid Build Coastguard Worker {
203*61046927SAndroid Build Coastguard Worker }
204*61046927SAndroid Build Coastguard Worker 
205*61046927SAndroid Build Coastguard Worker static void
print_csv_end_of_frame(struct u_trace_context * utctx)206*61046927SAndroid Build Coastguard Worker print_csv_end_of_frame(struct u_trace_context *utctx)
207*61046927SAndroid Build Coastguard Worker {
208*61046927SAndroid Build Coastguard Worker }
209*61046927SAndroid Build Coastguard Worker 
210*61046927SAndroid Build Coastguard Worker static void
print_csv_start_of_batch(struct u_trace_context * utctx)211*61046927SAndroid Build Coastguard Worker print_csv_start_of_batch(struct u_trace_context *utctx)
212*61046927SAndroid Build Coastguard Worker {
213*61046927SAndroid Build Coastguard Worker }
214*61046927SAndroid Build Coastguard Worker 
215*61046927SAndroid Build Coastguard Worker static void
print_csv_end_of_batch(struct u_trace_context * utctx)216*61046927SAndroid Build Coastguard Worker print_csv_end_of_batch(struct u_trace_context *utctx)
217*61046927SAndroid Build Coastguard Worker {
218*61046927SAndroid Build Coastguard Worker }
219*61046927SAndroid Build Coastguard Worker 
220*61046927SAndroid Build Coastguard Worker static void
print_csv_event(struct u_trace_context * utctx,struct u_trace_chunk * chunk,const struct u_trace_event * evt,uint64_t ns,int32_t delta,const void * indirect)221*61046927SAndroid Build Coastguard Worker print_csv_event(struct u_trace_context *utctx,
222*61046927SAndroid Build Coastguard Worker                 struct u_trace_chunk *chunk,
223*61046927SAndroid Build Coastguard Worker                 const struct u_trace_event *evt,
224*61046927SAndroid Build Coastguard Worker                 uint64_t ns,
225*61046927SAndroid Build Coastguard Worker                 int32_t delta,
226*61046927SAndroid Build Coastguard Worker                 const void *indirect)
227*61046927SAndroid Build Coastguard Worker {
228*61046927SAndroid Build Coastguard Worker    fprintf(utctx->out, "%u,%u,%"PRIu64",%s,\n",
229*61046927SAndroid Build Coastguard Worker            utctx->frame_nr, utctx->batch_nr, ns, evt->tp->name);
230*61046927SAndroid Build Coastguard Worker }
231*61046927SAndroid Build Coastguard Worker 
232*61046927SAndroid Build Coastguard Worker static struct u_trace_printer csv_printer = {
233*61046927SAndroid Build Coastguard Worker    .start = print_csv_start,
234*61046927SAndroid Build Coastguard Worker    .end = print_csv_end,
235*61046927SAndroid Build Coastguard Worker    .start_of_frame = &print_csv_start_of_frame,
236*61046927SAndroid Build Coastguard Worker    .end_of_frame = &print_csv_end_of_frame,
237*61046927SAndroid Build Coastguard Worker    .start_of_batch = &print_csv_start_of_batch,
238*61046927SAndroid Build Coastguard Worker    .end_of_batch = &print_csv_end_of_batch,
239*61046927SAndroid Build Coastguard Worker    .event = &print_csv_event,
240*61046927SAndroid Build Coastguard Worker };
241*61046927SAndroid Build Coastguard Worker 
242*61046927SAndroid Build Coastguard Worker static void
print_json_start(struct u_trace_context * utctx)243*61046927SAndroid Build Coastguard Worker print_json_start(struct u_trace_context *utctx)
244*61046927SAndroid Build Coastguard Worker {
245*61046927SAndroid Build Coastguard Worker    fprintf(utctx->out, "[\n");
246*61046927SAndroid Build Coastguard Worker }
247*61046927SAndroid Build Coastguard Worker 
248*61046927SAndroid Build Coastguard Worker static void
print_json_end(struct u_trace_context * utctx)249*61046927SAndroid Build Coastguard Worker print_json_end(struct u_trace_context *utctx)
250*61046927SAndroid Build Coastguard Worker {
251*61046927SAndroid Build Coastguard Worker    fprintf(utctx->out, "\n]");
252*61046927SAndroid Build Coastguard Worker }
253*61046927SAndroid Build Coastguard Worker 
254*61046927SAndroid Build Coastguard Worker static void
print_json_start_of_frame(struct u_trace_context * utctx)255*61046927SAndroid Build Coastguard Worker print_json_start_of_frame(struct u_trace_context *utctx)
256*61046927SAndroid Build Coastguard Worker {
257*61046927SAndroid Build Coastguard Worker    if (utctx->frame_nr != 0)
258*61046927SAndroid Build Coastguard Worker       fprintf(utctx->out, ",\n");
259*61046927SAndroid Build Coastguard Worker    fprintf(utctx->out, "{\n\"frame\": %u,\n", utctx->frame_nr);
260*61046927SAndroid Build Coastguard Worker    fprintf(utctx->out, "\"batches\": [\n");
261*61046927SAndroid Build Coastguard Worker }
262*61046927SAndroid Build Coastguard Worker 
263*61046927SAndroid Build Coastguard Worker static void
print_json_end_of_frame(struct u_trace_context * utctx)264*61046927SAndroid Build Coastguard Worker print_json_end_of_frame(struct u_trace_context *utctx)
265*61046927SAndroid Build Coastguard Worker {
266*61046927SAndroid Build Coastguard Worker    fprintf(utctx->out, "]\n}\n");
267*61046927SAndroid Build Coastguard Worker    fflush(utctx->out);
268*61046927SAndroid Build Coastguard Worker }
269*61046927SAndroid Build Coastguard Worker 
270*61046927SAndroid Build Coastguard Worker static void
print_json_start_of_batch(struct u_trace_context * utctx)271*61046927SAndroid Build Coastguard Worker print_json_start_of_batch(struct u_trace_context *utctx)
272*61046927SAndroid Build Coastguard Worker {
273*61046927SAndroid Build Coastguard Worker    if (utctx->batch_nr != 0)
274*61046927SAndroid Build Coastguard Worker       fprintf(utctx->out, ",\n");
275*61046927SAndroid Build Coastguard Worker    fprintf(utctx->out, "{\n\"events\": [\n");
276*61046927SAndroid Build Coastguard Worker }
277*61046927SAndroid Build Coastguard Worker 
278*61046927SAndroid Build Coastguard Worker static void
print_json_end_of_batch(struct u_trace_context * utctx)279*61046927SAndroid Build Coastguard Worker print_json_end_of_batch(struct u_trace_context *utctx)
280*61046927SAndroid Build Coastguard Worker {
281*61046927SAndroid Build Coastguard Worker    uint64_t elapsed = utctx->last_time_ns - utctx->first_time_ns;
282*61046927SAndroid Build Coastguard Worker    fprintf(utctx->out, "],\n");
283*61046927SAndroid Build Coastguard Worker    fprintf(utctx->out, "\"duration_ns\": %" PRIu64 "\n", elapsed);
284*61046927SAndroid Build Coastguard Worker    fprintf(utctx->out, "}\n");
285*61046927SAndroid Build Coastguard Worker }
286*61046927SAndroid Build Coastguard Worker 
287*61046927SAndroid Build Coastguard Worker static void
print_json_event(struct u_trace_context * utctx,struct u_trace_chunk * chunk,const struct u_trace_event * evt,uint64_t ns,int32_t delta,const void * indirect)288*61046927SAndroid Build Coastguard Worker print_json_event(struct u_trace_context *utctx,
289*61046927SAndroid Build Coastguard Worker                  struct u_trace_chunk *chunk,
290*61046927SAndroid Build Coastguard Worker                  const struct u_trace_event *evt,
291*61046927SAndroid Build Coastguard Worker                  uint64_t ns,
292*61046927SAndroid Build Coastguard Worker                  int32_t delta,
293*61046927SAndroid Build Coastguard Worker                  const void *indirect)
294*61046927SAndroid Build Coastguard Worker {
295*61046927SAndroid Build Coastguard Worker    if (utctx->event_nr != 0)
296*61046927SAndroid Build Coastguard Worker       fprintf(utctx->out, ",\n");
297*61046927SAndroid Build Coastguard Worker    fprintf(utctx->out, "{\n\"event\": \"%s\",\n", evt->tp->name);
298*61046927SAndroid Build Coastguard Worker    fprintf(utctx->out, "\"time_ns\": \"%016" PRIu64 "\",\n", ns);
299*61046927SAndroid Build Coastguard Worker    fprintf(utctx->out, "\"params\": {");
300*61046927SAndroid Build Coastguard Worker    if (evt->tp->print)
301*61046927SAndroid Build Coastguard Worker       evt->tp->print_json(utctx->out, evt->payload, indirect);
302*61046927SAndroid Build Coastguard Worker    fprintf(utctx->out, "}\n}\n");
303*61046927SAndroid Build Coastguard Worker }
304*61046927SAndroid Build Coastguard Worker 
305*61046927SAndroid Build Coastguard Worker static struct u_trace_printer json_printer = {
306*61046927SAndroid Build Coastguard Worker    .start = print_json_start,
307*61046927SAndroid Build Coastguard Worker    .end = print_json_end,
308*61046927SAndroid Build Coastguard Worker    .start_of_frame = &print_json_start_of_frame,
309*61046927SAndroid Build Coastguard Worker    .end_of_frame = &print_json_end_of_frame,
310*61046927SAndroid Build Coastguard Worker    .start_of_batch = &print_json_start_of_batch,
311*61046927SAndroid Build Coastguard Worker    .end_of_batch = &print_json_end_of_batch,
312*61046927SAndroid Build Coastguard Worker    .event = &print_json_event,
313*61046927SAndroid Build Coastguard Worker };
314*61046927SAndroid Build Coastguard Worker 
315*61046927SAndroid Build Coastguard Worker static struct u_trace_payload_buf *
u_trace_payload_buf_create(void)316*61046927SAndroid Build Coastguard Worker u_trace_payload_buf_create(void)
317*61046927SAndroid Build Coastguard Worker {
318*61046927SAndroid Build Coastguard Worker    struct u_trace_payload_buf *payload =
319*61046927SAndroid Build Coastguard Worker       malloc(sizeof(*payload) + PAYLOAD_BUFFER_SIZE);
320*61046927SAndroid Build Coastguard Worker 
321*61046927SAndroid Build Coastguard Worker    p_atomic_set(&payload->refcount, 1);
322*61046927SAndroid Build Coastguard Worker 
323*61046927SAndroid Build Coastguard Worker    payload->buf = (uint8_t *) (payload + 1);
324*61046927SAndroid Build Coastguard Worker    payload->end = payload->buf + PAYLOAD_BUFFER_SIZE;
325*61046927SAndroid Build Coastguard Worker    payload->next = payload->buf;
326*61046927SAndroid Build Coastguard Worker 
327*61046927SAndroid Build Coastguard Worker    return payload;
328*61046927SAndroid Build Coastguard Worker }
329*61046927SAndroid Build Coastguard Worker 
330*61046927SAndroid Build Coastguard Worker static struct u_trace_payload_buf *
u_trace_payload_buf_ref(struct u_trace_payload_buf * payload)331*61046927SAndroid Build Coastguard Worker u_trace_payload_buf_ref(struct u_trace_payload_buf *payload)
332*61046927SAndroid Build Coastguard Worker {
333*61046927SAndroid Build Coastguard Worker    p_atomic_inc(&payload->refcount);
334*61046927SAndroid Build Coastguard Worker    return payload;
335*61046927SAndroid Build Coastguard Worker }
336*61046927SAndroid Build Coastguard Worker 
337*61046927SAndroid Build Coastguard Worker static void
u_trace_payload_buf_unref(struct u_trace_payload_buf * payload)338*61046927SAndroid Build Coastguard Worker u_trace_payload_buf_unref(struct u_trace_payload_buf *payload)
339*61046927SAndroid Build Coastguard Worker {
340*61046927SAndroid Build Coastguard Worker    if (p_atomic_dec_zero(&payload->refcount))
341*61046927SAndroid Build Coastguard Worker       free(payload);
342*61046927SAndroid Build Coastguard Worker }
343*61046927SAndroid Build Coastguard Worker 
344*61046927SAndroid Build Coastguard Worker static void
free_chunk(void * ptr)345*61046927SAndroid Build Coastguard Worker free_chunk(void *ptr)
346*61046927SAndroid Build Coastguard Worker {
347*61046927SAndroid Build Coastguard Worker    struct u_trace_chunk *chunk = ptr;
348*61046927SAndroid Build Coastguard Worker 
349*61046927SAndroid Build Coastguard Worker    chunk->utctx->delete_buffer(chunk->utctx, chunk->timestamps);
350*61046927SAndroid Build Coastguard Worker    if (chunk->indirects)
351*61046927SAndroid Build Coastguard Worker       chunk->utctx->delete_buffer(chunk->utctx, chunk->indirects);
352*61046927SAndroid Build Coastguard Worker 
353*61046927SAndroid Build Coastguard Worker    /* Unref payloads attached to this chunk. */
354*61046927SAndroid Build Coastguard Worker    struct u_trace_payload_buf **payload;
355*61046927SAndroid Build Coastguard Worker    u_vector_foreach (payload, &chunk->payloads)
356*61046927SAndroid Build Coastguard Worker       u_trace_payload_buf_unref(*payload);
357*61046927SAndroid Build Coastguard Worker    u_vector_finish(&chunk->payloads);
358*61046927SAndroid Build Coastguard Worker 
359*61046927SAndroid Build Coastguard Worker    list_del(&chunk->node);
360*61046927SAndroid Build Coastguard Worker    free(chunk);
361*61046927SAndroid Build Coastguard Worker }
362*61046927SAndroid Build Coastguard Worker 
363*61046927SAndroid Build Coastguard Worker static void
free_chunks(struct list_head * chunks)364*61046927SAndroid Build Coastguard Worker free_chunks(struct list_head *chunks)
365*61046927SAndroid Build Coastguard Worker {
366*61046927SAndroid Build Coastguard Worker    while (!list_is_empty(chunks)) {
367*61046927SAndroid Build Coastguard Worker       struct u_trace_chunk *chunk =
368*61046927SAndroid Build Coastguard Worker          list_first_entry(chunks, struct u_trace_chunk, node);
369*61046927SAndroid Build Coastguard Worker       free_chunk(chunk);
370*61046927SAndroid Build Coastguard Worker    }
371*61046927SAndroid Build Coastguard Worker }
372*61046927SAndroid Build Coastguard Worker 
373*61046927SAndroid Build Coastguard Worker static struct u_trace_chunk *
get_chunk(struct u_trace * ut,size_t payload_size)374*61046927SAndroid Build Coastguard Worker get_chunk(struct u_trace *ut, size_t payload_size)
375*61046927SAndroid Build Coastguard Worker {
376*61046927SAndroid Build Coastguard Worker    struct u_trace_chunk *chunk;
377*61046927SAndroid Build Coastguard Worker 
378*61046927SAndroid Build Coastguard Worker    assert(payload_size <= PAYLOAD_BUFFER_SIZE);
379*61046927SAndroid Build Coastguard Worker 
380*61046927SAndroid Build Coastguard Worker    /* do we currently have a non-full chunk to append msgs to? */
381*61046927SAndroid Build Coastguard Worker    if (!list_is_empty(&ut->trace_chunks)) {
382*61046927SAndroid Build Coastguard Worker       chunk = list_last_entry(&ut->trace_chunks, struct u_trace_chunk, node);
383*61046927SAndroid Build Coastguard Worker       /* Can we store a new trace in the chunk? */
384*61046927SAndroid Build Coastguard Worker       if (chunk->num_traces < TRACES_PER_CHUNK) {
385*61046927SAndroid Build Coastguard Worker          /* If no payload required, nothing else to check. */
386*61046927SAndroid Build Coastguard Worker          if (payload_size <= 0)
387*61046927SAndroid Build Coastguard Worker             return chunk;
388*61046927SAndroid Build Coastguard Worker 
389*61046927SAndroid Build Coastguard Worker          /* If the payload buffer has space for the payload, we're good.
390*61046927SAndroid Build Coastguard Worker           */
391*61046927SAndroid Build Coastguard Worker          if (chunk->payload &&
392*61046927SAndroid Build Coastguard Worker              (chunk->payload->end - chunk->payload->next) >= payload_size)
393*61046927SAndroid Build Coastguard Worker             return chunk;
394*61046927SAndroid Build Coastguard Worker 
395*61046927SAndroid Build Coastguard Worker          /* If we don't have enough space in the payload buffer, can we
396*61046927SAndroid Build Coastguard Worker           * allocate a new one?
397*61046927SAndroid Build Coastguard Worker           */
398*61046927SAndroid Build Coastguard Worker          struct u_trace_payload_buf **buf = u_vector_add(&chunk->payloads);
399*61046927SAndroid Build Coastguard Worker          *buf = u_trace_payload_buf_create();
400*61046927SAndroid Build Coastguard Worker          chunk->payload = *buf;
401*61046927SAndroid Build Coastguard Worker          return chunk;
402*61046927SAndroid Build Coastguard Worker       }
403*61046927SAndroid Build Coastguard Worker       /* we need to expand to add another chunk to the batch, so
404*61046927SAndroid Build Coastguard Worker        * the current one is no longer the last one of the batch:
405*61046927SAndroid Build Coastguard Worker        */
406*61046927SAndroid Build Coastguard Worker       chunk->last = false;
407*61046927SAndroid Build Coastguard Worker    }
408*61046927SAndroid Build Coastguard Worker 
409*61046927SAndroid Build Coastguard Worker    /* .. if not, then create a new one: */
410*61046927SAndroid Build Coastguard Worker    chunk = calloc(1, sizeof(*chunk));
411*61046927SAndroid Build Coastguard Worker 
412*61046927SAndroid Build Coastguard Worker    chunk->utctx = ut->utctx;
413*61046927SAndroid Build Coastguard Worker    chunk->timestamps =
414*61046927SAndroid Build Coastguard Worker       ut->utctx->create_buffer(ut->utctx,
415*61046927SAndroid Build Coastguard Worker                                chunk->utctx->timestamp_size_bytes * TIMESTAMP_BUF_SIZE);
416*61046927SAndroid Build Coastguard Worker    if (chunk->utctx->max_indirect_size_bytes &&
417*61046927SAndroid Build Coastguard Worker        (chunk->utctx->enabled_traces & U_TRACE_TYPE_INDIRECTS)) {
418*61046927SAndroid Build Coastguard Worker       chunk->indirects =
419*61046927SAndroid Build Coastguard Worker          ut->utctx->create_buffer(ut->utctx,
420*61046927SAndroid Build Coastguard Worker                                   chunk->utctx->max_indirect_size_bytes * TIMESTAMP_BUF_SIZE);
421*61046927SAndroid Build Coastguard Worker    }
422*61046927SAndroid Build Coastguard Worker    chunk->last = true;
423*61046927SAndroid Build Coastguard Worker    u_vector_init(&chunk->payloads, 4, sizeof(struct u_trace_payload_buf *));
424*61046927SAndroid Build Coastguard Worker    if (payload_size > 0) {
425*61046927SAndroid Build Coastguard Worker       struct u_trace_payload_buf **buf = u_vector_add(&chunk->payloads);
426*61046927SAndroid Build Coastguard Worker       *buf = u_trace_payload_buf_create();
427*61046927SAndroid Build Coastguard Worker       chunk->payload = *buf;
428*61046927SAndroid Build Coastguard Worker    }
429*61046927SAndroid Build Coastguard Worker 
430*61046927SAndroid Build Coastguard Worker    list_addtail(&chunk->node, &ut->trace_chunks);
431*61046927SAndroid Build Coastguard Worker 
432*61046927SAndroid Build Coastguard Worker    return chunk;
433*61046927SAndroid Build Coastguard Worker }
434*61046927SAndroid Build Coastguard Worker 
435*61046927SAndroid Build Coastguard Worker static const struct debug_named_value config_control[] = {
436*61046927SAndroid Build Coastguard Worker    { "print", U_TRACE_TYPE_PRINT, "Enable print" },
437*61046927SAndroid Build Coastguard Worker    { "print_csv", U_TRACE_TYPE_PRINT_CSV, "Enable print in CSV" },
438*61046927SAndroid Build Coastguard Worker    { "print_json", U_TRACE_TYPE_PRINT_JSON, "Enable print in JSON" },
439*61046927SAndroid Build Coastguard Worker #ifdef HAVE_PERFETTO
440*61046927SAndroid Build Coastguard Worker    { "perfetto", U_TRACE_TYPE_PERFETTO_ENV, "Enable perfetto" },
441*61046927SAndroid Build Coastguard Worker #endif
442*61046927SAndroid Build Coastguard Worker    { "markers", U_TRACE_TYPE_MARKERS, "Enable marker trace" },
443*61046927SAndroid Build Coastguard Worker    { "indirects", U_TRACE_TYPE_INDIRECTS, "Enable indirect data capture" },
444*61046927SAndroid Build Coastguard Worker    DEBUG_NAMED_VALUE_END
445*61046927SAndroid Build Coastguard Worker };
446*61046927SAndroid Build Coastguard Worker 
447*61046927SAndroid Build Coastguard Worker DEBUG_GET_ONCE_OPTION(trace_file, "MESA_GPU_TRACEFILE", NULL)
448*61046927SAndroid Build Coastguard Worker 
449*61046927SAndroid Build Coastguard Worker static void
trace_file_fini(void)450*61046927SAndroid Build Coastguard Worker trace_file_fini(void)
451*61046927SAndroid Build Coastguard Worker {
452*61046927SAndroid Build Coastguard Worker    fclose(u_trace_state.trace_file);
453*61046927SAndroid Build Coastguard Worker    u_trace_state.trace_file = NULL;
454*61046927SAndroid Build Coastguard Worker }
455*61046927SAndroid Build Coastguard Worker 
456*61046927SAndroid Build Coastguard Worker static void
u_trace_state_init_once(void)457*61046927SAndroid Build Coastguard Worker u_trace_state_init_once(void)
458*61046927SAndroid Build Coastguard Worker {
459*61046927SAndroid Build Coastguard Worker    u_trace_state.enabled_traces =
460*61046927SAndroid Build Coastguard Worker       debug_get_flags_option("MESA_GPU_TRACES", config_control, 0);
461*61046927SAndroid Build Coastguard Worker    const char *tracefile_name = debug_get_option_trace_file();
462*61046927SAndroid Build Coastguard Worker    if (tracefile_name && __normal_user()) {
463*61046927SAndroid Build Coastguard Worker       u_trace_state.trace_file = fopen(tracefile_name, "w");
464*61046927SAndroid Build Coastguard Worker       if (u_trace_state.trace_file != NULL) {
465*61046927SAndroid Build Coastguard Worker          atexit(trace_file_fini);
466*61046927SAndroid Build Coastguard Worker       }
467*61046927SAndroid Build Coastguard Worker    }
468*61046927SAndroid Build Coastguard Worker    if (!u_trace_state.trace_file) {
469*61046927SAndroid Build Coastguard Worker       u_trace_state.trace_file = stdout;
470*61046927SAndroid Build Coastguard Worker    }
471*61046927SAndroid Build Coastguard Worker }
472*61046927SAndroid Build Coastguard Worker 
473*61046927SAndroid Build Coastguard Worker void
u_trace_state_init(void)474*61046927SAndroid Build Coastguard Worker u_trace_state_init(void)
475*61046927SAndroid Build Coastguard Worker {
476*61046927SAndroid Build Coastguard Worker    util_call_once(&u_trace_state.once, u_trace_state_init_once);
477*61046927SAndroid Build Coastguard Worker }
478*61046927SAndroid Build Coastguard Worker 
479*61046927SAndroid Build Coastguard Worker bool
u_trace_is_enabled(enum u_trace_type type)480*61046927SAndroid Build Coastguard Worker u_trace_is_enabled(enum u_trace_type type)
481*61046927SAndroid Build Coastguard Worker {
482*61046927SAndroid Build Coastguard Worker    /* Active is only tracked in a given u_trace context, so if you're asking
483*61046927SAndroid Build Coastguard Worker     * us if U_TRACE_TYPE_PERFETTO (_ENV | _ACTIVE) is enabled, then just check
484*61046927SAndroid Build Coastguard Worker     * _ENV ("perfetto tracing is desired, but perfetto might not be running").
485*61046927SAndroid Build Coastguard Worker     */
486*61046927SAndroid Build Coastguard Worker    type &= ~U_TRACE_TYPE_PERFETTO_ACTIVE;
487*61046927SAndroid Build Coastguard Worker 
488*61046927SAndroid Build Coastguard Worker    return (u_trace_state.enabled_traces & type) == type;
489*61046927SAndroid Build Coastguard Worker }
490*61046927SAndroid Build Coastguard Worker 
491*61046927SAndroid Build Coastguard Worker static void
queue_init(struct u_trace_context * utctx)492*61046927SAndroid Build Coastguard Worker queue_init(struct u_trace_context *utctx)
493*61046927SAndroid Build Coastguard Worker {
494*61046927SAndroid Build Coastguard Worker    if (utctx->queue.jobs)
495*61046927SAndroid Build Coastguard Worker       return;
496*61046927SAndroid Build Coastguard Worker 
497*61046927SAndroid Build Coastguard Worker    bool ret = util_queue_init(
498*61046927SAndroid Build Coastguard Worker       &utctx->queue, "traceq", 256, 1,
499*61046927SAndroid Build Coastguard Worker       UTIL_QUEUE_INIT_USE_MINIMUM_PRIORITY | UTIL_QUEUE_INIT_RESIZE_IF_FULL,
500*61046927SAndroid Build Coastguard Worker       NULL);
501*61046927SAndroid Build Coastguard Worker    assert(ret);
502*61046927SAndroid Build Coastguard Worker 
503*61046927SAndroid Build Coastguard Worker    if (!ret)
504*61046927SAndroid Build Coastguard Worker       utctx->out = NULL;
505*61046927SAndroid Build Coastguard Worker }
506*61046927SAndroid Build Coastguard Worker 
507*61046927SAndroid Build Coastguard Worker void
u_trace_context_init(struct u_trace_context * utctx,void * pctx,uint32_t timestamp_size_bytes,uint32_t max_indirect_size_bytes,u_trace_create_buffer create_buffer,u_trace_delete_buffer delete_buffer,u_trace_record_ts record_timestamp,u_trace_read_ts read_timestamp,u_trace_capture_data capture_data,u_trace_get_data get_data,u_trace_delete_flush_data delete_flush_data)508*61046927SAndroid Build Coastguard Worker u_trace_context_init(struct u_trace_context *utctx,
509*61046927SAndroid Build Coastguard Worker                      void *pctx,
510*61046927SAndroid Build Coastguard Worker                      uint32_t timestamp_size_bytes,
511*61046927SAndroid Build Coastguard Worker                      uint32_t max_indirect_size_bytes,
512*61046927SAndroid Build Coastguard Worker                      u_trace_create_buffer create_buffer,
513*61046927SAndroid Build Coastguard Worker                      u_trace_delete_buffer delete_buffer,
514*61046927SAndroid Build Coastguard Worker                      u_trace_record_ts record_timestamp,
515*61046927SAndroid Build Coastguard Worker                      u_trace_read_ts read_timestamp,
516*61046927SAndroid Build Coastguard Worker                      u_trace_capture_data capture_data,
517*61046927SAndroid Build Coastguard Worker                      u_trace_get_data get_data,
518*61046927SAndroid Build Coastguard Worker                      u_trace_delete_flush_data delete_flush_data)
519*61046927SAndroid Build Coastguard Worker {
520*61046927SAndroid Build Coastguard Worker    u_trace_state_init();
521*61046927SAndroid Build Coastguard Worker 
522*61046927SAndroid Build Coastguard Worker    utctx->enabled_traces = u_trace_state.enabled_traces;
523*61046927SAndroid Build Coastguard Worker    utctx->pctx = pctx;
524*61046927SAndroid Build Coastguard Worker    utctx->create_buffer = create_buffer;
525*61046927SAndroid Build Coastguard Worker    utctx->delete_buffer = delete_buffer;
526*61046927SAndroid Build Coastguard Worker    utctx->record_timestamp = record_timestamp;
527*61046927SAndroid Build Coastguard Worker    utctx->capture_data = capture_data;
528*61046927SAndroid Build Coastguard Worker    utctx->get_data = get_data;
529*61046927SAndroid Build Coastguard Worker    utctx->read_timestamp = read_timestamp;
530*61046927SAndroid Build Coastguard Worker    utctx->delete_flush_data = delete_flush_data;
531*61046927SAndroid Build Coastguard Worker    utctx->timestamp_size_bytes = timestamp_size_bytes;
532*61046927SAndroid Build Coastguard Worker    utctx->max_indirect_size_bytes = max_indirect_size_bytes;
533*61046927SAndroid Build Coastguard Worker 
534*61046927SAndroid Build Coastguard Worker    utctx->last_time_ns = 0;
535*61046927SAndroid Build Coastguard Worker    utctx->first_time_ns = 0;
536*61046927SAndroid Build Coastguard Worker    utctx->frame_nr = 0;
537*61046927SAndroid Build Coastguard Worker    utctx->batch_nr = 0;
538*61046927SAndroid Build Coastguard Worker    utctx->event_nr = 0;
539*61046927SAndroid Build Coastguard Worker    utctx->start_of_frame = true;
540*61046927SAndroid Build Coastguard Worker 
541*61046927SAndroid Build Coastguard Worker    utctx->dummy_indirect_data = calloc(1, max_indirect_size_bytes);
542*61046927SAndroid Build Coastguard Worker 
543*61046927SAndroid Build Coastguard Worker    list_inithead(&utctx->flushed_trace_chunks);
544*61046927SAndroid Build Coastguard Worker 
545*61046927SAndroid Build Coastguard Worker    if (utctx->enabled_traces & U_TRACE_TYPE_PRINT) {
546*61046927SAndroid Build Coastguard Worker       utctx->out = u_trace_state.trace_file;
547*61046927SAndroid Build Coastguard Worker 
548*61046927SAndroid Build Coastguard Worker       if (utctx->enabled_traces & U_TRACE_TYPE_JSON) {
549*61046927SAndroid Build Coastguard Worker          utctx->out_printer = &json_printer;
550*61046927SAndroid Build Coastguard Worker       } else if (utctx->enabled_traces & U_TRACE_TYPE_CSV) {
551*61046927SAndroid Build Coastguard Worker          utctx->out_printer = &csv_printer;
552*61046927SAndroid Build Coastguard Worker       } else {
553*61046927SAndroid Build Coastguard Worker          utctx->out_printer = &txt_printer;
554*61046927SAndroid Build Coastguard Worker       }
555*61046927SAndroid Build Coastguard Worker    } else {
556*61046927SAndroid Build Coastguard Worker       utctx->out = NULL;
557*61046927SAndroid Build Coastguard Worker       utctx->out_printer = NULL;
558*61046927SAndroid Build Coastguard Worker    }
559*61046927SAndroid Build Coastguard Worker 
560*61046927SAndroid Build Coastguard Worker #ifdef HAVE_PERFETTO
561*61046927SAndroid Build Coastguard Worker    simple_mtx_lock(&ctx_list_mutex);
562*61046927SAndroid Build Coastguard Worker    list_add(&utctx->node, &ctx_list);
563*61046927SAndroid Build Coastguard Worker    if (_u_trace_perfetto_count > 0)
564*61046927SAndroid Build Coastguard Worker       utctx->enabled_traces |= U_TRACE_TYPE_PERFETTO_ACTIVE;
565*61046927SAndroid Build Coastguard Worker 
566*61046927SAndroid Build Coastguard Worker    queue_init(utctx);
567*61046927SAndroid Build Coastguard Worker 
568*61046927SAndroid Build Coastguard Worker    simple_mtx_unlock(&ctx_list_mutex);
569*61046927SAndroid Build Coastguard Worker #else
570*61046927SAndroid Build Coastguard Worker    queue_init(utctx);
571*61046927SAndroid Build Coastguard Worker #endif
572*61046927SAndroid Build Coastguard Worker 
573*61046927SAndroid Build Coastguard Worker    if (!(p_atomic_read_relaxed(&utctx->enabled_traces) &
574*61046927SAndroid Build Coastguard Worker          U_TRACE_TYPE_REQUIRE_QUEUING))
575*61046927SAndroid Build Coastguard Worker       return;
576*61046927SAndroid Build Coastguard Worker 
577*61046927SAndroid Build Coastguard Worker    if (utctx->out) {
578*61046927SAndroid Build Coastguard Worker       utctx->out_printer->start(utctx);
579*61046927SAndroid Build Coastguard Worker    }
580*61046927SAndroid Build Coastguard Worker }
581*61046927SAndroid Build Coastguard Worker 
582*61046927SAndroid Build Coastguard Worker void
u_trace_context_fini(struct u_trace_context * utctx)583*61046927SAndroid Build Coastguard Worker u_trace_context_fini(struct u_trace_context *utctx)
584*61046927SAndroid Build Coastguard Worker {
585*61046927SAndroid Build Coastguard Worker #ifdef HAVE_PERFETTO
586*61046927SAndroid Build Coastguard Worker    simple_mtx_lock(&ctx_list_mutex);
587*61046927SAndroid Build Coastguard Worker    list_del(&utctx->node);
588*61046927SAndroid Build Coastguard Worker    simple_mtx_unlock(&ctx_list_mutex);
589*61046927SAndroid Build Coastguard Worker #endif
590*61046927SAndroid Build Coastguard Worker 
591*61046927SAndroid Build Coastguard Worker    if (utctx->out) {
592*61046927SAndroid Build Coastguard Worker       if (utctx->batch_nr > 0) {
593*61046927SAndroid Build Coastguard Worker          utctx->out_printer->end_of_frame(utctx);
594*61046927SAndroid Build Coastguard Worker       }
595*61046927SAndroid Build Coastguard Worker 
596*61046927SAndroid Build Coastguard Worker       utctx->out_printer->end(utctx);
597*61046927SAndroid Build Coastguard Worker       fflush(utctx->out);
598*61046927SAndroid Build Coastguard Worker    }
599*61046927SAndroid Build Coastguard Worker 
600*61046927SAndroid Build Coastguard Worker    free (utctx->dummy_indirect_data);
601*61046927SAndroid Build Coastguard Worker 
602*61046927SAndroid Build Coastguard Worker    if (!utctx->queue.jobs)
603*61046927SAndroid Build Coastguard Worker       return;
604*61046927SAndroid Build Coastguard Worker    util_queue_finish(&utctx->queue);
605*61046927SAndroid Build Coastguard Worker    util_queue_destroy(&utctx->queue);
606*61046927SAndroid Build Coastguard Worker    free_chunks(&utctx->flushed_trace_chunks);
607*61046927SAndroid Build Coastguard Worker }
608*61046927SAndroid Build Coastguard Worker 
609*61046927SAndroid Build Coastguard Worker #ifdef HAVE_PERFETTO
610*61046927SAndroid Build Coastguard Worker void
u_trace_perfetto_start(void)611*61046927SAndroid Build Coastguard Worker u_trace_perfetto_start(void)
612*61046927SAndroid Build Coastguard Worker {
613*61046927SAndroid Build Coastguard Worker    simple_mtx_lock(&ctx_list_mutex);
614*61046927SAndroid Build Coastguard Worker 
615*61046927SAndroid Build Coastguard Worker    list_for_each_entry (struct u_trace_context, utctx, &ctx_list, node) {
616*61046927SAndroid Build Coastguard Worker       queue_init(utctx);
617*61046927SAndroid Build Coastguard Worker       p_atomic_set(&utctx->enabled_traces,
618*61046927SAndroid Build Coastguard Worker                    utctx->enabled_traces | U_TRACE_TYPE_PERFETTO_ACTIVE);
619*61046927SAndroid Build Coastguard Worker    }
620*61046927SAndroid Build Coastguard Worker 
621*61046927SAndroid Build Coastguard Worker    _u_trace_perfetto_count++;
622*61046927SAndroid Build Coastguard Worker 
623*61046927SAndroid Build Coastguard Worker    simple_mtx_unlock(&ctx_list_mutex);
624*61046927SAndroid Build Coastguard Worker }
625*61046927SAndroid Build Coastguard Worker 
626*61046927SAndroid Build Coastguard Worker void
u_trace_perfetto_stop(void)627*61046927SAndroid Build Coastguard Worker u_trace_perfetto_stop(void)
628*61046927SAndroid Build Coastguard Worker {
629*61046927SAndroid Build Coastguard Worker    simple_mtx_lock(&ctx_list_mutex);
630*61046927SAndroid Build Coastguard Worker 
631*61046927SAndroid Build Coastguard Worker    assert(_u_trace_perfetto_count > 0);
632*61046927SAndroid Build Coastguard Worker    _u_trace_perfetto_count--;
633*61046927SAndroid Build Coastguard Worker    if (_u_trace_perfetto_count == 0) {
634*61046927SAndroid Build Coastguard Worker       list_for_each_entry (struct u_trace_context, utctx, &ctx_list, node) {
635*61046927SAndroid Build Coastguard Worker          p_atomic_set(&utctx->enabled_traces,
636*61046927SAndroid Build Coastguard Worker                       utctx->enabled_traces & ~U_TRACE_TYPE_PERFETTO_ACTIVE);
637*61046927SAndroid Build Coastguard Worker       }
638*61046927SAndroid Build Coastguard Worker    }
639*61046927SAndroid Build Coastguard Worker 
640*61046927SAndroid Build Coastguard Worker    simple_mtx_unlock(&ctx_list_mutex);
641*61046927SAndroid Build Coastguard Worker }
642*61046927SAndroid Build Coastguard Worker #endif
643*61046927SAndroid Build Coastguard Worker 
644*61046927SAndroid Build Coastguard Worker static void
process_chunk(void * job,void * gdata,int thread_index)645*61046927SAndroid Build Coastguard Worker process_chunk(void *job, void *gdata, int thread_index)
646*61046927SAndroid Build Coastguard Worker {
647*61046927SAndroid Build Coastguard Worker    struct u_trace_chunk *chunk = job;
648*61046927SAndroid Build Coastguard Worker    struct u_trace_context *utctx = chunk->utctx;
649*61046927SAndroid Build Coastguard Worker 
650*61046927SAndroid Build Coastguard Worker    if (chunk->frame_nr != U_TRACE_FRAME_UNKNOWN &&
651*61046927SAndroid Build Coastguard Worker        chunk->frame_nr != utctx->frame_nr) {
652*61046927SAndroid Build Coastguard Worker       if (utctx->out) {
653*61046927SAndroid Build Coastguard Worker          utctx->out_printer->end_of_frame(utctx);
654*61046927SAndroid Build Coastguard Worker       }
655*61046927SAndroid Build Coastguard Worker       utctx->frame_nr = chunk->frame_nr;
656*61046927SAndroid Build Coastguard Worker       utctx->start_of_frame = true;
657*61046927SAndroid Build Coastguard Worker    }
658*61046927SAndroid Build Coastguard Worker 
659*61046927SAndroid Build Coastguard Worker    if (utctx->start_of_frame) {
660*61046927SAndroid Build Coastguard Worker       utctx->start_of_frame = false;
661*61046927SAndroid Build Coastguard Worker       utctx->batch_nr = 0;
662*61046927SAndroid Build Coastguard Worker       if (utctx->out) {
663*61046927SAndroid Build Coastguard Worker          utctx->out_printer->start_of_frame(utctx);
664*61046927SAndroid Build Coastguard Worker       }
665*61046927SAndroid Build Coastguard Worker    }
666*61046927SAndroid Build Coastguard Worker 
667*61046927SAndroid Build Coastguard Worker    /* For first chunk of batch, accumulated times will be zerod: */
668*61046927SAndroid Build Coastguard Worker    if (!utctx->last_time_ns) {
669*61046927SAndroid Build Coastguard Worker       utctx->event_nr = 0;
670*61046927SAndroid Build Coastguard Worker       if (utctx->out) {
671*61046927SAndroid Build Coastguard Worker          utctx->out_printer->start_of_batch(utctx);
672*61046927SAndroid Build Coastguard Worker       }
673*61046927SAndroid Build Coastguard Worker    }
674*61046927SAndroid Build Coastguard Worker 
675*61046927SAndroid Build Coastguard Worker    for (unsigned idx = 0; idx < chunk->num_traces; idx++) {
676*61046927SAndroid Build Coastguard Worker       const struct u_trace_event *evt = &chunk->traces[idx];
677*61046927SAndroid Build Coastguard Worker 
678*61046927SAndroid Build Coastguard Worker       if (!evt->tp)
679*61046927SAndroid Build Coastguard Worker          continue;
680*61046927SAndroid Build Coastguard Worker 
681*61046927SAndroid Build Coastguard Worker       uint64_t ns = utctx->read_timestamp(utctx,
682*61046927SAndroid Build Coastguard Worker                                           chunk->timestamps,
683*61046927SAndroid Build Coastguard Worker                                           utctx->timestamp_size_bytes * idx,
684*61046927SAndroid Build Coastguard Worker                                           chunk->flush_data);
685*61046927SAndroid Build Coastguard Worker       int32_t delta;
686*61046927SAndroid Build Coastguard Worker 
687*61046927SAndroid Build Coastguard Worker       if (!utctx->first_time_ns)
688*61046927SAndroid Build Coastguard Worker          utctx->first_time_ns = ns;
689*61046927SAndroid Build Coastguard Worker 
690*61046927SAndroid Build Coastguard Worker       if (ns != U_TRACE_NO_TIMESTAMP) {
691*61046927SAndroid Build Coastguard Worker          delta = utctx->last_time_ns ? ns - utctx->last_time_ns : 0;
692*61046927SAndroid Build Coastguard Worker          utctx->last_time_ns = ns;
693*61046927SAndroid Build Coastguard Worker       } else {
694*61046927SAndroid Build Coastguard Worker          /* we skipped recording the timestamp, so it should be
695*61046927SAndroid Build Coastguard Worker           * the same as last msg:
696*61046927SAndroid Build Coastguard Worker           */
697*61046927SAndroid Build Coastguard Worker          ns = utctx->last_time_ns;
698*61046927SAndroid Build Coastguard Worker          delta = 0;
699*61046927SAndroid Build Coastguard Worker       }
700*61046927SAndroid Build Coastguard Worker 
701*61046927SAndroid Build Coastguard Worker       const void *indirect_data = NULL;
702*61046927SAndroid Build Coastguard Worker       if (evt->tp->indirect_sz > 0) {
703*61046927SAndroid Build Coastguard Worker          if (utctx->enabled_traces & U_TRACE_TYPE_INDIRECTS) {
704*61046927SAndroid Build Coastguard Worker             indirect_data = utctx->get_data(utctx, chunk->indirects,
705*61046927SAndroid Build Coastguard Worker                                             utctx->max_indirect_size_bytes * idx,
706*61046927SAndroid Build Coastguard Worker                                             evt->tp->indirect_sz);
707*61046927SAndroid Build Coastguard Worker          } else {
708*61046927SAndroid Build Coastguard Worker             indirect_data = utctx->dummy_indirect_data;
709*61046927SAndroid Build Coastguard Worker          }
710*61046927SAndroid Build Coastguard Worker       }
711*61046927SAndroid Build Coastguard Worker 
712*61046927SAndroid Build Coastguard Worker       if (utctx->out) {
713*61046927SAndroid Build Coastguard Worker          utctx->out_printer->event(utctx, chunk, evt, ns, delta, indirect_data);
714*61046927SAndroid Build Coastguard Worker       }
715*61046927SAndroid Build Coastguard Worker #ifdef HAVE_PERFETTO
716*61046927SAndroid Build Coastguard Worker       if (evt->tp->perfetto &&
717*61046927SAndroid Build Coastguard Worker           (p_atomic_read_relaxed(&utctx->enabled_traces) &
718*61046927SAndroid Build Coastguard Worker            U_TRACE_TYPE_PERFETTO_ACTIVE)) {
719*61046927SAndroid Build Coastguard Worker          evt->tp->perfetto(utctx->pctx, ns, evt->tp->tp_idx, chunk->flush_data,
720*61046927SAndroid Build Coastguard Worker                            evt->payload, indirect_data);
721*61046927SAndroid Build Coastguard Worker       }
722*61046927SAndroid Build Coastguard Worker #endif
723*61046927SAndroid Build Coastguard Worker 
724*61046927SAndroid Build Coastguard Worker       utctx->event_nr++;
725*61046927SAndroid Build Coastguard Worker    }
726*61046927SAndroid Build Coastguard Worker 
727*61046927SAndroid Build Coastguard Worker    if (chunk->last) {
728*61046927SAndroid Build Coastguard Worker       if (utctx->out) {
729*61046927SAndroid Build Coastguard Worker          utctx->out_printer->end_of_batch(utctx);
730*61046927SAndroid Build Coastguard Worker       }
731*61046927SAndroid Build Coastguard Worker 
732*61046927SAndroid Build Coastguard Worker       utctx->batch_nr++;
733*61046927SAndroid Build Coastguard Worker       utctx->last_time_ns = 0;
734*61046927SAndroid Build Coastguard Worker       utctx->first_time_ns = 0;
735*61046927SAndroid Build Coastguard Worker    }
736*61046927SAndroid Build Coastguard Worker 
737*61046927SAndroid Build Coastguard Worker    if (chunk->eof) {
738*61046927SAndroid Build Coastguard Worker       if (utctx->out) {
739*61046927SAndroid Build Coastguard Worker          utctx->out_printer->end_of_frame(utctx);
740*61046927SAndroid Build Coastguard Worker       }
741*61046927SAndroid Build Coastguard Worker       utctx->frame_nr++;
742*61046927SAndroid Build Coastguard Worker       utctx->start_of_frame = true;
743*61046927SAndroid Build Coastguard Worker    }
744*61046927SAndroid Build Coastguard Worker 
745*61046927SAndroid Build Coastguard Worker    if (chunk->free_flush_data && utctx->delete_flush_data) {
746*61046927SAndroid Build Coastguard Worker       utctx->delete_flush_data(utctx, chunk->flush_data);
747*61046927SAndroid Build Coastguard Worker    }
748*61046927SAndroid Build Coastguard Worker }
749*61046927SAndroid Build Coastguard Worker 
750*61046927SAndroid Build Coastguard Worker static void
cleanup_chunk(void * job,void * gdata,int thread_index)751*61046927SAndroid Build Coastguard Worker cleanup_chunk(void *job, void *gdata, int thread_index)
752*61046927SAndroid Build Coastguard Worker {
753*61046927SAndroid Build Coastguard Worker    free_chunk(job);
754*61046927SAndroid Build Coastguard Worker }
755*61046927SAndroid Build Coastguard Worker 
756*61046927SAndroid Build Coastguard Worker void
u_trace_context_process(struct u_trace_context * utctx,bool eof)757*61046927SAndroid Build Coastguard Worker u_trace_context_process(struct u_trace_context *utctx, bool eof)
758*61046927SAndroid Build Coastguard Worker {
759*61046927SAndroid Build Coastguard Worker    struct list_head *chunks = &utctx->flushed_trace_chunks;
760*61046927SAndroid Build Coastguard Worker 
761*61046927SAndroid Build Coastguard Worker    if (list_is_empty(chunks))
762*61046927SAndroid Build Coastguard Worker       return;
763*61046927SAndroid Build Coastguard Worker 
764*61046927SAndroid Build Coastguard Worker    struct u_trace_chunk *last_chunk =
765*61046927SAndroid Build Coastguard Worker       list_last_entry(chunks, struct u_trace_chunk, node);
766*61046927SAndroid Build Coastguard Worker    last_chunk->eof = eof;
767*61046927SAndroid Build Coastguard Worker 
768*61046927SAndroid Build Coastguard Worker    while (!list_is_empty(chunks)) {
769*61046927SAndroid Build Coastguard Worker       struct u_trace_chunk *chunk =
770*61046927SAndroid Build Coastguard Worker          list_first_entry(chunks, struct u_trace_chunk, node);
771*61046927SAndroid Build Coastguard Worker 
772*61046927SAndroid Build Coastguard Worker       /* remove from list before enqueuing, because chunk is freed
773*61046927SAndroid Build Coastguard Worker        * once it is processed by the queue:
774*61046927SAndroid Build Coastguard Worker        */
775*61046927SAndroid Build Coastguard Worker       list_delinit(&chunk->node);
776*61046927SAndroid Build Coastguard Worker 
777*61046927SAndroid Build Coastguard Worker       util_queue_add_job(&utctx->queue, chunk, &chunk->fence, process_chunk,
778*61046927SAndroid Build Coastguard Worker                          cleanup_chunk, TIMESTAMP_BUF_SIZE);
779*61046927SAndroid Build Coastguard Worker    }
780*61046927SAndroid Build Coastguard Worker }
781*61046927SAndroid Build Coastguard Worker 
782*61046927SAndroid Build Coastguard Worker void
u_trace_init(struct u_trace * ut,struct u_trace_context * utctx)783*61046927SAndroid Build Coastguard Worker u_trace_init(struct u_trace *ut, struct u_trace_context *utctx)
784*61046927SAndroid Build Coastguard Worker {
785*61046927SAndroid Build Coastguard Worker    ut->utctx = utctx;
786*61046927SAndroid Build Coastguard Worker    ut->num_traces = 0;
787*61046927SAndroid Build Coastguard Worker    list_inithead(&ut->trace_chunks);
788*61046927SAndroid Build Coastguard Worker }
789*61046927SAndroid Build Coastguard Worker 
790*61046927SAndroid Build Coastguard Worker void
u_trace_fini(struct u_trace * ut)791*61046927SAndroid Build Coastguard Worker u_trace_fini(struct u_trace *ut)
792*61046927SAndroid Build Coastguard Worker {
793*61046927SAndroid Build Coastguard Worker    /* Normally the list of trace-chunks would be empty, if they
794*61046927SAndroid Build Coastguard Worker     * have been flushed to the trace-context.
795*61046927SAndroid Build Coastguard Worker     */
796*61046927SAndroid Build Coastguard Worker    free_chunks(&ut->trace_chunks);
797*61046927SAndroid Build Coastguard Worker    ut->num_traces = 0;
798*61046927SAndroid Build Coastguard Worker }
799*61046927SAndroid Build Coastguard Worker 
800*61046927SAndroid Build Coastguard Worker bool
u_trace_has_points(struct u_trace * ut)801*61046927SAndroid Build Coastguard Worker u_trace_has_points(struct u_trace *ut)
802*61046927SAndroid Build Coastguard Worker {
803*61046927SAndroid Build Coastguard Worker    return !list_is_empty(&ut->trace_chunks);
804*61046927SAndroid Build Coastguard Worker }
805*61046927SAndroid Build Coastguard Worker 
806*61046927SAndroid Build Coastguard Worker struct u_trace_iterator
u_trace_begin_iterator(struct u_trace * ut)807*61046927SAndroid Build Coastguard Worker u_trace_begin_iterator(struct u_trace *ut)
808*61046927SAndroid Build Coastguard Worker {
809*61046927SAndroid Build Coastguard Worker    if (list_is_empty(&ut->trace_chunks))
810*61046927SAndroid Build Coastguard Worker       return (struct u_trace_iterator) { ut, NULL, 0 };
811*61046927SAndroid Build Coastguard Worker 
812*61046927SAndroid Build Coastguard Worker    struct u_trace_chunk *first_chunk =
813*61046927SAndroid Build Coastguard Worker       list_first_entry(&ut->trace_chunks, struct u_trace_chunk, node);
814*61046927SAndroid Build Coastguard Worker 
815*61046927SAndroid Build Coastguard Worker    return (struct u_trace_iterator) { ut, first_chunk, 0 };
816*61046927SAndroid Build Coastguard Worker }
817*61046927SAndroid Build Coastguard Worker 
818*61046927SAndroid Build Coastguard Worker struct u_trace_iterator
u_trace_end_iterator(struct u_trace * ut)819*61046927SAndroid Build Coastguard Worker u_trace_end_iterator(struct u_trace *ut)
820*61046927SAndroid Build Coastguard Worker {
821*61046927SAndroid Build Coastguard Worker    if (list_is_empty(&ut->trace_chunks))
822*61046927SAndroid Build Coastguard Worker       return (struct u_trace_iterator) { ut, NULL, 0 };
823*61046927SAndroid Build Coastguard Worker 
824*61046927SAndroid Build Coastguard Worker    struct u_trace_chunk *last_chunk =
825*61046927SAndroid Build Coastguard Worker       list_last_entry(&ut->trace_chunks, struct u_trace_chunk, node);
826*61046927SAndroid Build Coastguard Worker 
827*61046927SAndroid Build Coastguard Worker    return (struct u_trace_iterator) { ut, last_chunk,
828*61046927SAndroid Build Coastguard Worker                                       last_chunk->num_traces };
829*61046927SAndroid Build Coastguard Worker }
830*61046927SAndroid Build Coastguard Worker 
831*61046927SAndroid Build Coastguard Worker /* If an iterator was created when there were no chunks and there are now
832*61046927SAndroid Build Coastguard Worker  * chunks, "sanitize" it to include the first chunk.
833*61046927SAndroid Build Coastguard Worker  */
834*61046927SAndroid Build Coastguard Worker static struct u_trace_iterator
sanitize_iterator(struct u_trace_iterator iter)835*61046927SAndroid Build Coastguard Worker sanitize_iterator(struct u_trace_iterator iter)
836*61046927SAndroid Build Coastguard Worker {
837*61046927SAndroid Build Coastguard Worker    if (iter.ut && !iter.chunk && !list_is_empty(&iter.ut->trace_chunks)) {
838*61046927SAndroid Build Coastguard Worker       iter.chunk =
839*61046927SAndroid Build Coastguard Worker          list_first_entry(&iter.ut->trace_chunks, struct u_trace_chunk, node);
840*61046927SAndroid Build Coastguard Worker    }
841*61046927SAndroid Build Coastguard Worker 
842*61046927SAndroid Build Coastguard Worker    return iter;
843*61046927SAndroid Build Coastguard Worker }
844*61046927SAndroid Build Coastguard Worker 
845*61046927SAndroid Build Coastguard Worker bool
u_trace_iterator_equal(struct u_trace_iterator a,struct u_trace_iterator b)846*61046927SAndroid Build Coastguard Worker u_trace_iterator_equal(struct u_trace_iterator a, struct u_trace_iterator b)
847*61046927SAndroid Build Coastguard Worker {
848*61046927SAndroid Build Coastguard Worker    a = sanitize_iterator(a);
849*61046927SAndroid Build Coastguard Worker    b = sanitize_iterator(b);
850*61046927SAndroid Build Coastguard Worker    return a.ut == b.ut && a.chunk == b.chunk && a.event_idx == b.event_idx;
851*61046927SAndroid Build Coastguard Worker }
852*61046927SAndroid Build Coastguard Worker 
853*61046927SAndroid Build Coastguard Worker void
u_trace_clone_append(struct u_trace_iterator begin_it,struct u_trace_iterator end_it,struct u_trace * into,void * cmdstream,u_trace_copy_buffer copy_buffer)854*61046927SAndroid Build Coastguard Worker u_trace_clone_append(struct u_trace_iterator begin_it,
855*61046927SAndroid Build Coastguard Worker                      struct u_trace_iterator end_it,
856*61046927SAndroid Build Coastguard Worker                      struct u_trace *into,
857*61046927SAndroid Build Coastguard Worker                      void *cmdstream,
858*61046927SAndroid Build Coastguard Worker                      u_trace_copy_buffer copy_buffer)
859*61046927SAndroid Build Coastguard Worker {
860*61046927SAndroid Build Coastguard Worker    begin_it = sanitize_iterator(begin_it);
861*61046927SAndroid Build Coastguard Worker    end_it = sanitize_iterator(end_it);
862*61046927SAndroid Build Coastguard Worker 
863*61046927SAndroid Build Coastguard Worker    struct u_trace_chunk *from_chunk = begin_it.chunk;
864*61046927SAndroid Build Coastguard Worker    uint32_t from_idx = begin_it.event_idx;
865*61046927SAndroid Build Coastguard Worker 
866*61046927SAndroid Build Coastguard Worker    while (from_chunk != end_it.chunk || from_idx != end_it.event_idx) {
867*61046927SAndroid Build Coastguard Worker       struct u_trace_chunk *to_chunk = get_chunk(into, 0 /* payload_size */);
868*61046927SAndroid Build Coastguard Worker 
869*61046927SAndroid Build Coastguard Worker       unsigned to_copy = MIN2(TRACES_PER_CHUNK - to_chunk->num_traces,
870*61046927SAndroid Build Coastguard Worker                               from_chunk->num_traces - from_idx);
871*61046927SAndroid Build Coastguard Worker       if (from_chunk == end_it.chunk)
872*61046927SAndroid Build Coastguard Worker          to_copy = MIN2(to_copy, end_it.event_idx - from_idx);
873*61046927SAndroid Build Coastguard Worker 
874*61046927SAndroid Build Coastguard Worker       copy_buffer(begin_it.ut->utctx, cmdstream,
875*61046927SAndroid Build Coastguard Worker                   from_chunk->timestamps,
876*61046927SAndroid Build Coastguard Worker                   begin_it.ut->utctx->timestamp_size_bytes * from_idx,
877*61046927SAndroid Build Coastguard Worker                   to_chunk->timestamps,
878*61046927SAndroid Build Coastguard Worker                   begin_it.ut->utctx->timestamp_size_bytes * to_chunk->num_traces,
879*61046927SAndroid Build Coastguard Worker                   begin_it.ut->utctx->timestamp_size_bytes * to_copy);
880*61046927SAndroid Build Coastguard Worker 
881*61046927SAndroid Build Coastguard Worker       if (from_chunk->has_indirect) {
882*61046927SAndroid Build Coastguard Worker          copy_buffer(begin_it.ut->utctx, cmdstream,
883*61046927SAndroid Build Coastguard Worker                      from_chunk->indirects,
884*61046927SAndroid Build Coastguard Worker                      begin_it.ut->utctx->max_indirect_size_bytes * from_idx,
885*61046927SAndroid Build Coastguard Worker                      to_chunk->indirects,
886*61046927SAndroid Build Coastguard Worker                      begin_it.ut->utctx->max_indirect_size_bytes * to_chunk->num_traces,
887*61046927SAndroid Build Coastguard Worker                      begin_it.ut->utctx->max_indirect_size_bytes * to_copy);
888*61046927SAndroid Build Coastguard Worker       }
889*61046927SAndroid Build Coastguard Worker 
890*61046927SAndroid Build Coastguard Worker       memcpy(&to_chunk->traces[to_chunk->num_traces],
891*61046927SAndroid Build Coastguard Worker              &from_chunk->traces[from_idx],
892*61046927SAndroid Build Coastguard Worker              to_copy * sizeof(struct u_trace_event));
893*61046927SAndroid Build Coastguard Worker 
894*61046927SAndroid Build Coastguard Worker       /* Take a refcount on payloads from from_chunk if needed. */
895*61046927SAndroid Build Coastguard Worker       if (begin_it.ut != into) {
896*61046927SAndroid Build Coastguard Worker          struct u_trace_payload_buf **in_payload;
897*61046927SAndroid Build Coastguard Worker          u_vector_foreach (in_payload, &from_chunk->payloads) {
898*61046927SAndroid Build Coastguard Worker             struct u_trace_payload_buf **out_payload =
899*61046927SAndroid Build Coastguard Worker                u_vector_add(&to_chunk->payloads);
900*61046927SAndroid Build Coastguard Worker 
901*61046927SAndroid Build Coastguard Worker             *out_payload = u_trace_payload_buf_ref(*in_payload);
902*61046927SAndroid Build Coastguard Worker          }
903*61046927SAndroid Build Coastguard Worker       }
904*61046927SAndroid Build Coastguard Worker 
905*61046927SAndroid Build Coastguard Worker       into->num_traces += to_copy;
906*61046927SAndroid Build Coastguard Worker       to_chunk->num_traces += to_copy;
907*61046927SAndroid Build Coastguard Worker       from_idx += to_copy;
908*61046927SAndroid Build Coastguard Worker 
909*61046927SAndroid Build Coastguard Worker       assert(from_idx <= from_chunk->num_traces);
910*61046927SAndroid Build Coastguard Worker       if (from_idx == from_chunk->num_traces) {
911*61046927SAndroid Build Coastguard Worker          if (from_chunk == end_it.chunk)
912*61046927SAndroid Build Coastguard Worker             break;
913*61046927SAndroid Build Coastguard Worker 
914*61046927SAndroid Build Coastguard Worker          from_idx = 0;
915*61046927SAndroid Build Coastguard Worker          from_chunk =
916*61046927SAndroid Build Coastguard Worker             list_entry(from_chunk->node.next, struct u_trace_chunk, node);
917*61046927SAndroid Build Coastguard Worker       }
918*61046927SAndroid Build Coastguard Worker    }
919*61046927SAndroid Build Coastguard Worker }
920*61046927SAndroid Build Coastguard Worker 
921*61046927SAndroid Build Coastguard Worker void
u_trace_disable_event_range(struct u_trace_iterator begin_it,struct u_trace_iterator end_it)922*61046927SAndroid Build Coastguard Worker u_trace_disable_event_range(struct u_trace_iterator begin_it,
923*61046927SAndroid Build Coastguard Worker                             struct u_trace_iterator end_it)
924*61046927SAndroid Build Coastguard Worker {
925*61046927SAndroid Build Coastguard Worker    begin_it = sanitize_iterator(begin_it);
926*61046927SAndroid Build Coastguard Worker    end_it = sanitize_iterator(end_it);
927*61046927SAndroid Build Coastguard Worker 
928*61046927SAndroid Build Coastguard Worker    struct u_trace_chunk *current_chunk = begin_it.chunk;
929*61046927SAndroid Build Coastguard Worker    uint32_t start_idx = begin_it.event_idx;
930*61046927SAndroid Build Coastguard Worker 
931*61046927SAndroid Build Coastguard Worker    while (current_chunk != end_it.chunk) {
932*61046927SAndroid Build Coastguard Worker       memset(&current_chunk->traces[start_idx], 0,
933*61046927SAndroid Build Coastguard Worker              (current_chunk->num_traces - start_idx) *
934*61046927SAndroid Build Coastguard Worker                 sizeof(struct u_trace_event));
935*61046927SAndroid Build Coastguard Worker       start_idx = 0;
936*61046927SAndroid Build Coastguard Worker       current_chunk =
937*61046927SAndroid Build Coastguard Worker          list_entry(current_chunk->node.next, struct u_trace_chunk, node);
938*61046927SAndroid Build Coastguard Worker    }
939*61046927SAndroid Build Coastguard Worker 
940*61046927SAndroid Build Coastguard Worker    memset(&current_chunk->traces[start_idx], 0,
941*61046927SAndroid Build Coastguard Worker           (end_it.event_idx - start_idx) * sizeof(struct u_trace_event));
942*61046927SAndroid Build Coastguard Worker }
943*61046927SAndroid Build Coastguard Worker 
944*61046927SAndroid Build Coastguard Worker /**
945*61046927SAndroid Build Coastguard Worker  * Append a trace event, returning pointer to buffer of tp->payload_sz
946*61046927SAndroid Build Coastguard Worker  * to be filled in with trace payload.  Called by generated tracepoint
947*61046927SAndroid Build Coastguard Worker  * functions.
948*61046927SAndroid Build Coastguard Worker  */
949*61046927SAndroid Build Coastguard Worker void *
u_trace_appendv(struct u_trace * ut,void * cs,const struct u_tracepoint * tp,unsigned variable_sz,unsigned n_indirects,const struct u_trace_address * addresses,const uint8_t * indirect_sizes_B)950*61046927SAndroid Build Coastguard Worker u_trace_appendv(struct u_trace *ut,
951*61046927SAndroid Build Coastguard Worker                 void *cs,
952*61046927SAndroid Build Coastguard Worker                 const struct u_tracepoint *tp,
953*61046927SAndroid Build Coastguard Worker                 unsigned variable_sz,
954*61046927SAndroid Build Coastguard Worker                 unsigned n_indirects,
955*61046927SAndroid Build Coastguard Worker                 const struct u_trace_address *addresses,
956*61046927SAndroid Build Coastguard Worker                 const uint8_t *indirect_sizes_B)
957*61046927SAndroid Build Coastguard Worker {
958*61046927SAndroid Build Coastguard Worker    assert(tp->payload_sz == ALIGN_NPOT(tp->payload_sz, 8));
959*61046927SAndroid Build Coastguard Worker 
960*61046927SAndroid Build Coastguard Worker    unsigned payload_sz = ALIGN_NPOT(tp->payload_sz + variable_sz, 8);
961*61046927SAndroid Build Coastguard Worker    struct u_trace_chunk *chunk = get_chunk(ut, payload_sz);
962*61046927SAndroid Build Coastguard Worker    unsigned tp_idx = chunk->num_traces++;
963*61046927SAndroid Build Coastguard Worker 
964*61046927SAndroid Build Coastguard Worker    /* sub-allocate storage for trace payload: */
965*61046927SAndroid Build Coastguard Worker    void *payload = NULL;
966*61046927SAndroid Build Coastguard Worker    if (payload_sz > 0) {
967*61046927SAndroid Build Coastguard Worker       payload = chunk->payload->next;
968*61046927SAndroid Build Coastguard Worker       chunk->payload->next += payload_sz;
969*61046927SAndroid Build Coastguard Worker    }
970*61046927SAndroid Build Coastguard Worker 
971*61046927SAndroid Build Coastguard Worker    /* record a timestamp for the trace: */
972*61046927SAndroid Build Coastguard Worker    ut->utctx->record_timestamp(ut, cs, chunk->timestamps,
973*61046927SAndroid Build Coastguard Worker                                ut->utctx->timestamp_size_bytes * tp_idx,
974*61046927SAndroid Build Coastguard Worker                                tp->flags);
975*61046927SAndroid Build Coastguard Worker 
976*61046927SAndroid Build Coastguard Worker    if (ut->utctx->enabled_traces & U_TRACE_TYPE_INDIRECTS) {
977*61046927SAndroid Build Coastguard Worker       for (unsigned i = 0; i < n_indirects; i++) {
978*61046927SAndroid Build Coastguard Worker          ut->utctx->capture_data(ut, cs, chunk->indirects,
979*61046927SAndroid Build Coastguard Worker                                  ut->utctx->max_indirect_size_bytes * tp_idx,
980*61046927SAndroid Build Coastguard Worker                                  addresses[i].bo, addresses[i].offset,
981*61046927SAndroid Build Coastguard Worker                                  indirect_sizes_B[i]);
982*61046927SAndroid Build Coastguard Worker       }
983*61046927SAndroid Build Coastguard Worker       chunk->has_indirect |= n_indirects > 0;
984*61046927SAndroid Build Coastguard Worker    }
985*61046927SAndroid Build Coastguard Worker 
986*61046927SAndroid Build Coastguard Worker    chunk->traces[tp_idx] = (struct u_trace_event) {
987*61046927SAndroid Build Coastguard Worker       .tp = tp,
988*61046927SAndroid Build Coastguard Worker       .payload = payload,
989*61046927SAndroid Build Coastguard Worker    };
990*61046927SAndroid Build Coastguard Worker    ut->num_traces++;
991*61046927SAndroid Build Coastguard Worker 
992*61046927SAndroid Build Coastguard Worker    return payload;
993*61046927SAndroid Build Coastguard Worker }
994*61046927SAndroid Build Coastguard Worker 
995*61046927SAndroid Build Coastguard Worker void
u_trace_flush(struct u_trace * ut,void * flush_data,uint32_t frame_nr,bool free_data)996*61046927SAndroid Build Coastguard Worker u_trace_flush(struct u_trace *ut,
997*61046927SAndroid Build Coastguard Worker               void *flush_data,
998*61046927SAndroid Build Coastguard Worker               uint32_t frame_nr,
999*61046927SAndroid Build Coastguard Worker               bool free_data)
1000*61046927SAndroid Build Coastguard Worker {
1001*61046927SAndroid Build Coastguard Worker    list_for_each_entry (struct u_trace_chunk, chunk, &ut->trace_chunks,
1002*61046927SAndroid Build Coastguard Worker                         node) {
1003*61046927SAndroid Build Coastguard Worker       chunk->flush_data = flush_data;
1004*61046927SAndroid Build Coastguard Worker       chunk->free_flush_data = false;
1005*61046927SAndroid Build Coastguard Worker       chunk->frame_nr = frame_nr;
1006*61046927SAndroid Build Coastguard Worker    }
1007*61046927SAndroid Build Coastguard Worker 
1008*61046927SAndroid Build Coastguard Worker    if (free_data && !list_is_empty(&ut->trace_chunks)) {
1009*61046927SAndroid Build Coastguard Worker       struct u_trace_chunk *last_chunk =
1010*61046927SAndroid Build Coastguard Worker          list_last_entry(&ut->trace_chunks, struct u_trace_chunk, node);
1011*61046927SAndroid Build Coastguard Worker       last_chunk->free_flush_data = true;
1012*61046927SAndroid Build Coastguard Worker    }
1013*61046927SAndroid Build Coastguard Worker 
1014*61046927SAndroid Build Coastguard Worker    /* transfer batch's log chunks to context: */
1015*61046927SAndroid Build Coastguard Worker    list_splicetail(&ut->trace_chunks, &ut->utctx->flushed_trace_chunks);
1016*61046927SAndroid Build Coastguard Worker    list_inithead(&ut->trace_chunks);
1017*61046927SAndroid Build Coastguard Worker    ut->num_traces = 0;
1018*61046927SAndroid Build Coastguard Worker }
1019