compat fcntl.h: add cygwin support
[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
5eb91c98
DG
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>
3bd1e081 25#include <config.h>
5eb91c98 26
db758600 27#include <common/error.h>
990570ed 28#include <common/defaults.h>
5eb91c98
DG
29
30#include "poll.h"
31
32unsigned int poll_max_size;
33
34/*
35 * Create epoll set and allocate returned events structure.
36 */
37int 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) {
47 size = poll_max_size;
48 }
49
50 ret = epoll_create1(flags);
51 if (ret < 0) {
52 /* At this point, every error is fatal */
4c462e79 53 PERROR("epoll_create1");
5eb91c98
DG
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) {
4c462e79 62 PERROR("zmalloc epoll set");
5eb91c98
DG
63 goto error_close;
64 }
65
66 events->events_size = size;
67 events->nb_fd = 0;
68
69 return 0;
70
71error_close:
4c462e79
MD
72 ret = close(events->epfd);
73 if (ret) {
74 PERROR("close");
75 }
5eb91c98
DG
76error:
77 return -1;
78}
79
80/*
81 * Add a fd to the epoll set with requesting events.
82 */
83int 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:
b7a6b49f
DG
100 /* If exist, it's OK. */
101 goto end;
5eb91c98
DG
102 case ENOSPC:
103 case EPERM:
4c462e79
MD
104 /* Print PERROR and goto end not failing. Show must go on. */
105 PERROR("epoll_ctl ADD");
5eb91c98
DG
106 goto end;
107 default:
4c462e79 108 PERROR("epoll_ctl ADD fatal");
5eb91c98
DG
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) {
4c462e79 119 PERROR("realloc epoll add");
5eb91c98
DG
120 goto error;
121 }
122 events->events = ptr;
123 events->events_size = new_size;
124 }
125
126end:
127 return 0;
128
129error:
130 return -1;
131}
132
133/*
134 * Remove a fd from the epoll set.
135 */
136int 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:
4c462e79
MD
149 /* Print PERROR and goto end not failing. Show must go on. */
150 PERROR("epoll_ctl DEL");
5eb91c98
DG
151 goto end;
152 default:
4c462e79 153 PERROR("epoll_ctl DEL fatal");
5eb91c98
DG
154 goto error;
155 }
4c462e79 156 PERROR("epoll_ctl del");
5eb91c98
DG
157 goto error;
158 }
159
160 events->nb_fd--;
161
162end:
163 return 0;
164
165error:
166 return -1;
167}
168
169/*
170 * Wait on epoll set. This is a blocking call of timeout value.
171 */
172int 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
3ada8405
DG
182 do {
183 ret = epoll_wait(events->epfd, events->events, events->nb_fd, timeout);
184 } while (ret == -1 && errno == EINTR);
5eb91c98
DG
185 if (ret < 0) {
186 /* At this point, every error is fatal */
4c462e79 187 PERROR("epoll_wait");
5eb91c98
DG
188 goto error;
189 }
190
191 return ret;
192
193error:
194 return -1;
195}
196
197/*
198 * Setup poll set maximum size.
199 */
200void compat_epoll_set_max_size(void)
201{
202 int ret, fd;
203 char buf[64];
204
990570ed 205 poll_max_size = DEFAULT_POLL_SIZE;
5eb91c98 206
990570ed 207 fd = open(COMPAT_EPOLL_PROC_PATH, O_RDONLY);
5eb91c98
DG
208 if (fd < 0) {
209 return;
210 }
211
212 ret = read(fd, buf, sizeof(buf));
213 if (ret < 0) {
4c462e79 214 PERROR("read set max size");
5eb91c98
DG
215 goto error;
216 }
217
218 poll_max_size = atoi(buf);
219 if (poll_max_size <= 0) {
220 /* Extra precaution */
990570ed 221 poll_max_size = DEFAULT_POLL_SIZE;
5eb91c98
DG
222 }
223
224 DBG("epoll set max size is %d", poll_max_size);
225
226error:
4c462e79
MD
227 ret = close(fd);
228 if (ret) {
229 PERROR("close");
230 }
5eb91c98 231}
This page took 0.03685 seconds and 4 git commands to generate.