939aaace3c7c30272bc70f894a0a1bde97a09157
[lttng-tools.git] / src / common / compat / compat-epoll.c
1 /*
2 * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License, version 2 only,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16 */
17
18 #define _GNU_SOURCE
19 #include <fcntl.h>
20 #include <limits.h>
21 #include <stdlib.h>
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <unistd.h>
25 #include <config.h>
26
27 #include <common/error.h>
28 #include <common/defaults.h>
29
30 #include "poll.h"
31
32 unsigned int poll_max_size;
33
34 /*
35 * Create epoll set and allocate returned events structure.
36 */
37 int compat_epoll_create(struct lttng_poll_event *events, int size, int flags)
38 {
39 int ret;
40
41 if (events == NULL || size <= 0) {
42 goto error;
43 }
44
45 /* Don't bust the limit here */
46 if (size > poll_max_size && poll_max_size != 0) {
47 size = poll_max_size;
48 }
49
50 ret = epoll_create1(flags);
51 if (ret < 0) {
52 /* At this point, every error is fatal */
53 PERROR("epoll_create1");
54 goto error;
55 }
56
57 events->epfd = ret;
58
59 /* This *must* be freed by using lttng_poll_free() */
60 events->events = zmalloc(size * sizeof(struct epoll_event));
61 if (events->events == NULL) {
62 PERROR("zmalloc epoll set");
63 goto error_close;
64 }
65
66 events->events_size = size;
67 events->nb_fd = 0;
68
69 return 0;
70
71 error_close:
72 ret = close(events->epfd);
73 if (ret) {
74 PERROR("close");
75 }
76 error:
77 return -1;
78 }
79
80 /*
81 * Add a fd to the epoll set with requesting events.
82 */
83 int compat_epoll_add(struct lttng_poll_event *events, int fd, uint32_t req_events)
84 {
85 int ret, new_size;
86 struct epoll_event ev, *ptr;
87
88 if (events == NULL || events->events == NULL || fd < 0) {
89 ERR("Bad compat epoll add arguments");
90 goto error;
91 }
92
93 ev.events = req_events;
94 ev.data.fd = fd;
95
96 ret = epoll_ctl(events->epfd, EPOLL_CTL_ADD, fd, &ev);
97 if (ret < 0) {
98 switch (errno) {
99 case EEXIST:
100 /* If exist, it's OK. */
101 goto end;
102 case ENOSPC:
103 case EPERM:
104 /* Print PERROR and goto end not failing. Show must go on. */
105 PERROR("epoll_ctl ADD");
106 goto end;
107 default:
108 PERROR("epoll_ctl ADD fatal");
109 goto error;
110 }
111 }
112
113 events->nb_fd++;
114
115 if (events->nb_fd >= events->events_size) {
116 new_size = 2 * events->events_size;
117 ptr = realloc(events->events, new_size * sizeof(struct epoll_event));
118 if (ptr == NULL) {
119 PERROR("realloc epoll add");
120 goto error;
121 }
122 events->events = ptr;
123 events->events_size = new_size;
124 }
125
126 end:
127 return 0;
128
129 error:
130 return -1;
131 }
132
133 /*
134 * Remove a fd from the epoll set.
135 */
136 int compat_epoll_del(struct lttng_poll_event *events, int fd)
137 {
138 int ret;
139
140 if (events == NULL || fd < 0) {
141 goto error;
142 }
143
144 ret = epoll_ctl(events->epfd, EPOLL_CTL_DEL, fd, NULL);
145 if (ret < 0) {
146 switch (errno) {
147 case ENOENT:
148 case EPERM:
149 /* Print PERROR and goto end not failing. Show must go on. */
150 PERROR("epoll_ctl DEL");
151 goto end;
152 default:
153 PERROR("epoll_ctl DEL fatal");
154 goto error;
155 }
156 PERROR("epoll_ctl del");
157 goto error;
158 }
159
160 events->nb_fd--;
161
162 end:
163 return 0;
164
165 error:
166 return -1;
167 }
168
169 /*
170 * Wait on epoll set. This is a blocking call of timeout value.
171 */
172 int compat_epoll_wait(struct lttng_poll_event *events, int timeout)
173 {
174 int ret;
175
176 if (events == NULL || events->events == NULL ||
177 events->events_size < events->nb_fd) {
178 ERR("Wrong arguments in compat_epoll_wait");
179 goto error;
180 }
181
182 do {
183 ret = epoll_wait(events->epfd, events->events, events->nb_fd, timeout);
184 } while (ret == -1 && errno == EINTR);
185 if (ret < 0) {
186 /* At this point, every error is fatal */
187 PERROR("epoll_wait");
188 goto error;
189 }
190
191 return ret;
192
193 error:
194 return -1;
195 }
196
197 /*
198 * Setup poll set maximum size.
199 */
200 void compat_epoll_set_max_size(void)
201 {
202 int ret, fd;
203 char buf[64];
204
205 poll_max_size = DEFAULT_POLL_SIZE;
206
207 fd = open(COMPAT_EPOLL_PROC_PATH, O_RDONLY);
208 if (fd < 0) {
209 return;
210 }
211
212 ret = read(fd, buf, sizeof(buf));
213 if (ret < 0) {
214 PERROR("read set max size");
215 goto error;
216 }
217
218 poll_max_size = atoi(buf);
219 if (poll_max_size <= 0) {
220 /* Extra precaution */
221 poll_max_size = DEFAULT_POLL_SIZE;
222 }
223
224 DBG("epoll set max size is %d", poll_max_size);
225
226 error:
227 ret = close(fd);
228 if (ret) {
229 PERROR("close");
230 }
231 }
This page took 0.055087 seconds and 4 git commands to generate.