Fix: remove dead code
[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 <assert.h>
20 #include <fcntl.h>
21 #include <limits.h>
22 #include <stdlib.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <unistd.h>
26 #include <config.h>
27
28 #include <common/error.h>
29 #include <common/defaults.h>
30
31 #include "poll.h"
32
33 unsigned int poll_max_size;
34
35 /*
36 * Resize the epoll events structure of the new size.
37 *
38 * Return 0 on success or else -1 with the current events pointer untouched.
39 */
40 static int resize_poll_event(struct lttng_poll_event *events,
41 uint32_t new_size)
42 {
43 struct epoll_event *ptr;
44
45 assert(events);
46
47 ptr = realloc(events->events, new_size * sizeof(*ptr));
48 if (ptr == NULL) {
49 PERROR("realloc epoll add");
50 goto error;
51 }
52 events->events = ptr;
53 events->alloc_size = new_size;
54
55 return 0;
56
57 error:
58 return -1;
59 }
60
61 /*
62 * Create epoll set and allocate returned events structure.
63 */
64 int compat_epoll_create(struct lttng_poll_event *events, int size, int flags)
65 {
66 int ret;
67
68 if (events == NULL || size <= 0) {
69 goto error;
70 }
71
72 /* Don't bust the limit here */
73 if (size > poll_max_size && poll_max_size != 0) {
74 size = poll_max_size;
75 }
76
77 ret = epoll_create1(flags);
78 if (ret < 0) {
79 /* At this point, every error is fatal */
80 PERROR("epoll_create1");
81 goto error;
82 }
83
84 events->epfd = ret;
85
86 /* This *must* be freed by using lttng_poll_free() */
87 events->events = zmalloc(size * sizeof(struct epoll_event));
88 if (events->events == NULL) {
89 PERROR("zmalloc epoll set");
90 goto error_close;
91 }
92
93 events->alloc_size = events->init_size = size;
94 events->nb_fd = 0;
95
96 return 0;
97
98 error_close:
99 ret = close(events->epfd);
100 if (ret) {
101 PERROR("close");
102 }
103 error:
104 return -1;
105 }
106
107 /*
108 * Add a fd to the epoll set with requesting events.
109 */
110 int compat_epoll_add(struct lttng_poll_event *events, int fd, uint32_t req_events)
111 {
112 int ret;
113 struct epoll_event ev;
114
115 if (events == NULL || events->events == NULL || fd < 0) {
116 ERR("Bad compat epoll add arguments");
117 goto error;
118 }
119
120 ev.events = req_events;
121 ev.data.fd = fd;
122
123 ret = epoll_ctl(events->epfd, EPOLL_CTL_ADD, fd, &ev);
124 if (ret < 0) {
125 switch (errno) {
126 case EEXIST:
127 /* If exist, it's OK. */
128 goto end;
129 case ENOSPC:
130 case EPERM:
131 /* Print PERROR and goto end not failing. Show must go on. */
132 PERROR("epoll_ctl ADD");
133 goto end;
134 default:
135 PERROR("epoll_ctl ADD fatal");
136 goto error;
137 }
138 }
139
140 events->nb_fd++;
141
142 end:
143 return 0;
144
145 error:
146 return -1;
147 }
148
149 /*
150 * Remove a fd from the epoll set.
151 */
152 int compat_epoll_del(struct lttng_poll_event *events, int fd)
153 {
154 int ret;
155
156 if (events == NULL || fd < 0) {
157 goto error;
158 }
159
160 ret = epoll_ctl(events->epfd, EPOLL_CTL_DEL, fd, NULL);
161 if (ret < 0) {
162 switch (errno) {
163 case ENOENT:
164 case EPERM:
165 /* Print PERROR and goto end not failing. Show must go on. */
166 PERROR("epoll_ctl DEL");
167 goto end;
168 default:
169 PERROR("epoll_ctl DEL fatal");
170 goto error;
171 }
172 }
173
174 events->nb_fd--;
175
176 end:
177 return 0;
178
179 error:
180 return -1;
181 }
182
183 /*
184 * Wait on epoll set. This is a blocking call of timeout value.
185 */
186 int compat_epoll_wait(struct lttng_poll_event *events, int timeout)
187 {
188 int ret;
189 uint32_t new_size;
190
191 if (events == NULL || events->events == NULL) {
192 ERR("Wrong arguments in compat_epoll_wait");
193 goto error;
194 }
195
196 /*
197 * Resize if needed before waiting. We could either expand the array or
198 * shrink it down. It's important to note that after this step, we are
199 * ensured that the events argument of the epoll_wait call will be large
200 * enough to hold every possible returned events.
201 */
202 if (events->nb_fd > events->alloc_size) {
203 /* Expand if the nb_fd is higher than the actual size. */
204 new_size = events->alloc_size << 1UL;
205 } else if ((events->nb_fd << 1UL) <= events->alloc_size &&
206 events->nb_fd >= events->init_size) {
207 /* Shrink if nb_fd multiplied by two is <= than the actual size. */
208 new_size = events->alloc_size >> 1UL;
209 } else {
210 /* Indicate that we don't want to resize. */
211 new_size = 0;
212 }
213
214 if (new_size) {
215 ret = resize_poll_event(events, new_size);
216 if (ret < 0) {
217 /* ENOMEM problem at this point. */
218 goto error;
219 }
220 }
221
222 do {
223 ret = epoll_wait(events->epfd, events->events, events->nb_fd, timeout);
224 } while (ret == -1 && errno == EINTR);
225 if (ret < 0) {
226 /* At this point, every error is fatal */
227 PERROR("epoll_wait");
228 goto error;
229 }
230
231 /*
232 * Since the returned events are set sequentially in the "events" structure
233 * we only need to return the epoll_wait value and iterate over it.
234 */
235 return ret;
236
237 error:
238 return -1;
239 }
240
241 /*
242 * Setup poll set maximum size.
243 */
244 void compat_epoll_set_max_size(void)
245 {
246 int ret, fd;
247 char buf[64];
248
249 poll_max_size = DEFAULT_POLL_SIZE;
250
251 fd = open(COMPAT_EPOLL_PROC_PATH, O_RDONLY);
252 if (fd < 0) {
253 return;
254 }
255
256 ret = read(fd, buf, sizeof(buf));
257 if (ret < 0) {
258 PERROR("read set max size");
259 goto error;
260 }
261
262 poll_max_size = atoi(buf);
263 if (poll_max_size == 0) {
264 /* Extra precaution */
265 poll_max_size = DEFAULT_POLL_SIZE;
266 }
267
268 DBG("epoll set max size is %d", poll_max_size);
269
270 error:
271 ret = close(fd);
272 if (ret) {
273 PERROR("close");
274 }
275 }
This page took 0.035591 seconds and 5 git commands to generate.