From 02ba5f41033e96111caffbb7f4c6dcb662eb7c27 Mon Sep 17 00:00:00 2001 From: Jiuzhu Dong Date: Wed, 26 Jan 2022 21:36:49 +0800 Subject: [PATCH] fs/epoll_fd: support dup file descriptor Signed-off-by: Jiuzhu Dong --- fs/vfs/fs_epoll.c | 43 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/fs/vfs/fs_epoll.c b/fs/vfs/fs_epoll.c index 6c2f9833f4..dcc2599bc2 100644 --- a/fs/vfs/fs_epoll.c +++ b/fs/vfs/fs_epoll.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -47,6 +48,8 @@ struct epoll_head { int size; int occupied; + int crefs; + sem_t sem; struct file fp; struct inode in; FAR epoll_data_t *data; @@ -57,6 +60,7 @@ struct epoll_head * Private Function Prototypes ****************************************************************************/ +static int epoll_do_open(FAR struct file *filep); static int epoll_do_close(FAR struct file *filep); static int epoll_do_poll(FAR struct file *filep, FAR struct pollfd *fds, bool setup); @@ -67,7 +71,7 @@ static int epoll_do_poll(FAR struct file *filep, static const struct file_operations g_epoll_ops = { - NULL, /* open */ + epoll_do_open, /* open */ epoll_do_close, /* close */ NULL, /* read */ NULL, /* write */ @@ -108,12 +112,41 @@ static FAR struct epoll_head *epoll_head_from_fd(int fd) return (FAR struct epoll_head *)filep->f_inode->i_private; } +static int epoll_do_open(FAR struct file *filep) +{ + FAR struct epoll_head *eph = filep->f_inode->i_private; + int ret; + + ret = nxsem_wait(&eph->sem); + if (ret < 0) + { + return ret; + } + + eph->crefs++; + nxsem_post(&eph->sem); + return ret; +} + static int epoll_do_close(FAR struct file *filep) { FAR struct epoll_head *eph = filep->f_inode->i_private; + int ret; - kmm_free(eph); - return OK; + ret = nxsem_wait(&eph->sem); + if (ret < 0) + { + return ret; + } + + eph->crefs--; + nxsem_post(&eph->sem); + if (eph->crefs <= 0) + { + kmm_free(eph); + } + + return ret; } static int epoll_do_poll(FAR struct file *filep, @@ -138,6 +171,8 @@ static int epoll_do_create(int size, int flags) return -1; } + nxsem_init(&eph->sem, 0, 0); + nxsem_set_protocol(&eph->sem, SEM_PRIO_NONE); eph->size = size; eph->data = (FAR epoll_data_t *)(eph + 1); eph->poll = (FAR struct pollfd *)(eph->data + reserve); @@ -155,11 +190,13 @@ static int epoll_do_create(int size, int flags) fd = files_allocate(&eph->in, flags, 0, eph, 0); if (fd < 0) { + nxsem_destroy(&eph->sem); kmm_free(eph); set_errno(-fd); return -1; } + nxsem_post(&eph->sem); return fd; }