2 * Copyright 2016 IoT.bzh
3 * Author: José Bollo <jose.bollo@iot.bzh>
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 #include <sys/epoll.h>
25 #include "utils-upoll.h"
34 void (*write)(void *);
35 void (*hangup)(void *);
48 static int pollfd = 0;
49 static struct upollfd *head = NULL;
50 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
52 static int update(struct upollfd *ufd)
61 pthread_mutex_lock(&mutex);
64 /* no more watchers */
73 pthread_mutex_unlock(&mutex);
74 epoll_ctl(pollfd, EPOLL_CTL_DEL, ufd->fd, NULL);
78 /* compute the events for the watchers */
86 pthread_mutex_unlock(&mutex);
87 if (ufd->events == events)
91 rc = epoll_ctl(pollfd, EPOLL_CTL_MOD, ufd->fd, &e);
97 static struct upollfd *get_fd(int fd)
100 struct upollfd *result;
103 /* opens the epoll stream */
105 pollfd = epoll_create1(EPOLL_CLOEXEC);
118 while (result != NULL) {
119 if (result->fd == fd)
121 result = result->next;
125 result = calloc(1, sizeof *result);
131 pthread_mutex_lock(&mutex);
134 pthread_mutex_unlock(&mutex);
139 rc = epoll_ctl(pollfd, EPOLL_CTL_ADD, fd, &e);
143 /* revert on error */
150 int upoll_is_valid(struct upoll *upoll)
152 struct upollfd *itfd = head;
154 while (itfd != NULL) {
166 struct upoll *upoll_open(int fd, void *closure)
169 struct upoll *result;
172 result = calloc(1, sizeof *result);
185 result->closure = closure;
186 pthread_mutex_lock(&mutex);
187 result->next = ufd->head;
189 pthread_mutex_unlock(&mutex);
193 int upoll_on_readable(struct upoll *upoll, void (*process)(void *))
196 assert(upoll_is_valid(upoll));
198 upoll->read = process;
199 return update(upoll->fd);
202 int upoll_on_writable(struct upoll *upoll, void (*process)(void *))
205 assert(upoll_is_valid(upoll));
207 upoll->write = process;
208 return update(upoll->fd);
211 void upoll_on_hangup(struct upoll *upoll, void (*process)(void *))
214 assert(upoll_is_valid(upoll));
216 upoll->hangup = process;
219 void upoll_close(struct upoll *upoll)
225 assert(upoll_is_valid(upoll));
228 pthread_mutex_lock(&mutex);
233 pthread_mutex_unlock(&mutex);
238 int upoll_wait(int timeout)
241 struct epoll_event e;
251 rc = epoll_wait(pollfd, &e, 1, timeout);
252 } while (rc < 0 && errno == EINTR);
257 if ((e.events & EPOLLIN) && u->read) {
260 if ((e.events & EPOLLOUT) && u->write) {
261 u->write(u->closure);
263 if ((e.events & EPOLLHUP) && u->hangup) {
264 u->hangup(u->closure);
269 return rc < 0 ? rc : 0;