all repos — tint2 @ 6605a1c3c286d0eec6f8a3971931fc58cccb3c36

fork of the tint2 desktop panel for my custom setup - only minimized windows across all desktops for the taskbar

Tracing support
o9000 mrovi9000@gmail.com
commit

6605a1c3c286d0eec6f8a3971931fc58cccb3c36

parent

0c754affd9be716a40215cbefd14dd5fa4d1c72a

M CMakeLists.txtCMakeLists.txt

@@ -6,6 +6,7 @@ option( ENABLE_TINT2CONF "Enable tint2conf build, a GTK+2 theme configurator for tint2" ON )

option( ENABLE_EXTRA_THEMES "Install additional tint2 themes" ON ) option( ENABLE_RSVG "Rsvg support (launcher only)" ON ) option( ENABLE_SN "Startup notification support" ON ) +option( ENABLE_TRACING "Build tint2 with tracing instrumentation" OFF ) option( ENABLE_ASAN "Build tint2 with AddressSanitizer" OFF ) option( ENABLE_BACKTRACE "Dump a backtrace in case of fatal errors (e.g. X11 I/O error)" OFF ) option( ENABLE_BACKTRACE_ON_SIGNAL "Dump a backtrace also when receiving signals such as SIGSEGV" OFF )

@@ -119,6 +120,7 @@ src/server.c

src/main.c src/init.c src/signals.c + src/tracing.c src/mouse_actions.c src/drag_and_drop.c src/clock/clock.c

@@ -215,13 +217,22 @@ add_dependencies( tint2conf version )

endif( ENABLE_TINT2CONF ) if( ENABLE_ASAN ) - SET(ASAN_C_FLAGS " -O0 -g3 -gdwarf-2 -fsanitize=address -fno-common -fno-omit-frame-pointer -rdynamic -Wshadow") - SET(ASAN_L_FLAGS " -O0 -g3 -gdwarf-2 -fsanitize=address -fno-common -fno-omit-frame-pointer -rdynamic -fuse-ld=gold ") + SET(ASAN_C_FLAGS " -O0 -g3 -fsanitize=address -fno-common -fno-omit-frame-pointer -rdynamic -Wshadow") + SET(ASAN_L_FLAGS " -O0 -g3 -fsanitize=address -fno-common -fno-omit-frame-pointer -rdynamic -fuse-ld=gold ") else() SET(ASAN_C_FLAGS "") SET(ASAN_L_FLAGS "") endif() +if( ENABLE_TRACING ) + add_definitions( -DHAVE_TRACING ) + SET(TRACING_C_FLAGS " -finstrument-functions -finstrument-functions-exclude-file-list=tracing.c -finstrument-functions-exclude-function-list=get_time,gettime -O0 -g3 -fno-common -fno-omit-frame-pointer -rdynamic") + SET(TRACING_L_FLAGS " -O0 -g3 -fno-common -fno-omit-frame-pointer -rdynamic") +else() + SET(TRACING_C_FLAGS "") + SET(TRACING_L_FLAGS "") +endif() + add_custom_target( version ALL "${PROJECT_SOURCE_DIR}/get_version.sh" -- "\"${PROJECT_SOURCE_DIR}/\"" ) link_directories( ${X11_LIBRARY_DIRS}

@@ -256,8 +267,8 @@

target_link_libraries( tint2 m ) add_dependencies( tint2 version ) -set_target_properties( tint2 PROPERTIES COMPILE_FLAGS "-Wall -Wpointer-arith -fno-strict-aliasing -pthread -std=c99 ${ASAN_C_FLAGS}" ) -set_target_properties( tint2 PROPERTIES LINK_FLAGS "-pthread -fno-strict-aliasing ${ASAN_L_FLAGS} ${BACKTRACE_L_FLAGS}" ) +set_target_properties( tint2 PROPERTIES COMPILE_FLAGS "-Wall -Wpointer-arith -fno-strict-aliasing -pthread -std=c99 ${ASAN_C_FLAGS} ${TRACING_C_FLAGS}" ) +set_target_properties( tint2 PROPERTIES LINK_FLAGS "-pthread -fno-strict-aliasing ${ASAN_L_FLAGS} ${BACKTRACE_L_FLAGS} ${TRACING_L_FLAGS}" ) install( TARGETS tint2 DESTINATION bin ) install( FILES tint2.svg DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/scalable/apps )
M src/init.csrc/init.c

@@ -12,6 +12,7 @@ #include "panel.h"

#include "server.h" #include "signals.h" #include "tooltip.h" +#include "tracing.h" #include "uevent.h" #include "version.h"

@@ -83,8 +84,13 @@ debug_geometry = getenv("DEBUG_GEOMETRY") != NULL;

debug_gradients = getenv("DEBUG_GRADIENTS") != NULL; debug_fps = getenv("DEBUG_FPS") != NULL; debug_frames = getenv("DEBUG_FRAMES") != NULL; - if (debug_fps) + if (debug_fps) { init_fps_distribution(); + char *s = getenv("TRACING_FPS_THRESHOLD"); + if (!s || sscanf(s, "%lf", &tracing_fps_threshold) != 1) { + tracing_fps_threshold = 60; + } + } } static timeout *detect_compositor_timer = NULL;

@@ -269,4 +275,8 @@ }

uevent_cleanup(); cleanup_fps_distribution(); + +#ifdef HAVE_TRACING + cleanup_tracing(); +#endif }
M src/main.csrc/main.c

@@ -57,6 +57,7 @@ #include "task.h"

#include "taskbar.h" #include "tooltip.h" #include "timer.h" +#include "tracing.h" #include "uevent.h" #include "version.h" #include "window.h"

@@ -69,6 +70,7 @@

gboolean debug_fps = FALSE; gboolean debug_frames = FALSE; static int frame = 0; +double tracing_fps_threshold = 60; static double ts_event_read; static double ts_event_processed; static double ts_render_finished;

@@ -711,6 +713,12 @@ fps_samples,

proc_ratio * 100, render_ratio * 100, flush_ratio * 100); +#ifdef HAVE_TRACING + stop_tracing(); + if (fps <= tracing_fps_threshold) { + print_tracing_events(); + } +#endif } if (debug_frames) { for (int i = 0; i < num_panels; i++) {

@@ -741,6 +749,9 @@

// Wait for an event and handle it ts_event_read = 0; if (XPending(server.display) > 0 || select(max_fd + 1, &fd_set, 0, 0, get_next_timeout()) >= 0) { +#ifdef HAVE_TRACING + start_tracing((void*)run_tint2_event_loop); +#endif uevent_handler(); handle_sigchld_events(); handle_execp_events();
M src/panel.hsrc/panel.h

@@ -92,6 +92,7 @@ extern XSettingsClient *xsettings_client;

extern gboolean startup_notifications; extern gboolean debug_geometry; extern gboolean debug_fps; +extern double tracing_fps_threshold; extern gboolean debug_frames; typedef struct Panel {
M src/server.csrc/server.c

@@ -23,6 +23,7 @@ #include <X11/extensions/Xrender.h>

#include <X11/extensions/Xrandr.h> #include <stdio.h> +#include <fcntl.h> #include <stdlib.h> #include <string.h> #include <unistd.h>
A src/tracing.c

@@ -0,0 +1,164 @@

+#include "timer.h" + +#ifdef HAVE_TRACING + +#ifdef ENABLE_EXECINFO +#include <execinfo.h> +#endif +#include <glib.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define GREEN "\033[1;32m" +#define YELLOW "\033[1;33m" +#define RED "\033[1;31m" +#define BLUE "\033[1;34m" +#define RESET "\033[0m" + +static GList *tracing_events = NULL; +static sig_atomic_t tracing = FALSE; + +typedef struct TracingEvent { + void *address; + void *caller; + double time; + gboolean enter; +} TracingEvent; + +void __attribute__ ((constructor)) init_tracing() +{ + tracing_events = NULL; + tracing = FALSE; +} + +void cleanup_tracing() +{ + g_list_free_full(tracing_events, free); + tracing_events = NULL; + tracing = FALSE; +} + +char *addr2name(void *func) +{ +#ifdef ENABLE_EXECINFO + void *array[1]; + array[0] = func; + char **strings = backtrace_symbols(array, 1); + char *result = strdup(strings[0] ? strings[0] : "??"); + free(strings); + return result; +#else + char *result = (char*) calloc(32, 1); + sprintf(result, "%p", func); + return result; +#endif +} + +void add_tracing_event(void *func, void *caller, gboolean enter) +{ + TracingEvent *entry = (TracingEvent *)calloc(sizeof(TracingEvent), 1); + entry->address = func; + entry->caller = caller; + entry->time = get_time(); + entry->enter = enter; + tracing_events = g_list_append(tracing_events, entry); +} + +void start_tracing(void *root) +{ + if (tracing_events) + cleanup_tracing(); + add_tracing_event(root, NULL, TRUE); + tracing = TRUE; +} + +void stop_tracing() +{ + tracing = FALSE; +} + +void __cyg_profile_func_enter(void *func, void *caller) +{ + if (tracing) + add_tracing_event(func, caller, TRUE); +} + +void __cyg_profile_func_exit(void *func, void *caller) +{ + if (tracing) + add_tracing_event(func, caller, FALSE); +} + +void print_tracing_events() +{ + GList *stack = NULL; + int depth = 0; + double now = get_time(); + for (GList *i = tracing_events; i; i = i->next) { + TracingEvent *e = (TracingEvent *)i->data; + if (e->enter) { + // Push a new function on the stack + for (int d = 0; d < depth; d++) + fprintf(stderr, " "); + char *name = addr2name(e->address); + char *caller = addr2name(e->caller); + fprintf(stderr, + "%s called from %s\n", + name, + caller); + stack = g_list_append(stack, e); + depth++; + } else { + // Pop a function from the stack, if matching, and print + if (stack) { + TracingEvent *old = (TracingEvent *)g_list_last(stack)->data; + if (old->address == e->address) { + depth--; + for (int d = 0; d < depth; d++) + fprintf(stderr, " "); + char *name = addr2name(e->address); + double duration = (e->time - old->time) * 1.0e3; + fprintf(stderr, + "-- %s exited after %.1f ms", + name, + duration); + if (duration >= 1.0) { + fprintf(stderr, YELLOW " "); + for (int d = 0; d < duration; d++) { + fprintf(stderr, "#"); + } + fprintf(stderr, RESET); + } + fprintf(stderr, "\n"); + free(name); + stack = g_list_delete_link(stack, g_list_last(stack)); + } + } + } + } + while (stack) { + TracingEvent *old = (TracingEvent *)g_list_last(stack)->data; + depth--; + for (int d = 0; d < depth; d++) + fprintf(stderr, " "); + char *name = addr2name(old->address); + double duration = (now - old->time) * 1.0e3; + fprintf(stderr, + "-- %s exited after %.1f ms", + name, + duration); + if (duration >= 1.0) { + fprintf(stderr, YELLOW " "); + for (int d = 0; d < duration; d++) { + fprintf(stderr, "#"); + } + fprintf(stderr, RESET); + } + fprintf(stderr, "\n"); + free(name); + stack = g_list_delete_link(stack, g_list_last(stack)); + } +} + +#endif
A src/tracing.h

@@ -0,0 +1,15 @@

+#ifndef TRACING_H +#define TRACING_H + +#ifdef HAVE_TRACING + +void init_tracing(); +void cleanup_tracing(); + +void start_tracing(void *root); +void stop_tracing(); +void print_tracing_events(); + +#endif + +#endif
M tint2.configtint2.config

@@ -4,3 +4,5 @@ #define HAVE_SN 1

#define ENABLE_BATTERY 1 #define ENABLE_UEVENT 1 #define GETTEXT_PACKAGE +#define HAVE_TRACING +#define ENABLE_EXECINFO
M tint2.filestint2.files

@@ -235,3 +235,5 @@ src/init.h

src/init.c src/signals.c src/signals.h +src/tracing.c +src/tracing.h