feat: log continuous debug messages into per-device buffers

Instead of exposing to consumers write streaming log data into a per-device
buffer that gets created on request and destroyed after the buffer has been
written to the log.

Passing a NULL string to the internal continuous log function triggers a write
of the buffer to the log.

BREAKING CHANGE: continuous log function is moved from log header to private
header.
This commit is contained in:
Roman Gilg 2020-02-29 02:04:26 +01:00 committed by Simon Ser
parent 273cf8a432
commit c05f290f95
No known key found for this signature in database
GPG key ID: 0FDE7BE0E88F5E48
7 changed files with 126 additions and 62 deletions

50
alloc.c
View file

@ -581,23 +581,21 @@ static void log_no_reuse(struct liftoff_output *output)
} }
} }
static void log_plane_type_change(uint32_t base, uint32_t cmp) static void log_plane_type_change(struct liftoff_device *device,
uint32_t base, uint32_t cmp)
{ {
switch (base) { switch (base) {
case DRM_PLANE_TYPE_PRIMARY: case DRM_PLANE_TYPE_PRIMARY:
liftoff_log_cnt(LIFTOFF_DEBUG, " <p|"); debug_cnt(device, " <p|");
liftoff_log_cnt(LIFTOFF_DEBUG, debug_cnt(device, cmp == DRM_PLANE_TYPE_OVERLAY ? "o>" : "c>");
cmp == DRM_PLANE_TYPE_OVERLAY ? "o>" : "c>");
break; break;
case DRM_PLANE_TYPE_CURSOR: case DRM_PLANE_TYPE_CURSOR:
liftoff_log_cnt(LIFTOFF_DEBUG, " <c|"); debug_cnt(device, " <c|");
liftoff_log_cnt(LIFTOFF_DEBUG, debug_cnt(device, cmp == DRM_PLANE_TYPE_PRIMARY ? "p>" : "o>");
cmp == DRM_PLANE_TYPE_PRIMARY ? "p>" : "o>");
break; break;
case DRM_PLANE_TYPE_OVERLAY: case DRM_PLANE_TYPE_OVERLAY:
liftoff_log_cnt(LIFTOFF_DEBUG, " <o|"); debug_cnt(device, " <o|");
liftoff_log_cnt(LIFTOFF_DEBUG, debug_cnt(device, cmp == DRM_PLANE_TYPE_PRIMARY ? "p>" : "c>");
cmp == DRM_PLANE_TYPE_PRIMARY ? "p>" : "c>");
break; break;
} }
} }
@ -615,12 +613,13 @@ static void log_planes(struct liftoff_device *device,
return; return;
} }
liftoff_log_cnt(LIFTOFF_DEBUG, "\nAvailable planes"); debug_cnt(device, "Available planes");
if (output) { if (output) {
liftoff_log(LIFTOFF_DEBUG, " (on output %"PRIu32 "):", output->crtc_id); debug_cnt(device, " (on output %"PRIu32 "):", output->crtc_id);
} else { } else {
liftoff_log(LIFTOFF_DEBUG, ":"); debug_cnt(device, ":");
} }
debug_cnt(device, NULL);
liftoff_list_for_each(plane, &device->planes, link) { liftoff_list_for_each(plane, &device->planes, link) {
bool active = false; bool active = false;
@ -653,7 +652,7 @@ static void log_planes(struct liftoff_device *device,
} }
} }
liftoff_log_cnt(LIFTOFF_DEBUG, " Plane %"PRIu32 "%s", plane->id, debug_cnt(device, " Plane %"PRIu32 "%s", plane->id,
active ? ":" : " (inactive):"); active ? ":" : " (inactive):");
max_per_line = active ? 1 : 4; max_per_line = active ? 1 : 4;
@ -663,21 +662,22 @@ static void log_planes(struct liftoff_device *device,
char *name; char *name;
if (++per_line == max_per_line) { if (++per_line == max_per_line) {
liftoff_log_cnt(LIFTOFF_DEBUG, "\n "); debug_cnt(device, NULL);
debug_cnt(device, " ");
per_line = 0; per_line = 0;
} }
drm_prop = drmModeGetProperty(device->drm_fd, drm_prop = drmModeGetProperty(device->drm_fd,
drm_props->props[i]); drm_props->props[i]);
if (drm_prop == NULL) { if (drm_prop == NULL) {
liftoff_log_cnt(LIFTOFF_DEBUG, "ERR!"); debug_cnt(device, "ERR!");
continue; continue;
} }
name = drm_prop->name; name = drm_prop->name;
if (strcmp(name, "type") == 0) { if (strcmp(name, "type") == 0) {
liftoff_log_cnt(LIFTOFF_DEBUG, " %s: %s", name, debug_cnt(device, " %s: %s", name,
value == DRM_PLANE_TYPE_PRIMARY ? "primary" : value == DRM_PLANE_TYPE_PRIMARY ? "primary" :
value == DRM_PLANE_TYPE_CURSOR ? "cursor" : "overlay"); value == DRM_PLANE_TYPE_CURSOR ? "cursor" : "overlay");
continue; continue;
@ -685,16 +685,16 @@ static void log_planes(struct liftoff_device *device,
if (strcmp(name, "CRTC_X") == 0 || strcmp(name, "CRTC_Y") == 0 if (strcmp(name, "CRTC_X") == 0 || strcmp(name, "CRTC_Y") == 0
|| strcmp(name, "IN_FENCE_FD") == 0) { || strcmp(name, "IN_FENCE_FD") == 0) {
liftoff_log_cnt(LIFTOFF_DEBUG, " %s: %"PRIi32, name, (int32_t)value); debug_cnt(device, " %s: %"PRIi32, name, (int32_t)value);
continue; continue;
} }
if (strcmp(name, "SRC_W") == 0 || strcmp(name, "SRC_H") == 0) { if (strcmp(name, "SRC_W") == 0 || strcmp(name, "SRC_H") == 0) {
value = value >> 16; value = value >> 16;
} }
liftoff_log_cnt(LIFTOFF_DEBUG, " %s: %"PRIu64, name, value); debug_cnt(device, " %s: %"PRIu64, name, value);
} }
liftoff_log_cnt(LIFTOFF_DEBUG, "\n"); debug_cnt(device, NULL);
} }
} }
@ -704,7 +704,7 @@ static bool reset_planes(struct liftoff_device *device, drmModeAtomicReq *req)
uint32_t debug_type = DRM_PLANE_TYPE_PRIMARY; uint32_t debug_type = DRM_PLANE_TYPE_PRIMARY;
bool compatible; bool compatible;
liftoff_log_cnt(LIFTOFF_DEBUG, "\nReset planes:"); debug_cnt(device, "\nReset planes:");
liftoff_list_for_each(plane, &device->planes, link) { liftoff_list_for_each(plane, &device->planes, link) {
if (plane->layer != NULL) { if (plane->layer != NULL) {
@ -713,19 +713,21 @@ static bool reset_planes(struct liftoff_device *device, drmModeAtomicReq *req)
if (log_has(LIFTOFF_DEBUG)) { if (log_has(LIFTOFF_DEBUG)) {
if (plane->type != debug_type) { if (plane->type != debug_type) {
log_plane_type_change(debug_type, plane->type); log_plane_type_change(device, debug_type, plane->type);
debug_type = plane->type; debug_type = plane->type;
} }
liftoff_log_cnt(LIFTOFF_DEBUG, " %"PRIu32, plane->id); debug_cnt(device, " %"PRIu32, plane->id);
} }
if (!plane_apply(plane, NULL, req, &compatible)) { if (!plane_apply(plane, NULL, req, &compatible)) {
debug_cnt(device, "... Error resetting: %"PRIu32, plane->id);
debug_cnt(device, NULL);
return false; return false;
} }
assert(compatible); assert(compatible);
} }
liftoff_log(LIFTOFF_DEBUG, "\n"); debug_cnt(device, NULL);
return true; return true;
} }

View file

@ -13,14 +13,14 @@ struct liftoff_device *liftoff_device_create(int drm_fd)
drmModePlaneRes *drm_plane_res; drmModePlaneRes *drm_plane_res;
uint32_t i; uint32_t i;
liftoff_log_cnt(LIFTOFF_DEBUG, "\nCreating device for fd %d. ", drm_fd);
device = calloc(1, sizeof(*device)); device = calloc(1, sizeof(*device));
if (device == NULL) { if (device == NULL) {
liftoff_log_errno(LIFTOFF_ERROR, "calloc"); liftoff_log_errno(LIFTOFF_ERROR, "calloc");
return NULL; return NULL;
} }
liftoff_log(LIFTOFF_DEBUG, "\nCreating device for fd %d. ", drm_fd);
liftoff_list_init(&device->planes); liftoff_list_init(&device->planes);
liftoff_list_init(&device->outputs); liftoff_list_init(&device->outputs);
@ -63,9 +63,9 @@ struct liftoff_device *liftoff_device_create(int drm_fd)
for (i = 0; i < drm_plane_res->count_planes; i++) { for (i = 0; i < drm_plane_res->count_planes; i++) {
if (i < 9 && drm_plane_res->count_planes >= 9) { if (i < 9 && drm_plane_res->count_planes >= 9) {
liftoff_log_cnt(LIFTOFF_DEBUG, " "); debug_cnt(device, " ");
} }
liftoff_log_cnt(LIFTOFF_DEBUG, "[%d] ", i + 1); debug_cnt(device, "[%d] ", i + 1);
if (plane_create(device, drm_plane_res->planes[i]) == NULL) { if (plane_create(device, drm_plane_res->planes[i]) == NULL) {
liftoff_device_destroy(device); liftoff_device_destroy(device);
return NULL; return NULL;
@ -73,8 +73,6 @@ struct liftoff_device *liftoff_device_create(int drm_fd)
} }
drmModeFreePlaneResources(drm_plane_res); drmModeFreePlaneResources(drm_plane_res);
liftoff_log_cnt(LIFTOFF_DEBUG, "\n");
return device; return device;
} }
@ -91,6 +89,7 @@ void liftoff_device_destroy(struct liftoff_device *device)
plane_destroy(plane); plane_destroy(plane);
} }
free(device->crtcs); free(device->crtcs);
free(device->log_buf);
free(device); free(device);
} }

View file

@ -74,7 +74,7 @@ enum liftoff_log_importance {
LIFTOFF_DEBUG, LIFTOFF_DEBUG,
}; };
typedef void (*liftoff_log_func)(enum liftoff_log_importance importance, bool newline, typedef void (*liftoff_log_func)(enum liftoff_log_importance importance,
const char *fmt, va_list args); const char *fmt, va_list args);
void liftoff_log_init(enum liftoff_log_importance verbosity, void liftoff_log_init(enum liftoff_log_importance verbosity,

View file

@ -13,8 +13,9 @@ bool log_has(enum liftoff_log_importance verbosity);
void liftoff_log(enum liftoff_log_importance verbosity, void liftoff_log(enum liftoff_log_importance verbosity,
const char *format, ...) _LIFTOFF_ATTRIB_PRINTF(2, 3); const char *format, ...) _LIFTOFF_ATTRIB_PRINTF(2, 3);
void liftoff_log_cnt(enum liftoff_log_importance verbosity,
const char *format, ...) _LIFTOFF_ATTRIB_PRINTF(2, 3);
void liftoff_log_errno(enum liftoff_log_importance verbosity, const char *msg); void liftoff_log_errno(enum liftoff_log_importance verbosity, const char *msg);
void debug_cnt(struct liftoff_device *device, const char *format, ...)
_LIFTOFF_ATTRIB_PRINTF(2, 3);
#endif #endif

View file

@ -19,6 +19,10 @@ struct liftoff_device {
size_t crtcs_len; size_t crtcs_len;
int page_flip_counter; int page_flip_counter;
char *log_buf;
size_t log_buf_len;
size_t log_buf_index;
}; };
struct liftoff_output { struct liftoff_output {

85
log.c
View file

@ -1,17 +1,17 @@
#include <errno.h> #include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include "log.h" #include "log.h"
#include "private.h"
static enum liftoff_log_importance log_importance = LIFTOFF_ERROR; static enum liftoff_log_importance log_importance = LIFTOFF_ERROR;
static void log_stderr(enum liftoff_log_importance verbosity, bool newline, const char *fmt, static void log_stderr(enum liftoff_log_importance verbosity, const char *fmt,
va_list args) va_list args)
{ {
vfprintf(stderr, fmt, args); vfprintf(stderr, fmt, args);
if (newline) {
fprintf(stderr, "\n"); fprintf(stderr, "\n");
}
} }
static liftoff_log_func log_callback = log_stderr; static liftoff_log_func log_callback = log_stderr;
@ -39,19 +39,7 @@ void liftoff_log(enum liftoff_log_importance verbosity, const char *fmt, ...)
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
log_callback(verbosity, true, fmt, args); log_callback(verbosity, fmt, args);
va_end(args);
}
void liftoff_log_cnt(enum liftoff_log_importance verbosity, const char *fmt, ...)
{
if (!log_has(verbosity)) {
return;
}
va_list args;
va_start(args, fmt);
log_callback(verbosity, false, fmt, args);
va_end(args); va_end(args);
} }
@ -59,3 +47,68 @@ void liftoff_log_errno(enum liftoff_log_importance verbosity, const char *msg)
{ {
liftoff_log(verbosity, "%s: %s", msg, strerror(errno)); liftoff_log(verbosity, "%s: %s", msg, strerror(errno));
} }
void debug_cnt(struct liftoff_device *device, const char *fmt, ...)
{
if (!log_has(LIFTOFF_DEBUG)) {
return;
}
if (fmt == NULL) {
if (device->log_buf == 0) {
return;
}
liftoff_log(LIFTOFF_DEBUG, "%s", device->log_buf);
free(device->log_buf);
device->log_buf = NULL;
device->log_buf_index = 0;
device->log_buf_len = 0;
return;
}
va_list args;
va_start(args, fmt);
if (device->log_buf == NULL) {
device->log_buf = malloc(4096);
if (device->log_buf == NULL) {
liftoff_log_errno(LIFTOFF_ERROR, "malloc");
goto cleanup_out;
}
device->log_buf_len = 4096 / sizeof(char);
}
do {
size_t max_len = device->log_buf_len - device->log_buf_index;
int ret;
ret = vsnprintf(device->log_buf + device->log_buf_index,
max_len, fmt, args);
if (ret < 0) {
goto cleanup_out;
}
if (ret - (int)max_len > 0) {
device->log_buf_index = device->log_buf_len;
device->log_buf_len *= 2;
if (realloc(device->log_buf, device->log_buf_len) == NULL) {
liftoff_log_errno(LIFTOFF_ERROR, "realloc");
goto cleanup_out;
}
} else {
device->log_buf_index += ret;
goto final_out;
}
} while (1);
cleanup_out:
free(device->log_buf);
device->log_buf = NULL;
device->log_buf_index = 0;
device->log_buf_len = 0;
final_out:
va_end(args);
}

27
plane.c
View file

@ -30,7 +30,8 @@ static int guess_plane_zpos_from_type(struct liftoff_device *device,
return 0; return 0;
} }
static void log_plane(struct liftoff_plane *plane) static void log_plane(struct liftoff_device *device,
struct liftoff_plane *plane)
{ {
size_t i; size_t i;
int per_line = 0; int per_line = 0;
@ -39,26 +40,29 @@ static void log_plane(struct liftoff_plane *plane)
return; return;
} }
liftoff_log_cnt(LIFTOFF_DEBUG, " type: "); debug_cnt(device, " type: ");
if (plane->type == DRM_PLANE_TYPE_PRIMARY) { if (plane->type == DRM_PLANE_TYPE_PRIMARY) {
liftoff_log(LIFTOFF_DEBUG, "Primary"); debug_cnt(device, "Primary");
} else if (plane->type == DRM_PLANE_TYPE_CURSOR) { } else if (plane->type == DRM_PLANE_TYPE_CURSOR) {
liftoff_log(LIFTOFF_DEBUG, "Cursor"); debug_cnt(device, "Cursor");
} else { } else {
liftoff_log(LIFTOFF_DEBUG, "Overlay"); debug_cnt(device, "Overlay");
} }
debug_cnt(device, NULL);
liftoff_log(LIFTOFF_DEBUG, " zpos: %"PRIu32, plane->zpos); liftoff_log(LIFTOFF_DEBUG, " zpos: %"PRIu32, plane->zpos);
liftoff_log_cnt(LIFTOFF_DEBUG, " props:"); debug_cnt(device, " props:");
for (i = 0; i < plane->props_len; i++) { for (i = 0; i < plane->props_len; i++) {
if (per_line == 5) { if (per_line == 5) {
liftoff_log_cnt(LIFTOFF_DEBUG, "\n "); debug_cnt(device, NULL);
debug_cnt(device, " ");
per_line = 0; per_line = 0;
} }
liftoff_log_cnt(LIFTOFF_DEBUG, " %s", plane->props[i].name); debug_cnt(device, " %s", plane->props[i].name);
per_line++; per_line++;
} }
liftoff_log_cnt(LIFTOFF_DEBUG, "\n"); debug_cnt(device, NULL);
} }
struct liftoff_plane *plane_create(struct liftoff_device *device, uint32_t id) struct liftoff_plane *plane_create(struct liftoff_device *device, uint32_t id)
@ -72,7 +76,8 @@ struct liftoff_plane *plane_create(struct liftoff_device *device, uint32_t id)
uint64_t value; uint64_t value;
bool has_type = false, has_zpos = false; bool has_type = false, has_zpos = false;
liftoff_log(LIFTOFF_DEBUG, "Plane %"PRIu32, id); debug_cnt(device, "Plane %"PRIu32, id);
debug_cnt(device, NULL);
plane = calloc(1, sizeof(*plane)); plane = calloc(1, sizeof(*plane));
if (plane == NULL) { if (plane == NULL) {
@ -158,7 +163,7 @@ struct liftoff_plane *plane_create(struct liftoff_device *device, uint32_t id)
} }
} }
log_plane(plane); log_plane(device, plane);
return plane; return plane;
} }