diff options
author | Nicolai Hähnle <[email protected]> | 2017-08-15 15:15:47 +0200 |
---|---|---|
committer | Nicolai Hähnle <[email protected]> | 2017-08-22 09:50:40 +0200 |
commit | 177144cefc83f3670d46418c1e401d3f27e2d33e (patch) | |
tree | d7114b0ae3558654f582591fed1bfb3051ded50e /src/gallium/auxiliary | |
parent | 1cc2fd57d1def9f191a3479628497743d670e02d (diff) |
util/log: add auto logger facility
Reviewed-by: Marek Olšák <[email protected]>
Diffstat (limited to 'src/gallium/auxiliary')
-rw-r--r-- | src/gallium/auxiliary/util/u_log.c | 60 | ||||
-rw-r--r-- | src/gallium/auxiliary/util/u_log.h | 17 |
2 files changed, 75 insertions, 2 deletions
diff --git a/src/gallium/auxiliary/util/u_log.c b/src/gallium/auxiliary/util/u_log.c index 6d826f0adda..359b3e10a2e 100644 --- a/src/gallium/auxiliary/util/u_log.c +++ b/src/gallium/auxiliary/util/u_log.c @@ -36,13 +36,18 @@ struct u_log_page { unsigned max_entries; }; +struct u_log_auto_logger { + u_auto_log_fn *callback; + void *data; +}; + /** * Initialize the given logging context. */ void u_log_context_init(struct u_log_context *ctx) { - ctx->cur = NULL; + memset(ctx, 0, sizeof(*ctx)); } /** @@ -55,7 +60,56 @@ void u_log_context_destroy(struct u_log_context *ctx) { u_log_page_destroy(ctx->cur); - ctx->cur = NULL; + FREE(ctx->auto_loggers); + memset(ctx, 0, sizeof(*ctx)); +} + +/** + * Add an auto logger. + * + * Auto loggers are called each time a chunk is added to the log. + */ +void +u_log_add_auto_logger(struct u_log_context *ctx, u_auto_log_fn *callback, + void *data) +{ + struct u_log_auto_logger *new_auto_loggers = + REALLOC(ctx->auto_loggers, + sizeof(*new_auto_loggers) * ctx->num_auto_loggers, + sizeof(*new_auto_loggers) * (ctx->num_auto_loggers + 1)); + if (!new_auto_loggers) { + fprintf(stderr, "Gallium u_log: out of memory\n"); + return; + } + + unsigned idx = ctx->num_auto_loggers++; + ctx->auto_loggers = new_auto_loggers; + ctx->auto_loggers[idx].callback = callback; + ctx->auto_loggers[idx].data = data; +} + +/** + * Make sure that auto loggers have run. + */ +void +u_log_flush(struct u_log_context *ctx) +{ + if (!ctx->num_auto_loggers) + return; + + struct u_log_auto_logger *auto_loggers = ctx->auto_loggers; + unsigned num_auto_loggers = ctx->num_auto_loggers; + + /* Prevent recursion. */ + ctx->num_auto_loggers = 0; + ctx->auto_loggers = NULL; + + for (unsigned i = 0; i < num_auto_loggers; ++i) + auto_loggers[i].callback(auto_loggers[i].data, ctx); + + assert(!ctx->num_auto_loggers); + ctx->num_auto_loggers = num_auto_loggers; + ctx->auto_loggers = auto_loggers; } static void str_print(void *data, FILE *stream) @@ -96,6 +150,8 @@ u_log_chunk(struct u_log_context *ctx, const struct u_log_chunk_type *type, { struct u_log_page *page = ctx->cur; + u_log_flush(ctx); + if (!page) { ctx->cur = CALLOC_STRUCT(u_log_page); page = ctx->cur; diff --git a/src/gallium/auxiliary/util/u_log.h b/src/gallium/auxiliary/util/u_log.h index d4e6018c9f7..09c47caee55 100644 --- a/src/gallium/auxiliary/util/u_log.h +++ b/src/gallium/auxiliary/util/u_log.h @@ -35,6 +35,11 @@ * * Chunks are accumulated into "pages". The manager of the log can periodically * take out the current page using \ref u_log_new_page and dump it to a file. + * + * Furthermore, "auto loggers" can be added to a context, which are callbacks + * that are given the opportunity to add their own logging each time a chunk is + * added. Drivers can use this to lazily log chunks of their command stream. + * Lazy loggers don't need to be re-entrant. */ #ifndef U_LOG_H @@ -45,6 +50,7 @@ #include "u_debug.h" struct u_log_page; +struct u_log_auto_logger; struct u_log_chunk_type { void (*destroy)(void *data); @@ -53,8 +59,12 @@ struct u_log_chunk_type { struct u_log_context { struct u_log_page *cur; + struct u_log_auto_logger *auto_loggers; + unsigned num_auto_loggers; }; +typedef void (u_auto_log_fn)(void *data, struct u_log_context *ctx); + void u_log_context_init(struct u_log_context *ctx); @@ -62,6 +72,13 @@ void u_log_context_destroy(struct u_log_context *ctx); void +u_log_add_auto_logger(struct u_log_context *ctx, u_auto_log_fn *callback, + void *data); + +void +u_log_flush(struct u_log_context *ctx); + +void u_log_printf(struct u_log_context *ctx, const char *fmt, ...) _util_printf_format(2,3); void |