2 * Copyright 2017 Advanced Micro Devices, Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE.
26 #include "util/u_memory.h"
27 #include "util/u_string.h"
30 const struct u_log_chunk_type
*type
;
35 struct page_entry
*entries
;
40 struct u_log_auto_logger
{
41 u_auto_log_fn
*callback
;
46 * Initialize the given logging context.
49 u_log_context_init(struct u_log_context
*ctx
)
51 memset(ctx
, 0, sizeof(*ctx
));
55 * Free all resources associated with the given logging context.
57 * Pages taken from the context via \ref u_log_new_page must be destroyed
61 u_log_context_destroy(struct u_log_context
*ctx
)
63 u_log_page_destroy(ctx
->cur
);
64 FREE(ctx
->auto_loggers
);
65 memset(ctx
, 0, sizeof(*ctx
));
71 * Auto loggers are called each time a chunk is added to the log.
74 u_log_add_auto_logger(struct u_log_context
*ctx
, u_auto_log_fn
*callback
,
77 struct u_log_auto_logger
*new_auto_loggers
=
78 REALLOC(ctx
->auto_loggers
,
79 sizeof(*new_auto_loggers
) * ctx
->num_auto_loggers
,
80 sizeof(*new_auto_loggers
) * (ctx
->num_auto_loggers
+ 1));
81 if (!new_auto_loggers
) {
82 fprintf(stderr
, "Gallium u_log: out of memory\n");
86 unsigned idx
= ctx
->num_auto_loggers
++;
87 ctx
->auto_loggers
= new_auto_loggers
;
88 ctx
->auto_loggers
[idx
].callback
= callback
;
89 ctx
->auto_loggers
[idx
].data
= data
;
93 * Make sure that auto loggers have run.
96 u_log_flush(struct u_log_context
*ctx
)
98 if (!ctx
->num_auto_loggers
)
101 struct u_log_auto_logger
*auto_loggers
= ctx
->auto_loggers
;
102 unsigned num_auto_loggers
= ctx
->num_auto_loggers
;
104 /* Prevent recursion. */
105 ctx
->num_auto_loggers
= 0;
106 ctx
->auto_loggers
= NULL
;
108 for (unsigned i
= 0; i
< num_auto_loggers
; ++i
)
109 auto_loggers
[i
].callback(auto_loggers
[i
].data
, ctx
);
111 assert(!ctx
->num_auto_loggers
);
112 ctx
->num_auto_loggers
= num_auto_loggers
;
113 ctx
->auto_loggers
= auto_loggers
;
116 static void str_print(void *data
, FILE *stream
)
118 fputs((char *)data
, stream
);
121 static const struct u_log_chunk_type str_chunk_type
= {
127 u_log_printf(struct u_log_context
*ctx
, const char *fmt
, ...)
133 int ret
= vasprintf(&str
, fmt
, va
);
137 u_log_chunk(ctx
, &str_chunk_type
, str
);
139 fprintf(stderr
, "Gallium u_log_printf: out of memory\n");
144 * Add a custom chunk to the log.
146 * type->destroy will be called as soon as \p data is no longer needed.
149 u_log_chunk(struct u_log_context
*ctx
, const struct u_log_chunk_type
*type
,
152 struct u_log_page
*page
= ctx
->cur
;
157 ctx
->cur
= CALLOC_STRUCT(u_log_page
);
163 if (page
->num_entries
>= page
->max_entries
) {
164 unsigned new_max_entries
= MAX2(16, page
->num_entries
* 2);
165 struct page_entry
*new_entries
= REALLOC(page
->entries
,
166 page
->max_entries
* sizeof(*page
->entries
),
167 new_max_entries
* sizeof(*page
->entries
));
171 page
->entries
= new_entries
;
172 page
->max_entries
= new_max_entries
;
175 page
->entries
[page
->num_entries
].type
= type
;
176 page
->entries
[page
->num_entries
].data
= data
;
181 fprintf(stderr
, "Gallium: u_log: out of memory\n");
185 * Convenience helper that starts a new page and prints the previous one.
188 u_log_new_page_print(struct u_log_context
*ctx
, FILE *stream
)
193 u_log_page_print(ctx
->cur
, stream
);
194 u_log_page_destroy(ctx
->cur
);
200 * Return the current page from the logging context and start a new one.
202 * The caller is responsible for destroying the returned page.
205 u_log_new_page(struct u_log_context
*ctx
)
209 struct u_log_page
*page
= ctx
->cur
;
215 * Free all data associated with \p page.
218 u_log_page_destroy(struct u_log_page
*page
)
223 for (unsigned i
= 0; i
< page
->num_entries
; ++i
) {
224 if (page
->entries
[i
].type
->destroy
)
225 page
->entries
[i
].type
->destroy(page
->entries
[i
].data
);
232 * Print the given page to \p stream.
235 u_log_page_print(struct u_log_page
*page
, FILE *stream
)
237 for (unsigned i
= 0; i
< page
->num_entries
; ++i
)
238 page
->entries
[i
].type
->print(page
->entries
[i
].data
, stream
);