2 * Copyright (C) 2018, 2019 "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.
20 #include <sys/epoll.h>
24 #include "fdev-epoll.h"
27 * For sake of simplicity there is no struct fdev_epoll.
28 * Instead, the file descriptor of the internal epoll is used
29 * and wrapped in a pseudo pointer to a pseudo struct.
31 #define epollfd(fdev_epoll) ((int)(intptr_t)fdev_epoll)
34 * disable callback for fdev
36 * refs to fdev must not be counted here
38 static void disable(void *closure, const struct fdev *fdev)
40 struct fdev_epoll *fdev_epoll = closure;
41 epoll_ctl(epollfd(fdev_epoll), EPOLL_CTL_DEL, fdev_fd(fdev), 0);
45 * enable callback for fdev
47 * refs to fdev must not be counted here
49 static void enable_or_update(void *closure, const struct fdev *fdev, int op, int err)
51 struct fdev_epoll *fdev_epoll = closure;
52 struct epoll_event event;
56 event.events = fdev_events(fdev);
57 event.data.ptr = (void*)fdev;
58 rc = epoll_ctl(epollfd(fdev_epoll), op, fd, &event);
59 if (rc < 0 && errno == err)
60 epoll_ctl(epollfd(fdev_epoll), (EPOLL_CTL_MOD + EPOLL_CTL_ADD) - op, fd, &event);
64 * enable callback for fdev
66 * refs to fdev must not be counted here
68 static void enable(void *closure, const struct fdev *fdev)
70 enable_or_update(closure, fdev, EPOLL_CTL_ADD, EEXIST);
74 * update callback for fdev
76 * refs to fdev must not be counted here
78 static void update(void *closure, const struct fdev *fdev)
80 enable_or_update(closure, fdev, EPOLL_CTL_MOD, ENOENT);
84 * unref is not handled here
86 static struct fdev_itf itf =
95 * create an fdev_epoll
97 struct fdev_epoll *fdev_epoll_create()
99 int fd = epoll_create1(EPOLL_CLOEXEC);
104 return fd < 0 ? 0 : (struct fdev_epoll*)(intptr_t)fd;
108 * destroy the fdev_epoll
110 void fdev_epoll_destroy(struct fdev_epoll *fdev_epoll)
112 close(epollfd(fdev_epoll));
116 * get pollable fd for the fdev_epoll
118 int fdev_epoll_fd(struct fdev_epoll *fdev_epoll)
120 return epollfd(fdev_epoll);
124 * create an fdev linked to the 'fdev_epoll' for 'fd'
126 struct fdev *fdev_epoll_add(struct fdev_epoll *fdev_epoll, int fd)
130 fdev = fdev_create(fd);
132 fdev_set_itf(fdev, &itf, fdev_epoll);
137 * get pollable fd for the fdev_epoll
139 int fdev_epoll_wait_and_dispatch(struct fdev_epoll *fdev_epoll, int timeout_ms)
142 struct epoll_event events;
145 rc = epoll_wait(epollfd(fdev_epoll), &events, 1, timeout_ms < 0 ? -1 : timeout_ms);
147 fdev = events.data.ptr;
148 fdev_dispatch(fdev, events.events);