[FFmpeg-devel] [PATCH 1/3] libavutil: prefix log messages with thread name

Martin Carroll martin.carroll at alcatel-lucent.com
Wed Jul 18 17:22:19 CEST 2012


To make it easier to see which thread is doing what, the logger can
now be configured to prefix all log messages with the name of the
calling thread.  The name is printed if the thread was previously
registered with av_log_set_threadname().  To enable this feature,
the variable print_threadname in libavutil/log.c must be set to 1.

Signed-off-by: Martin Carroll <martin.carroll at alcatel-lucent.com>
---
 libavutil/log.c |  104 +++++++++++++++++++++++++++++++++++++++++++++++++------
 libavutil/log.h |   11 ++++++
 2 files changed, 104 insertions(+), 11 deletions(-)

diff --git a/libavutil/log.c b/libavutil/log.c
index 53c756b..bee612f 100644
--- a/libavutil/log.c
+++ b/libavutil/log.c
@@ -30,11 +30,34 @@
 #include <unistd.h>
 #endif
 #include <stdlib.h>
+#include <pthread.h>
 #include "avutil.h"
 #include "log.h"
 
 #define LINE_SZ 1024
 
+#define MAX_THREAD_INFOS 10
+#define MAX_THREAD_NAMELEN 128
+
+/*
+ * we do *not* use thread-specific data to implement this
+ * data structure, because we want the creat*ing* thread to
+ * be able to set the creat*ed* thread's name, and implementing
+ * that functionality is easier with a globally accessed (and
+ * properly locked) table.
+ */
+typedef struct {
+    pthread_t pid;
+    char name[MAX_THREAD_NAMELEN];
+    void *fcn;
+    int instance_num_of_fcn;
+    int sole_instance_of_fcn;
+} Thread_info;
+
+static pthread_rwlock_t thread_info_rwlock = PTHREAD_RWLOCK_INITIALIZER;
+static Thread_info thread_info[MAX_THREAD_INFOS];
+static int num_thread_infos = 0;
+static int print_threadname = 0; /* set to 1 to prefix all log messages with name of thread */
 static int av_log_level = AV_LOG_INFO;
 static int flags;
 
@@ -163,11 +186,53 @@ static int get_category(void *ptr){
     return avc->category + 16;
 }
 
+void av_log_set_threadname(pthread_t pid, const char *name, void *fcn)
+{
+	pthread_rwlock_wrlock(&thread_info_rwlock);
+    if (num_thread_infos < MAX_THREAD_INFOS) {
+        Thread_info *info;
+        int instance_num_of_fcn = 0;
+        int sole_instance_of_fcn = 1;
+        int i;
+
+        for (i = 0; i < num_thread_infos; ++i) {
+            info = &thread_info[i];
+            if (info->fcn == fcn) {
+                info->sole_instance_of_fcn = 0;
+                sole_instance_of_fcn = 0;
+                ++instance_num_of_fcn;
+            }
+        }
+        info = &thread_info[num_thread_infos];
+        info->pid = pid;
+        info->fcn = fcn;
+        info->instance_num_of_fcn = instance_num_of_fcn;
+        info->sole_instance_of_fcn = sole_instance_of_fcn;
+        snprintf(info->name, MAX_THREAD_NAMELEN, "%s", name);
+        info->name[MAX_THREAD_NAMELEN-1] = 0;
+        ++num_thread_infos;
+    }
+	pthread_rwlock_unlock(&thread_info_rwlock);
+}
+
+static Thread_info* lookup_thread_info(void)
+{
+    int i;
+
+    pthread_t pid = pthread_self();
+    for (i = 0; i < num_thread_infos; ++i) {
+        Thread_info* info = &thread_info[i];
+        if (pthread_equal(info->pid, pid))
+            return info;
+    }
+    return NULL;
+}
+
 static void format_line(void *ptr, int level, const char *fmt, va_list vl,
-                        char part[3][LINE_SZ], int part_size, int *print_prefix, int type[2])
+                        char part[5][LINE_SZ], int part_size, int *print_prefix, int type[2])
 {
     AVClass* avc = ptr ? *(AVClass **) ptr : NULL;
-    part[0][0] = part[1][0] = part[2][0] = 0;
+    part[0][0] = part[1][0] = part[2][0] = part[3][0] = part[4][0] = 0;
     if(type) type[0] = type[1] = AV_CLASS_CATEGORY_NA + 16;
     if (*print_prefix && avc) {
         if (avc->parent_log_context_offset) {
@@ -183,18 +248,29 @@ static void format_line(void *ptr, int level, const char *fmt, va_list vl,
                  avc->item_name(ptr), ptr);
         if(type) type[1] = get_category(ptr);
     }
-
-    vsnprintf(part[2], part_size, fmt, vl);
-
-    *print_prefix = strlen(part[2]) && part[2][strlen(part[2]) - 1] == '\n';
+    if (print_threadname) {
+        Thread_info* info;
+
+		pthread_rwlock_rdlock(&thread_info_rwlock);
+        info = lookup_thread_info();
+        if (info) {
+            if (info->sole_instance_of_fcn)
+                snprintf(part[2], part_size, "%s: ", info->name);
+            else
+                snprintf(part[2], part_size, "%s(%d): ", info->name, info->instance_num_of_fcn);
+        }
+		pthread_rwlock_unlock(&thread_info_rwlock);
+    }
+    vsnprintf(part[4], part_size, fmt, vl);
+    *print_prefix = strlen(part[4]) && part[4][strlen(part[4]) - 1] == '\n';
 }
 
 void av_log_format_line(void *ptr, int level, const char *fmt, va_list vl,
                         char *line, int line_size, int *print_prefix)
 {
-    char part[3][LINE_SZ];
+    char part[5][LINE_SZ];
     format_line(ptr, level, fmt, vl, part, sizeof(part[0]), print_prefix, NULL);
-    snprintf(line, line_size, "%s%s%s", part[0], part[1], part[2]);
+    snprintf(line, line_size, "%s%s%s%s%s", part[0], part[1], part[2], part[3], part[4]);
 }
 
 void av_log_default_callback(void* ptr, int level, const char* fmt, va_list vl)
@@ -202,15 +278,16 @@ void av_log_default_callback(void* ptr, int level, const char* fmt, va_list vl)
     static int print_prefix = 1;
     static int count;
     static char prev[LINE_SZ];
-    char part[3][LINE_SZ];
+    char part[5][LINE_SZ];
     char line[LINE_SZ];
     static int is_atty;
     int type[2];
+    int lev;
 
     if (level > av_log_level)
         return;
     format_line(ptr, level, fmt, vl, part, sizeof(part[0]), &print_prefix, type);
-    snprintf(line, sizeof(line), "%s%s%s", part[0], part[1], part[2]);
+    snprintf(line, sizeof(line), "%s%s%s%s%s", part[0], part[1], part[2], part[3], part[4]);
 
 #if HAVE_ISATTY
     if (!is_atty)
@@ -234,7 +311,12 @@ void av_log_default_callback(void* ptr, int level, const char* fmt, va_list vl)
     sanitize(part[1]);
     colored_fputs(type[1], part[1]);
     sanitize(part[2]);
-    colored_fputs(av_clip(level >> 3, 0, 6), part[2]);
+    lev = av_clip(level >> 3, 0, 6);
+    colored_fputs(lev, part[2]);
+    sanitize(part[3]);
+    colored_fputs(lev, part[3]);
+    sanitize(part[4]);
+    colored_fputs(lev, part[4]);
 }
 
 static void (*av_log_callback)(void*, int, const char*, va_list) =
diff --git a/libavutil/log.h b/libavutil/log.h
index ba7315f..da96016 100644
--- a/libavutil/log.h
+++ b/libavutil/log.h
@@ -170,6 +170,17 @@ typedef struct AVClass {
  */
 void av_log(void *avcl, int level, const char *fmt, ...) av_printf_format(3, 4);
 
+/**
+ * If the logger is configured to print thread info (see libavutil/log.c),
+ * then prefix all log messages issued by the given thread with the given
+ * thread name.
+ *
+ * @param pid The thread id.
+ * @param name A descriptive name for the thread.
+ * @param fcn The thread's top-level function.
+ */
+void av_log_set_threadname(pthread_t pid, const char* name, void *fcn);
+
 void av_vlog(void *avcl, int level, const char *fmt, va_list);
 int av_log_get_level(void);
 void av_log_set_level(int);
-- 
1.7.8.6



More information about the ffmpeg-devel mailing list