Fix: remove nonblock flag of sessiond socket in consumer
[lttng-tools.git] / src / common / compat / compat-epoll.c
CommitLineData
5eb91c98
DG
1/*
2 * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
3 *
d14d33bf
AM
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.
5eb91c98
DG
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 *
d14d33bf
AM
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.
5eb91c98
DG
16 */
17
4c462e79 18#define _GNU_SOURCE
d21b0d71 19#include <assert.h>
5eb91c98
DG
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>
3bd1e081 26#include <config.h>
5eb91c98 27
db758600 28#include <common/error.h>
990570ed 29#include <common/defaults.h>
5eb91c98
DG
30
31#include "poll.h"
32
33unsigned int poll_max_size;
34
d21b0d71
DG
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 */
40static 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
57error:
58 return -1;
59}
60
5eb91c98
DG
61/*
62 * Create epoll set and allocate returned events structure.
63 */
64int 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 */
fb3a43a9 73 if (size > poll_max_size && poll_max_size != 0) {
5eb91c98
DG
74 size = poll_max_size;
75 }
76
77 ret = epoll_create1(flags);
78 if (ret < 0) {
79 /* At this point, every error is fatal */
4c462e79 80 PERROR("epoll_create1");
5eb91c98
DG
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) {
4c462e79 89 PERROR("zmalloc epoll set");
5eb91c98
DG
90 goto error_close;
91 }
92
d21b0d71 93 events->alloc_size = events->init_size = size;
5eb91c98
DG
94 events->nb_fd = 0;
95
96 return 0;
97
98error_close:
4c462e79
MD
99 ret = close(events->epfd);
100 if (ret) {
101 PERROR("close");
102 }
5eb91c98
DG
103error:
104 return -1;
105}
106
107/*
108 * Add a fd to the epoll set with requesting events.
109 */
110int compat_epoll_add(struct lttng_poll_event *events, int fd, uint32_t req_events)
111{
d21b0d71
DG
112 int ret;
113 struct epoll_event ev;
5eb91c98
DG
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:
b7a6b49f
DG
127 /* If exist, it's OK. */
128 goto end;
5eb91c98
DG
129 case ENOSPC:
130 case EPERM:
4c462e79
MD
131 /* Print PERROR and goto end not failing. Show must go on. */
132 PERROR("epoll_ctl ADD");
5eb91c98
DG
133 goto end;
134 default:
4c462e79 135 PERROR("epoll_ctl ADD fatal");
5eb91c98
DG
136 goto error;
137 }
138 }
139
140 events->nb_fd++;
141
5eb91c98
DG
142end:
143 return 0;
144
145error:
146 return -1;
147}
148
149/*
150 * Remove a fd from the epoll set.
151 */
152int 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:
4c462e79
MD
165 /* Print PERROR and goto end not failing. Show must go on. */
166 PERROR("epoll_ctl DEL");
5eb91c98
DG
167 goto end;
168 default:
4c462e79 169 PERROR("epoll_ctl DEL fatal");
5eb91c98
DG
170 goto error;
171 }
5eb91c98
DG
172 }
173
174 events->nb_fd--;
175
176end:
177 return 0;
178
179error:
180 return -1;
181}
182
183/*
184 * Wait on epoll set. This is a blocking call of timeout value.
185 */
186int compat_epoll_wait(struct lttng_poll_event *events, int timeout)
187{
188 int ret;
d21b0d71 189 uint32_t new_size;
5eb91c98 190
d21b0d71 191 if (events == NULL || events->events == NULL) {
5eb91c98
DG
192 ERR("Wrong arguments in compat_epoll_wait");
193 goto error;
194 }
195
d21b0d71
DG
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
3ada8405
DG
222 do {
223 ret = epoll_wait(events->epfd, events->events, events->nb_fd, timeout);
224 } while (ret == -1 && errno == EINTR);
5eb91c98
DG
225 if (ret < 0) {
226 /* At this point, every error is fatal */
4c462e79 227 PERROR("epoll_wait");
5eb91c98
DG
228 goto error;
229 }
230
9ddba525
DG
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 */
5eb91c98
DG
235 return ret;
236
237error:
238 return -1;
239}
240
241/*
242 * Setup poll set maximum size.
243 */
244void compat_epoll_set_max_size(void)
245{
246 int ret, fd;
247 char buf[64];
248
990570ed 249 poll_max_size = DEFAULT_POLL_SIZE;
5eb91c98 250
990570ed 251 fd = open(COMPAT_EPOLL_PROC_PATH, O_RDONLY);
5eb91c98
DG
252 if (fd < 0) {
253 return;
254 }
255
256 ret = read(fd, buf, sizeof(buf));
257 if (ret < 0) {
4c462e79 258 PERROR("read set max size");
5eb91c98
DG
259 goto error;
260 }
261
262 poll_max_size = atoi(buf);
d21b0d71 263 if (poll_max_size == 0) {
5eb91c98 264 /* Extra precaution */
990570ed 265 poll_max_size = DEFAULT_POLL_SIZE;
5eb91c98
DG
266 }
267
268 DBG("epoll set max size is %d", poll_max_size);
269
270error:
4c462e79
MD
271 ret = close(fd);
272 if (ret) {
273 PERROR("close");
274 }
5eb91c98 275}
This page took 0.040255 seconds and 4 git commands to generate.