Merge tag 'v3.14.25' into backport/v3.14.24-ltsi-rc1+v3.14.25/snapshot-merge.wip
[platform/adaptation/renesas_rcar/renesas_kernel.git] / drivers / staging / ktap / userspace / ktapio.c
1 /*
2  * ktapio.c - ring buffer transport 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
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <unistd.h>
26 #include <sys/mman.h>
27 #include <sys/stat.h>
28 #include <sys/poll.h>
29 #include <sys/signal.h>
30 #include <fcntl.h>
31 #include <pthread.h>
32
33 #define MAX_BUFLEN  131072
34 #define PATH_MAX 128
35
36 #define handle_error(str) do { perror(str); exit(-1); } while(0)
37
38 void sigfunc(int signo)
39 {
40         /* should not not reach here */
41 }
42
43 static void block_sigint()
44 {
45         sigset_t mask;
46
47         sigemptyset(&mask);
48         sigaddset(&mask, SIGINT);
49
50         pthread_sigmask(SIG_BLOCK, &mask, NULL);
51 }
52
53 static void *reader_thread(void *data)
54 {
55         char buf[MAX_BUFLEN];
56         char filename[PATH_MAX];
57         const char *output = data;
58         int failed = 0, fd, out_fd, len;
59
60         block_sigint();
61
62         if (output) {
63                 out_fd = open(output, O_CREAT | O_WRONLY | O_TRUNC,
64                                         S_IRUSR|S_IWUSR);
65                 if (out_fd < 0) {
66                         fprintf(stderr, "Cannot open output file %s\n", output);
67                         return NULL;
68                 }
69         } else
70                 out_fd = 2;
71
72         sprintf(filename, "/sys/kernel/debug/ktap/trace_pipe_%d", getpid());
73
74  open_again:
75         fd = open(filename, O_RDONLY);
76         if (fd < 0) {
77                 usleep(10000);
78
79                 if (failed++ == 10) {
80                         fprintf(stderr, "Cannot open file %s\n", filename);
81                         return NULL;
82                 }
83                 goto open_again;
84         }
85
86         while ((len = read(fd, buf, sizeof(buf))) > 0)
87                 write(out_fd, buf, len);
88
89         close(fd);
90         close(out_fd);
91
92         return NULL;
93 }
94
95 int ktapio_create(const char *output)
96 {
97         pthread_t reader;
98
99         signal(SIGINT, sigfunc);
100
101         if (pthread_create(&reader, NULL, reader_thread, (void *)output) < 0)
102                 handle_error("pthread_create reader_thread failed\n");
103
104         return 0;
105 }
106