diff --git a/fs/vfs/Make.defs b/fs/vfs/Make.defs index 09d0eb5242..6769e8b12c 100644 --- a/fs/vfs/Make.defs +++ b/fs/vfs/Make.defs @@ -68,7 +68,7 @@ else CSRCS += fs_close.c fs_dup.c fs_dup2.c fs_fcntl.c fs_dupfd.c fs_dupfd2.c CSRCS += fs_getfilep.c fs_ioctl.c fs_lseek.c fs_mkdir.c fs_open.c fs_poll.c CSRCS += fs_read.c fs_rename.c fs_rmdir.c fs_stat.c fs_statfs.c fs_select.c -CSRCS += fs_unlink.c fs_write.c +CSRCS += fs_unlink.c fs_write.c epoll.c # Certain interfaces are not available if there is no mountpoint support diff --git a/fs/vfs/epoll.c b/fs/vfs/epoll.c new file mode 100644 index 0000000000..9b7bdf2d7e --- /dev/null +++ b/fs/vfs/epoll.c @@ -0,0 +1,102 @@ +#include +#include +#include +#include +#include + +#include + +int epoll_create(int size) +{ + struct epoll_head *eph = malloc(sizeof(struct epoll_head)); + + eph->size = size; + eph->occupied = 0; + eph->evs = malloc(sizeof(struct epoll_event) * eph->size); + + return (int)eph; +} + +void epoll_close(int epfd) +{ + struct epoll_head *eph = (struct epoll_head *)epfd; + + free(eph->evs); + free(eph); +} + +int epoll_ctl(int epfd, int op, int fd, struct epoll_event *ev) +{ + struct epoll_head *eph = (struct epoll_head *)epfd; + + switch (op) + { + case EPOLL_CTL_ADD: + printf("%08x CTL ADD(%d): fd=%d ev=%08x\n", epfd, eph->occupied, fd, ev->events); + eph->evs[eph->occupied].events = ev->events | POLLERR | POLLHUP; + eph->evs[eph->occupied++].data.fd = fd; + return 0; + + case EPOLL_CTL_DEL: + { + int i; + for (i=0; i < eph->occupied; i++) + { + if (eph->evs[i].data.fd == fd) + { + if (i != eph->occupied-1) + memmove(&eph->evs[i], &eph->evs[i + 1], eph->occupied - i); + eph->occupied--; + return 0; + } + } + return -ENOENT; + } + + case EPOLL_CTL_MOD: + { + int i; + printf("%08x CTL MOD(%d): fd=%d ev=%08x\n", epfd, eph->occupied, fd, ev->events); + for (i=0; i < eph->occupied; i++) + { + if (eph->evs[i].data.fd == fd) + { + eph->evs[i].events = ev->events | POLLERR | POLLHUP; + return 0; + } + } + return -ENOENT; + } + } + + return -EINVAL; +} + +int epoll_wait(int epfd, struct epoll_event *evs, int maxevents, int timeout) +{ + int i; + int rc; + struct epoll_head *eph = (struct epoll_head *)epfd; + + rc = poll((struct pollfd *)eph->evs, eph->occupied, timeout); + + if (rc <= 0) + { + if (rc < 0) { + printf("%08x poll fail: %d for %d, %d msecs\n", epfd, rc, eph->occupied, timeout); + for (i=0; i < eph->occupied; i++) + { + printf("%02d: fd=%d\n", i, eph->evs[i].data.fd); + } + } + return rc; + } + + for (i=0; i < rc; i++) + { + evs[i].data.fd = (pollevent_t)eph->evs[i].data.fd; + evs[i].events = (pollevent_t)eph->evs[i].revents; + } + + return rc; +} diff --git a/include/sys/epoll.h b/include/sys/epoll.h new file mode 100644 index 0000000000..96fe2efe17 --- /dev/null +++ b/include/sys/epoll.h @@ -0,0 +1,59 @@ +#ifndef _EPOLL__H +#define _EPOLL__H + +#include + +enum EPOLL_EVENTS + { + EPOLLIN = POLLIN, +#define EPOLLIN EPOLLIN + EPOLLPRI = POLLPRI, +#define EPOLLPRI EPOLLPRI + EPOLLOUT = POLLOUT, +#define EPOLLOUT EPOLLOUT + EPOLLRDNORM = POLLRDNORM, +#define EPOLLRDNORM EPOLLRDNORM + EPOLLRDBAND = POLLRDBAND, +#define EPOLLRDBAND EPOLLRDBAND + EPOLLWRNORM = POLLWRNORM, +#define EPOLLWRNORM EPOLLWRNORM + EPOLLWRBAND = POLLWRBAND, +#define EPOLLWRBAND EPOLLWRBAND + EPOLLERR = POLLERR, +#define EPOLLERR EPOLLERR + EPOLLHUP = POLLHUP, +#define EPOLLHUP EPOLLHUP + }; + +#define EPOLL_CTL_ADD 1 /* Add a file descriptor to the interface. */ +#define EPOLL_CTL_DEL 2 /* Remove a file descriptor from the interface. */ +#define EPOLL_CTL_MOD 3 /* Change file descriptor epoll_event structure. */ + +typedef union poll_data +{ + int fd; /* The descriptor being polled */ +} epoll_data_t; + +struct epoll_event +{ + epoll_data_t data; + sem_t *sem; /* Pointer to semaphore used to post output event */ + pollevent_t events; /* The input event flags */ + pollevent_t revents; /* The output event flags */ + FAR void *priv; /* For use by drivers */ +}; + +struct epoll_head +{ + int size; + int occupied; + struct epoll_event *evs; +}; + +int epoll_create(int size); +int epoll_ctl(int epfd, int op, int fd, struct epoll_event *ev); +int epoll_wait(int epfd, struct epoll_event *evs, int maxevents, int timeout); + +void epoll_close(int epfd); + +#endif