userspace/kp_reader.c - ktap

Functions defined

Macros defined

Source code

  1. /*
  2. * reader.c - ring buffer reader in userspace
  3. *
  4. * This file is part of ktap by Jovi Zhangwei.
  5. *
  6. * Copyright (C) 2012-2013 Jovi Zhangwei <jovi.zhangwei@gmail.com>.
  7. *
  8. * ktap is free software; you can redistribute it and/or modify it
  9. * under the terms and conditions of the GNU General Public License,
  10. * version 2, as published by the Free Software Foundation.
  11. *
  12. * ktap is distributed in the hope it will be useful, but WITHOUT
  13. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14. * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  15. * more details.
  16. *
  17. * You should have received a copy of the GNU General Public License along with
  18. * this program; if not, write to the Free Software Foundation, Inc.,
  19. * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
  20. */

  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <unistd.h>
  25. #include <sys/mman.h>
  26. #include <sys/stat.h>
  27. #include <sys/poll.h>
  28. #include <sys/signal.h>
  29. #include <fcntl.h>
  30. #include <pthread.h>

  31. #define MAX_BUFLEN  131072
  32. #define PATH_MAX 128

  33. #define handle_error(str) do { perror(str); exit(-1); } while(0)

  34. void sigfunc(int signo)
  35. {
  36.     /* should not not reach here */
  37. }

  38. static void block_sigint()
  39. {
  40.     sigset_t mask;

  41.     sigemptyset(&mask);
  42.     sigaddset(&mask, SIGINT);

  43.     pthread_sigmask(SIG_BLOCK, &mask, NULL);
  44. }

  45. static void *reader_thread(void *data)
  46. {
  47.     char buf[MAX_BUFLEN];
  48.     char filename[PATH_MAX];
  49.     const char *output = data;
  50.     int failed = 0, fd, out_fd, len;

  51.     block_sigint();

  52.     if (output) {
  53.         out_fd = open(output, O_CREAT | O_WRONLY | O_TRUNC,
  54.                     S_IRUSR|S_IWUSR);
  55.         if (out_fd < 0) {
  56.             fprintf(stderr, "Cannot open output file %s\n", output);
  57.             return NULL;
  58.         }
  59.     } else
  60.         out_fd = 1;

  61.     sprintf(filename, "/sys/kernel/debug/ktap/trace_pipe_%d", getpid());

  62. open_again:
  63.     fd = open(filename, O_RDONLY);
  64.     if (fd < 0) {
  65.         usleep(10000);

  66.         if (failed++ == 10) {
  67.             fprintf(stderr, "Cannot open file %s\n", filename);
  68.             return NULL;
  69.         }
  70.         goto open_again;
  71.     }

  72.     while ((len = read(fd, buf, sizeof(buf))) > 0)
  73.         write(out_fd, buf, len);

  74.     close(fd);
  75.     close(out_fd);

  76.     return NULL;
  77. }

  78. int kp_create_reader(const char *output)
  79. {
  80.     pthread_t reader;

  81.     signal(SIGINT, sigfunc);

  82.     if (pthread_create(&reader, NULL, reader_thread, (void *)output) < 0)
  83.         handle_error("pthread_create reader_thread failed\n");

  84.     return 0;
  85. }