[Intel-gfx] [PATCH i-g-t] Add dmesg capture and dumping to tests and a test for it.

Thomas Wood thomas.wood at intel.com
Wed Nov 18 09:41:45 PST 2015


On 18 November 2015 at 15:44, Daniel Vetter <daniel at ffwll.ch> wrote:
> On Mon, Nov 16, 2015 at 03:22:23PM +0200, Joonas Lahtinen wrote:
>> Cc: Thomas Wood <thomas.wood at intel.com>
>> Cc: Chris Wilson <chris at chris-wilson.co.uk>
>> Cc: Damien Lespiau <damien.lespiau at intel.com>
>> Signed-off-by: Joonas Lahtinen <joonas.lahtinen at linux.intel.com>
>
> Given that we have all that in piglit already the commit message is a bit
> thin on justification. Why do we need this in igt too? How does this
> interact with the piglit dmesg capture?

There are a few tests that rely on checking dmesg to determine if the
test failed (such as gem_hangcheck_forcewake and kms_flip_event_leak).
Although not implemented in this patch, it might be useful to use this
feature to actually report a failure in those cases.


>
>> ---
>>  lib/igt_core.c         | 113 ++++++++++++++++++++++++++++++++++++++++++++++---
>>  tests/Makefile.sources |   1 +
>>  tests/igt_capture.c    |  93 ++++++++++++++++++++++++++++++++++++++++
>>  3 files changed, 200 insertions(+), 7 deletions(-)
>>  create mode 100644 tests/igt_capture.c
>>
>> diff --git a/lib/igt_core.c b/lib/igt_core.c
>> index 04a0ab2..e73175a 100644
>> --- a/lib/igt_core.c
>> +++ b/lib/igt_core.c
>> @@ -211,6 +211,8 @@
>>   * "--help" command line option.
>>   */
>>
>> +#define IGT_KMSG_CAPTURE_DUMP_BUF_SIZE               4096
>> +
>>  static unsigned int exit_handler_count;
>>  const char *igt_interactive_debug;
>>
>> @@ -247,6 +249,10 @@ enum {
>>  static int igt_exitcode = IGT_EXIT_SUCCESS;
>>  static const char *command_str;
>>
>> +static int igt_kmsg_capture_fd;
>> +static char* igt_kmsg_capture_dump_buf;
>> +static pthread_mutex_t kmsg_mutex = PTHREAD_MUTEX_INITIALIZER;
>> +
>>  static char* igt_log_domain_filter;
>>  static struct {
>>       char *entries[256];
>> @@ -312,6 +318,71 @@ static void _igt_log_buffer_dump(void)
>>       pthread_mutex_unlock(&log_buffer_mutex);
>>  }
>>
>> +static void _igt_kmsg_capture_reset(void)
>> +{
>> +     if (igt_kmsg_capture_fd == -1)
>> +             return;
>> +
>> +     pthread_mutex_lock(&kmsg_mutex);
>> +
>> +     lseek(igt_kmsg_capture_fd, 0, SEEK_END);
>> +
>> +     pthread_mutex_unlock(&kmsg_mutex);
>> +}
>> +
>> +static void _igt_kmsg_capture_dump(void)
>> +{
>> +     size_t nbytes;
>> +     int nlines;
>> +     char *p;
>> +     char *p0;
>> +     int c;
>> +
>> +     if (igt_kmsg_capture_fd == -1 ||
>> +         igt_kmsg_capture_dump_buf == NULL)
>> +             return;
>> +
>> +     pthread_mutex_lock(&kmsg_mutex);
>> +
>> +
>> +     nlines = 0;
>> +     do {
>> +             errno = 0;
>> +             nbytes = read(igt_kmsg_capture_fd,
>> +                           igt_kmsg_capture_dump_buf,
>> +                           IGT_KMSG_CAPTURE_DUMP_BUF_SIZE);
>> +
>> +             if (nbytes == -1)
>> +                     continue;
>> +
>> +             if (!nlines)
>> +                     fprintf(stderr, "**** KMSG ****\n");
>> +
>> +             p = p0 = strchr(igt_kmsg_capture_dump_buf, ';') + 1;
>> +             while (p - p0 < nbytes) {
>> +                     if (*p != '\\') {
>> +                             fputc(*p++, stderr);
>> +                             continue;
>> +                     }
>> +                     sscanf(p, "\\x%x", &c);
>> +                     fputc(c, stderr);
>> +                     p += 4;
>> +             }
>> +             //fputs(strchr(igt_kmsg_capture_dump_buf, ';') + 1, stderr);
>> +             nlines++;
>> +     } while(errno == 0);
>> +
>> +     if (nlines)
>> +             fprintf(stderr, "****  END  ****\n");
>> +     else
>> +             fprintf(stderr, "No kmsg.\n");
>> +
>> +     if (errno != EAGAIN)
>> +             fprintf(stderr, "Incomplete kmsg.\n");
>> +
>> +     pthread_mutex_unlock(&kmsg_mutex);
>> +}
>> +
>>  __attribute__((format(printf, 1, 2)))
>>  static void kmsg(const char *format, ...)
>>  #define KERN_EMER    "<0>"
>> @@ -330,11 +401,15 @@ static void kmsg(const char *format, ...)
>>       if (file == NULL)
>>               return;
>>
>> +     pthread_mutex_lock(&kmsg_mutex);
>> +
>>       va_start(ap, format);
>>       vfprintf(file, format, ap);
>>       va_end(ap);
>>
>>       fclose(file);
>> +
>> +     pthread_mutex_unlock(&kmsg_mutex);
>>  }
>>
>>  static void gettime(struct timespec *ts)
>> @@ -527,6 +602,15 @@ static int common_init(int *argc, char **argv,
>>       int ret = 0;
>>       const char *env;
>>
>> +     igt_kmsg_capture_fd = open("/dev/kmsg", O_RDWR | O_NONBLOCK);
>> +     if (igt_kmsg_capture_fd != -1) {
>> +             igt_kmsg_capture_dump_buf =
>> +                     malloc(IGT_KMSG_CAPTURE_DUMP_BUF_SIZE);
>> +             if(igt_kmsg_capture_dump_buf == NULL)
>> +                     igt_warn("Unable to allocate memory, "
>> +                              "will not dump kmsg.\n");
>> +     }
>> +
>>       if (!isatty(STDOUT_FILENO) || getenv("IGT_PLAIN_OUTPUT"))
>>               __igt_plain_output = true;
>>
>> @@ -796,6 +880,7 @@ bool __igt_run_subtest(const char *subtest_name)
>>       igt_debug("Starting subtest: %s\n", subtest_name);
>>
>>       _igt_log_buffer_reset();
>> +     _igt_kmsg_capture_reset();
>>
>>       gettime(&subtest_time);
>>       return (in_subtest = subtest_name);
>> @@ -972,6 +1057,7 @@ void igt_fail(int exitcode)
>>               exit(exitcode);
>>
>>       _igt_log_buffer_dump();
>> +     _igt_kmsg_capture_dump();
>>
>>       if (in_subtest) {
>>               if (exitcode == IGT_EXIT_TIMEOUT)
>> @@ -1072,16 +1158,21 @@ void __igt_fail_assert(const char *domain, const char *file, const int line,
>>   */
>>  void igt_exit(void)
>>  {
>> +     int status = IGT_EXIT_SUCCESS;
>> +
>>       igt_exit_called = true;
>>
>>       if (run_single_subtest && !run_single_subtest_found) {
>>               igt_warn("Unknown subtest: %s\n", run_single_subtest);
>> -             exit(IGT_EXIT_INVALID);
>> +             status = IGT_EXIT_INVALID;
>> +             goto do_exit;
>>       }
>>
>>
>> -     if (igt_only_list_subtests())
>> -             exit(IGT_EXIT_SUCCESS);
>> +     if (igt_only_list_subtests()) {
>> +             status = IGT_EXIT_SUCCESS;
>> +             goto do_exit;
>> +     }
>>
>>       kmsg(KERN_INFO "%s: exiting, ret=%d\n", command_str, igt_exitcode);
>>       igt_debug("Exiting with status code %d\n", igt_exitcode);
>> @@ -1111,18 +1202,26 @@ void igt_exit(void)
>>
>>
>>               printf("%s (%.3fs)\n", result, elapsed);
>> -             exit(igt_exitcode);
>> +             status = igt_exitcode;
>> +             goto do_exit;
>>       }
>>
>>       /* Calling this without calling one of the above is a failure */
>>       assert(skipped_one || succeeded_one || failed_one);
>>
>>       if (failed_one)
>> -             exit(igt_exitcode);
>> +             status = igt_exitcode;
>>       else if (succeeded_one)
>> -             exit(IGT_EXIT_SUCCESS);
>> +             status = IGT_EXIT_SUCCESS;
>>       else
>> -             exit(IGT_EXIT_SKIP);
>> +             status = IGT_EXIT_SKIP;
>> +do_exit:
>> +     if (igt_kmsg_capture_fd != -1)
>> +             close(igt_kmsg_capture_fd);
>> +     if (igt_kmsg_capture_dump_buf != NULL)
>> +             free(igt_kmsg_capture_dump_buf);
>> +
>> +     exit(status);
>>  }
>>
>>  /* fork support code */
>> diff --git a/tests/Makefile.sources b/tests/Makefile.sources
>> index 8fb2de8..25f0c4a 100644
>> --- a/tests/Makefile.sources
>> +++ b/tests/Makefile.sources
>> @@ -62,6 +62,7 @@ TESTS_progs_M = \
>>       gem_tiled_partial_pwrite_pread \
>>       gem_userptr_blits \
>>       gem_write_read_ring_switch \
>> +     igt_capture \
>>       kms_addfb_basic \
>>       kms_atomic \
>>       kms_cursor_crc \
>> diff --git a/tests/igt_capture.c b/tests/igt_capture.c
>> new file mode 100644
>> index 0000000..fd008d0
>> --- /dev/null
>> +++ b/tests/igt_capture.c
>> @@ -0,0 +1,93 @@
>> +/*
>> + * Copyright © 2015 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.
>> + *
>> + * Authors:
>> + *    Joonas Lahtinen <joonas.lahtinen at linux.intel.com>
>> + *
>> + */
>> +
>> +#include "igt.h"
>> +#include <unistd.h>
>> +#include <stdlib.h>
>> +#include <stdio.h>
>> +#include <string.h>
>> +#include <fcntl.h>
>> +#include <inttypes.h>
>> +#include <errno.h>
>> +#include <sys/stat.h>
>> +#include <sys/ioctl.h>
>> +
>> +static FILE* kmsg;
>> +
>> +static void
>> +test_kmsg(void)
>> +{
>> +     fputs("TEST (KMSG)\n", kmsg);
>> +     fflush(kmsg);
>> +     igt_fail(IGT_EXIT_FAILURE);
>> +}
>> +
>> +static void
>> +test_warn(void)
>> +{
>> +     igt_warn("TEST (WARN)\n");
>> +     igt_fail(IGT_EXIT_FAILURE);
>> +}
>> +
>> +static void
>> +test_debug(void)
>> +{
>> +     igt_debug("TEST (DEBUG)\n");
>> +     igt_fail(IGT_EXIT_FAILURE);
>> +}
>> +
>> +static void
>> +test_combined(void)
>> +{
>> +     igt_warn("TEST #1 (WARN)\n");
>> +     fputs("TEST #1\n", kmsg);
>> +     igt_warn("TEST #2 (WARN)\n");
>> +     fputs("TEST #2\n", kmsg);
>> +     fflush(kmsg);
>> +     igt_fail(IGT_EXIT_FAILURE);
>> +}
>> +
>> +igt_main
>> +{
>> +     igt_fixture {
>> +             kmsg = fopen("/dev/kmsg", "w");
>> +             igt_require(kmsg != NULL);
>> +     }
>> +
>> +     igt_subtest("kmsg")
>> +             test_kmsg();
>> +     igt_subtest("warn")
>> +             test_warn();
>> +     igt_subtest("debug")
>> +             test_debug();
>> +     igt_subtest("combined")
>> +             test_combined();
>> +
>> +     igt_fixture {
>> +             fclose(kmsg);
>> +     }
>> +}
>> --
>> 2.4.3
>>
>> _______________________________________________
>> Intel-gfx mailing list
>> Intel-gfx at lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>
> --
> Daniel Vetter
> Software Engineer, Intel Corporation
> http://blog.ffwll.ch


More information about the Intel-gfx mailing list