diff --git a/lib/Makefile.sources b/lib/Makefile.sources index 09aedb4035c21039573a6be3127d123d591ff7e5..00374c97b5018b8cca34557a839bdf542b91d856 100644 --- a/lib/Makefile.sources +++ b/lib/Makefile.sources @@ -64,6 +64,8 @@ lib_source_list = \ igt_sysfs.h \ igt_sysrq.c \ igt_sysrq.h \ + igt_thread.c \ + igt_thread.h \ igt_x86.h \ igt_x86.c \ igt_vec.c \ diff --git a/lib/igt_core.c b/lib/igt_core.c index cbcc3f4df4a173a86abc111aeb778cd9c683f99b..c95295c74bf6a701ac45c23a7742be5e7ea62d40 100644 --- a/lib/igt_core.c +++ b/lib/igt_core.c @@ -72,6 +72,7 @@ #include "igt_rc.h" #include "igt_list.h" #include "igt_device_scan.h" +#include "igt_thread.h" #define UNW_LOCAL_ONLY #include <libunwind.h> @@ -2687,6 +2688,12 @@ void igt_log(const char *domain, enum igt_log_level level, const char *format, . va_end(args); } +static pthread_key_t __vlog_line_continuation; + +igt_constructor { + pthread_key_create(&__vlog_line_continuation, NULL); +} + /** * igt_vlog: * @domain: the log domain, or NULL for no domain @@ -2705,6 +2712,7 @@ void igt_vlog(const char *domain, enum igt_log_level level, const char *format, { FILE *file; char *line, *formatted_line; + char *thread_id; const char *program_name; const char *igt_log_level_str[] = { "DEBUG", @@ -2713,7 +2721,8 @@ void igt_vlog(const char *domain, enum igt_log_level level, const char *format, "CRITICAL", "NONE" }; - static bool line_continuation = false; + + static pthread_mutex_t print_mutex = PTHREAD_MUTEX_INITIALIZER; assert(format); @@ -2723,23 +2732,37 @@ void igt_vlog(const char *domain, enum igt_log_level level, const char *format, program_name = command_str; #endif + + if (igt_thread_is_main()) { + thread_id = strdup(""); + } else { + if (asprintf(&thread_id, "[thread:%d] ", gettid()) == -1) + thread_id = NULL; + } + + if (!thread_id) + goto out; + if (list_subtests && level <= IGT_LOG_WARN) return; if (vasprintf(&line, format, args) == -1) return; - if (line_continuation) { + if (pthread_getspecific(__vlog_line_continuation)) { formatted_line = strdup(line); if (!formatted_line) goto out; - } else if (asprintf(&formatted_line, "(%s:%d) %s%s%s: %s", program_name, - getpid(), (domain) ? domain : "", (domain) ? "-" : "", + } else if (asprintf(&formatted_line, "(%s:%d) %s%s%s%s: %s", program_name, + getpid(), thread_id, (domain) ? domain : "", (domain) ? "-" : "", igt_log_level_str[level], line) == -1) { goto out; } - line_continuation = line[strlen(line) - 1] != '\n'; + if (line[strlen(line) - 1] == '\n') + pthread_setspecific(__vlog_line_continuation, (void*) false); + else + pthread_setspecific(__vlog_line_continuation, (void*) true); /* append log buffer */ _igt_log_buffer_append(formatted_line); @@ -2758,6 +2781,8 @@ void igt_vlog(const char *domain, enum igt_log_level level, const char *format, goto out; } + pthread_mutex_lock(&print_mutex); + /* use stderr for warning messages and above */ if (level >= IGT_LOG_WARN) { file = stderr; @@ -2768,13 +2793,18 @@ void igt_vlog(const char *domain, enum igt_log_level level, const char *format, /* prepend all except information messages with process, domain and log * level information */ - if (level != IGT_LOG_INFO) + if (level != IGT_LOG_INFO) { fwrite(formatted_line, sizeof(char), strlen(formatted_line), file); - else + } else { + fwrite(thread_id, sizeof(char), strlen(thread_id), file); fwrite(line, sizeof(char), strlen(line), file); + } + + pthread_mutex_unlock(&print_mutex); out: + free(thread_id); free(line); } diff --git a/lib/igt_thread.c b/lib/igt_thread.c new file mode 100644 index 0000000000000000000000000000000000000000..deab62257c3b3861aec2b7468ebd5fbdb8f8afc2 --- /dev/null +++ b/lib/igt_thread.c @@ -0,0 +1,39 @@ +/* + * Copyright © 2020 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include <pthread.h> + +#include "igt_core.h" +#include "igt_thread.h" + +static pthread_key_t __igt_is_main_thread; + +bool igt_thread_is_main(void) +{ + return pthread_getspecific(__igt_is_main_thread) != NULL; +} + +igt_constructor { + pthread_key_create(&__igt_is_main_thread, NULL); + pthread_setspecific(__igt_is_main_thread, (void*) 0x1); +} diff --git a/lib/igt_thread.h b/lib/igt_thread.h new file mode 100644 index 0000000000000000000000000000000000000000..b16f803f001c4d1fbb6e9c9e3b65d92c46139811 --- /dev/null +++ b/lib/igt_thread.h @@ -0,0 +1,24 @@ +/* + * Copyright © 2020 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +bool igt_thread_is_main(void); diff --git a/lib/meson.build b/lib/meson.build index 6cf786639e1d1cd0efe4cc6fbaa25568e10d3276..6c71ae3d819da80a53c2bf47df5158ab183a09f8 100644 --- a/lib/meson.build +++ b/lib/meson.build @@ -26,6 +26,7 @@ lib_sources = [ 'igt_syncobj.c', 'igt_sysfs.c', 'igt_sysrq.c', + 'igt_thread.c', 'igt_vec.c', 'igt_vgem.c', 'igt_x86.c',