fs/epoll_fd: support dup file descriptor

Signed-off-by: Jiuzhu Dong <dongjiuzhu1@xiaomi.com>
This commit is contained in:
Jiuzhu Dong
2022-01-26 21:36:49 +08:00
committed by Xiang Xiao
parent bff02fcd79
commit 02ba5f4103
+40 -3
View File
@@ -32,6 +32,7 @@
#include <errno.h> #include <errno.h>
#include <string.h> #include <string.h>
#include <debug.h> #include <debug.h>
#include <semaphore.h>
#include <nuttx/clock.h> #include <nuttx/clock.h>
#include <nuttx/fs/fs.h> #include <nuttx/fs/fs.h>
@@ -47,6 +48,8 @@ struct epoll_head
{ {
int size; int size;
int occupied; int occupied;
int crefs;
sem_t sem;
struct file fp; struct file fp;
struct inode in; struct inode in;
FAR epoll_data_t *data; FAR epoll_data_t *data;
@@ -57,6 +60,7 @@ struct epoll_head
* Private Function Prototypes * 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_close(FAR struct file *filep);
static int epoll_do_poll(FAR struct file *filep, static int epoll_do_poll(FAR struct file *filep,
FAR struct pollfd *fds, bool setup); 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 = static const struct file_operations g_epoll_ops =
{ {
NULL, /* open */ epoll_do_open, /* open */
epoll_do_close, /* close */ epoll_do_close, /* close */
NULL, /* read */ NULL, /* read */
NULL, /* write */ 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; 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) static int epoll_do_close(FAR struct file *filep)
{ {
FAR struct epoll_head *eph = filep->f_inode->i_private; FAR struct epoll_head *eph = filep->f_inode->i_private;
int ret;
kmm_free(eph); ret = nxsem_wait(&eph->sem);
return OK; 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, static int epoll_do_poll(FAR struct file *filep,
@@ -138,6 +171,8 @@ static int epoll_do_create(int size, int flags)
return -1; return -1;
} }
nxsem_init(&eph->sem, 0, 0);
nxsem_set_protocol(&eph->sem, SEM_PRIO_NONE);
eph->size = size; eph->size = size;
eph->data = (FAR epoll_data_t *)(eph + 1); eph->data = (FAR epoll_data_t *)(eph + 1);
eph->poll = (FAR struct pollfd *)(eph->data + reserve); 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); fd = files_allocate(&eph->in, flags, 0, eph, 0);
if (fd < 0) if (fd < 0)
{ {
nxsem_destroy(&eph->sem);
kmm_free(eph); kmm_free(eph);
set_errno(-fd); set_errno(-fd);
return -1; return -1;
} }
nxsem_post(&eph->sem);
return fd; return fd;
} }