diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 86b52c684..f6350c606 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -27,6 +27,7 @@ #include "render/color.h" #include "types/wlr_output.h" #include "util/env.h" +#include "util/trace.h" #include "config.h" #if HAVE_LIBLIFTOFF @@ -615,6 +616,8 @@ static bool drm_commit(struct wlr_drm_backend *drm, // Disallow atomic-only flags assert((flags & ~DRM_MODE_PAGE_FLIP_FLAGS) == 0); + wlr_trace("drm_commit"); + struct wlr_drm_page_flip *page_flip = NULL; if (flags & DRM_MODE_PAGE_FLIP_EVENT) { page_flip = drm_page_flip_create(drm, state); @@ -998,7 +1001,11 @@ static bool drm_connector_test(struct wlr_output *output, static bool drm_connector_commit(struct wlr_output *output, const struct wlr_output_state *state) { struct wlr_drm_connector *conn = get_drm_connector_from_output(output); - return drm_connector_commit_state(conn, state, false); + struct wlr_trace_ctx trace_ctx; + wlr_trace_begin_ctx(&trace_ctx, "drm_connector_commit"); + bool ok = drm_connector_commit_state(conn, state, false); + wlr_trace_end_ctx(&trace_ctx, "drm_connector_commit"); + return ok; } size_t drm_crtc_get_gamma_lut_size(struct wlr_drm_backend *drm, @@ -1989,6 +1996,8 @@ static void handle_page_flip(int fd, unsigned seq, unsigned tv_sec, unsigned tv_usec, unsigned crtc_id, void *data) { struct wlr_drm_page_flip *page_flip = data; + wlr_trace("drm_page_flip_uevent"); + struct wlr_drm_connector *conn = drm_page_flip_pop(page_flip, crtc_id); if (conn != NULL) { conn->pending_page_flip = NULL; diff --git a/include/util/trace.h b/include/util/trace.h new file mode 100644 index 000000000..72c34b3ae --- /dev/null +++ b/include/util/trace.h @@ -0,0 +1,17 @@ +#ifndef UTIL_TRACE_H +#define UTIL_TRACE_H + +#include +#include + +void wlr_trace(const char *format, ...) _WLR_ATTRIB_PRINTF(1, 2); +void wlr_vtrace(const char *format, va_list args) _WLR_ATTRIB_PRINTF(1, 0); + +struct wlr_trace_ctx { + uint32_t seq; +}; + +void wlr_trace_begin_ctx(struct wlr_trace_ctx *ctx, const char *format, ...) _WLR_ATTRIB_PRINTF(2, 3); +void wlr_trace_end_ctx(struct wlr_trace_ctx *ctx, const char *format, ...) _WLR_ATTRIB_PRINTF(2, 3); + +#endif diff --git a/types/wlr_linux_drm_syncobj_v1.c b/types/wlr_linux_drm_syncobj_v1.c index 988d44e01..f5a34561c 100644 --- a/types/wlr_linux_drm_syncobj_v1.c +++ b/types/wlr_linux_drm_syncobj_v1.c @@ -11,6 +11,7 @@ #include #include "config.h" #include "linux-drm-syncobj-v1-protocol.h" +#include "util/trace.h" #define LINUX_DRM_SYNCOBJ_V1_VERSION 1 @@ -214,6 +215,9 @@ static void surface_commit_handle_surface_destroy(struct wl_listener *listener, // Block the surface commit until the fence materializes static bool lock_surface_commit(struct wlr_linux_drm_syncobj_surface_v1 *surface, struct wlr_drm_syncobj_timeline *timeline, uint64_t point) { + wlr_trace("linux_drm_syncobj_v1_commit (handle=%"PRIu32" point=%"PRIu64")", + timeline->handle, point); + uint32_t flags = DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE; bool already_materialized = false; @@ -475,6 +479,9 @@ struct release_signaller { static void release_signaller_handle_buffer_release(struct wl_listener *listener, void *data) { struct release_signaller *signaller = wl_container_of(listener, signaller, buffer_release); + wlr_trace("linux_drm_syncobj_v1_release (handle=%"PRIu32" point=%"PRIu64")", + signaller->timeline->handle, signaller->point); + if (drmSyncobjTimelineSignal(signaller->timeline->drm_fd, &signaller->timeline->handle, &signaller->point, 1) != 0) { wlr_log(WLR_ERROR, "drmSyncobjTimelineSignal() failed"); diff --git a/util/meson.build b/util/meson.build index 6aad13386..6b28c40c6 100644 --- a/util/meson.build +++ b/util/meson.build @@ -13,6 +13,7 @@ wlr_files += files( 'shm.c', 'time.c', 'token.c', + 'trace.c', 'transform.c', 'utf8.c', 'version.c', diff --git a/util/trace.c b/util/trace.c new file mode 100644 index 000000000..babbda352 --- /dev/null +++ b/util/trace.c @@ -0,0 +1,58 @@ +#include +#include +#include "util/trace.h" + +static bool trace_initialized = false; +static FILE *trace_file = NULL; +static uint32_t prev_ctx = 0; + +void wlr_vtrace(const char *fmt, va_list args) { + if (!trace_initialized) { + trace_initialized = true; + trace_file = fopen("/sys/kernel/tracing/trace_marker", "w"); + if (trace_file != NULL) { + wlr_log(WLR_INFO, "Kernel tracing is enabled"); + } + } + + if (trace_file == NULL) { + return; + } + + vfprintf(trace_file, fmt, args); + fprintf(trace_file, "\n"); + fflush(trace_file); +} + +void wlr_trace(const char *fmt, ...) { + va_list args; + va_start(args, fmt); + wlr_vtrace(fmt, args); + va_end(args); +} + +void wlr_trace_begin_ctx(struct wlr_trace_ctx *ctx, const char *fmt, ...) { + *ctx = (struct wlr_trace_ctx){ + .seq = prev_ctx++, + }; + + static char new_fmt[512]; + snprintf(new_fmt, sizeof(new_fmt), "%s (begin_ctx=%"PRIu32")", fmt, ctx->seq); + + va_list args; + va_start(args, fmt); + wlr_vtrace(new_fmt, args); + va_end(args); +} + +void wlr_trace_end_ctx(struct wlr_trace_ctx *ctx, const char *fmt, ...) { + static char new_fmt[512]; + snprintf(new_fmt, sizeof(new_fmt), "%s (end_ctx=%"PRIu32")", fmt, ctx->seq); + + va_list args; + va_start(args, fmt); + wlr_vtrace(new_fmt, args); + va_end(args); + + ctx->seq = 0; +}