diff --git a/fs/include/vfs_config.h b/fs/include/vfs_config.h index 12b8b1fc..48909065 100644 --- a/fs/include/vfs_config.h +++ b/fs/include/vfs_config.h @@ -96,6 +96,7 @@ extern "C" { #define CONFIG_NEXPANED_DESCRIPTORS (CONFIG_NTIME_DESCRIPTORS + CONFIG_NQUEUE_DESCRIPTORS) #define TIMER_FD_OFFSET FD_SETSIZE #define MQUEUE_FD_OFFSET (FD_SETSIZE + CONFIG_NTIME_DESCRIPTORS) +#define EPOLL_FD_OFFSET (FD_SETSIZE + CONFIG_NTIME_DESCRIPTORS + CONFIG_NQUEUE_DESCRIPTORS) /* net configure */ @@ -129,6 +130,8 @@ extern "C" { #define VFS_USING_WORKDIR // enable current working directory +#define CONFIG_EPOLL_DESCRIPTORS 32 + /* permission configure */ #define DEFAULT_DIR_MODE 0777 #define DEFAULT_FILE_MODE 0666 diff --git a/fs/proc/os_adapt/fd_proc.c b/fs/proc/os_adapt/fd_proc.c index d357227a..337b493b 100644 --- a/fs/proc/os_adapt/fd_proc.c +++ b/fs/proc/os_adapt/fd_proc.c @@ -70,6 +70,8 @@ static void FillFdInfo(struct SeqBuf *seqBuf, struct filelist *fileList, unsigne name = "(timer)"; } else if (sysFd < (MQUEUE_FD_OFFSET + CONFIG_NQUEUE_DESCRIPTORS)) { name = "(mqueue)"; + } else if (sysFd < (EPOLL_FD_OFFSET + CONFIG_EPOLL_DESCRIPTORS)) { + name = "(epoll)"; } else { name = "(unknown)"; } diff --git a/fs/vfs/BUILD.gn b/fs/vfs/BUILD.gn index 71159a7e..5f128d49 100644 --- a/fs/vfs/BUILD.gn +++ b/fs/vfs/BUILD.gn @@ -104,6 +104,7 @@ kernel_module(module_name) { "$LITEOSTHIRDPARTY/NuttX/fs/vfs/fs_truncate64.c", "$LITEOSTHIRDPARTY/NuttX/fs/vfs/fs_unlink.c", "$LITEOSTHIRDPARTY/NuttX/fs/vfs/fs_write.c", + "$LITEOSTOPDIR/fs/vfs/epoll/fs_epoll.c", "$LITEOSTOPDIR/fs/vfs/mount.c", "$LITEOSTOPDIR/fs/vfs/path_cache.c", "$LITEOSTOPDIR/fs/vfs/vnode.c", diff --git a/fs/vfs/Makefile b/fs/vfs/Makefile index 240db04b..9fcfc33a 100644 --- a/fs/vfs/Makefile +++ b/fs/vfs/Makefile @@ -35,6 +35,7 @@ $(LITEOSTOPDIR)/fs/vfs/mount.c \ $(LITEOSTOPDIR)/fs/vfs/vnode.c \ $(LITEOSTOPDIR)/fs/vfs/path_cache.c \ $(LITEOSTOPDIR)/fs/vfs/vnode_hash.c \ +$(LITEOSTOPDIR)/fs/vfs/epoll/fs_epoll.c \ $(LITEOSTHIRDPARTY)/NuttX/fs/vfs/fs_close.c \ $(LITEOSTHIRDPARTY)/NuttX/fs/vfs/fs_dup2.c \ $(LITEOSTHIRDPARTY)/NuttX/fs/vfs/fs_dup.c \ diff --git a/fs/vfs/epoll/fs_epoll.c b/fs/vfs/epoll/fs_epoll.c new file mode 100755 index 00000000..d59e7cdf --- /dev/null +++ b/fs/vfs/epoll/fs_epoll.c @@ -0,0 +1,344 @@ +/* + * Copyright (c) 2021-2021 Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "epoll.h" +#include +#include +#include +#include +#include "pthread.h" + +/* 100, the number of fd one epollfd can control */ +#define EPOLL_DEFAULT_SIZE 100 + +/* Internal data, used to manage each epoll fd */ +struct epoll_head { + int size; + int nodeCount; + struct epoll_event *evs; +}; + +STATIC pthread_mutex_t g_epollMutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; + +#ifndef MAX_EPOLL_FD +#define MAX_EPOLL_FD CONFIG_EPOLL_DESCRIPTORS +#endif + +/* Record the kernel fd of epoll */ +STATIC fd_set g_epollFdSet; + +/* Record the private data of epoll */ +STATIC struct epoll_head *g_epPrivBuf[MAX_EPOLL_FD]; + +/** + * Alloc sysFd, storage epoll private data, set using bit. + * + * @param maxfdp: Maximum allowed application of sysFd. + * @param head: Private data. + * @return the index of the new fd; -1 on error + */ +static int EpollAllocSysFd(int maxfdp, struct epoll_head *head) +{ + int i; + + fd_set *fdset = &g_epollFdSet; + + for (i = 0; i < maxfdp; i++) { + if (fdset && !(FD_ISSET(i + EPOLL_FD_OFFSET, fdset))) { + FD_SET(i + EPOLL_FD_OFFSET, fdset); + if (!g_epPrivBuf[i]) { + g_epPrivBuf[i] = head; + return i + EPOLL_FD_OFFSET; + } + } + } + + set_errno(EMFILE); + return -1; +} + +/** + * free sysFd, delete epoll private data, clear using bit. + * + * @param fd: epoll fd. + * @return 0 or -1 + */ +static int EpollFreeSysFd(int fd) +{ + int id = fd - EPOLL_FD_OFFSET; + + if ((id < 0) || (id >= MAX_EPOLL_FD)) { + set_errno(EMFILE); + return -1; + } + + fd_set *fdset = &g_epollFdSet; + if (fdset && FD_ISSET(fd, fdset)) { + FD_CLR(id, fdset); + g_epPrivBuf[id] = NULL; + } + + return 0; +} + +/** + * get private data by epoll fd + * + * @param fd: epoll fd. + * @return point to epoll_head + */ +static struct epoll_head *EpollGetDataBuff(int fd) +{ + int id = fd - EPOLL_FD_OFFSET; + + if ((id < 0) || (id >= MAX_EPOLL_FD)) { + return NULL; + } + + return g_epPrivBuf[id]; +} + +/** + * when do EPOLL_CTL_ADD, need check if fd exist + * + * @param epHead: epoll control head, find by epoll id . + * @param fd: ctl add fd. + * @return 0 or -1 + */ +static int CheckFdExist(struct epoll_head *epHead, int fd) +{ + int i; + for (i = 0; i < epHead->nodeCount; i++) { + if (epHead->evs[i].data.fd == fd) { + return -1; + } + } + + return 0; +} + +/** + * close epoll + * + * @param epHead: epoll control head. + * @return void + */ +static VOID DoEpollClose(struct epoll_head *epHead) +{ + if (epHead != NULL) { + if (epHead->evs != NULL) { + free(epHead->evs); + } + + free(epHead); + } + return ; +} + +/** + * epoll_create, + * The simple version of epoll does not use red-black trees, + * so when fd is normal value (greater than 0), + * actually allocated epoll can manage num of EPOLL_DEFAULT_SIZE + * + * @param size: not actually used + * @return epoll fd + */ +int epoll_create(int size) +{ + int fd = -1; + + if (size <= 0) { + set_errno(EINVAL); + return fd; + } + + struct epoll_head *epHead = (struct epoll_head *)malloc(sizeof(struct epoll_head)); + if (epHead == NULL) { + set_errno(ENOMEM); + return fd; + } + + /* actually allocated epoll can manage num is EPOLL_DEFAULT_SIZE */ + epHead->size = EPOLL_DEFAULT_SIZE; + epHead->nodeCount = 0; + epHead->evs = malloc(sizeof(struct epoll_event) * EPOLL_DEFAULT_SIZE); + if (epHead->evs == NULL) { + free(epHead); + set_errno(ENOMEM); + return fd; + } + + /* fd set, get sysfd, for close */ + (VOID)pthread_mutex_lock(&g_epollMutex); + fd = EpollAllocSysFd(MAX_EPOLL_FD, epHead); + if (fd == -1) { + (VOID)pthread_mutex_unlock(&g_epollMutex); + DoEpollClose(epHead); + set_errno(EMFILE); + return fd; + } + (VOID)pthread_mutex_unlock(&g_epollMutex); + return fd; +} + +/** + * epoll_close, + * called by close + * @param epfd: epoll fd + * @return 0 or -1 + */ +int epoll_close(int epfd) +{ + struct epoll_head *epHead = NULL; + + epHead = EpollGetDataBuff(epfd); + if (epHead == NULL) { + set_errno(EBADF); + return -1; + } + + DoEpollClose(epHead); + return EpollFreeSysFd(epfd); +} + +int epoll_ctl(int epfd, int op, int fd, struct epoll_event *ev) +{ + struct epoll_head *epHead = NULL; + int i; + int ret = -1; + + epHead = EpollGetDataBuff(epfd); + if (epHead== NULL) { + set_errno(EBADF); + return ret; + } + + switch (op) { + case EPOLL_CTL_ADD: + ret = CheckFdExist(epHead, fd); + if (ret == -1) { + set_errno(EEXIST); + return -1; + } + + if (epHead->nodeCount == EPOLL_DEFAULT_SIZE) { + set_errno(ENOMEM); + return -1; + } + + epHead->evs[epHead->nodeCount].events = ev->events | POLLERR | POLLHUP; + epHead->evs[epHead->nodeCount].data.fd = fd; + epHead->nodeCount++; + return 0; + case EPOLL_CTL_DEL: + for (i = 0; i < epHead->nodeCount; i++) { + if (epHead->evs[i].data.fd != fd) { + continue; + } + + if (i != epHead->nodeCount - 1) { + memmove_s(&epHead->evs[i], epHead->nodeCount - i, &epHead->evs[i + 1], + epHead->nodeCount - i); + } + epHead->nodeCount--; + return 0; + } + set_errno(ENOENT); + return -1; + case EPOLL_CTL_MOD: + for (i = 0; i < epHead->nodeCount; i++) { + if (epHead->evs[i].data.fd == fd) { + epHead->evs[i].events = ev->events | POLLERR | POLLHUP; + return 0; + } + } + set_errno(ENOENT); + return -1; + default: + set_errno(EINVAL); + return -1; + } +} + +int epoll_wait(int epfd, FAR struct epoll_event *evs, int maxevents, int timeout) +{ + struct epoll_head *epHead = NULL; + int ret; + int counter; + int i; + struct pollfd *pFd = NULL; + int pollSize; + + epHead = EpollGetDataBuff(epfd); + if (epHead== NULL) { + set_errno(EBADF); + return -1; + } + + if (maxevents <= 0) { + set_errno(EINVAL); + return -1; + } + + if (maxevents > epHead->nodeCount) { + pollSize = epHead->nodeCount; + } else { + pollSize = maxevents; + } + + pFd = malloc(sizeof(struct pollfd) * pollSize); + if (pFd == NULL) { + set_errno(EINVAL); + return -1; + } + + for (i = 0; i < epHead->nodeCount; i++) { + pFd[i].fd = epHead->evs[i].data.fd; + pFd[i].events = (short)epHead->evs[i].events; + } + + + ret = poll(pFd, pollSize, timeout); + if (ret <= 0) { + return 0; + } + + for (i = 0, counter = 0; i < ret && counter < pollSize; counter++) { + if (pFd[counter].revents != 0) { + evs[i].data.fd = pFd[counter].fd; + evs[i].events = pFd[counter].revents; + i++; + } + } + + return i; +} + diff --git a/fs/vfs/include/epoll.h b/fs/vfs/include/epoll.h new file mode 100755 index 00000000..70f75f64 --- /dev/null +++ b/fs/vfs/include/epoll.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2021-2021 Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _FS_EPOLL_H_ +#define _FS_EPOLL_H_ + +#include "los_typedef.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef FAR +#define FAR +#endif + +#define EPOLL_CLOEXEC O_CLOEXEC +#define EPOLL_NONBLOCK O_NONBLOCK + +#define EPOLLIN 0x001 +#define EPOLLPRI 0x002 +#define EPOLLOUT 0x004 +#define EPOLLRDNORM 0x040 +#define EPOLLNVAL 0x020 +#define EPOLLRDBAND 0x080 +#define EPOLLWRNORM 0x100 +#define EPOLLWRBAND 0x200 +#define EPOLLMSG 0x400 +#define EPOLLERR 0x008 +#define EPOLLHUP 0x010 + +#define EPOLL_CTL_ADD 1 +#define EPOLL_CTL_DEL 2 +#define EPOLL_CTL_MOD 3 + +typedef union epoll_data { + void *ptr; + int fd; + UINT32 u32; + UINT64 u64; +} epoll_data_t; + +struct epoll_event { + UINT32 events; + epoll_data_t data; +}; + +int epoll_create(int size); +int epoll_close(int epfd); +int epoll_ctl(int epfd, int op, int fd, struct epoll_event *ev); +int epoll_wait(int epfd, FAR struct epoll_event *evs, int maxevents, int timeout); + +#ifdef __cplusplus +} +#endif + +#endif /* sys/epoll.h */ diff --git a/syscall/fs_syscall.c b/syscall/fs_syscall.c old mode 100644 new mode 100755 index 530e30d2..acd54a9d --- a/syscall/fs_syscall.c +++ b/syscall/fs_syscall.c @@ -43,6 +43,7 @@ #include "sys/uio.h" #include "poll.h" #include "sys/prctl.h" +#include "epoll.h" #ifdef LOSCFG_KERNEL_DYNLOAD #include "los_exec_elf.h" #endif @@ -2594,4 +2595,132 @@ int SysPselect6(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, return ret; } + +int SysEpollCreate(int size) +{ + int ret; + int procFd; + + if (size <= 0) { + return -EINVAL; + } + + ret = epoll_create(size); + if (ret < 0) { + ret = -get_errno(); + } + + procFd = AllocAndAssocProcessFd((INTPTR)(ret), MIN_START_FD); + if (procFd == -1) { + epoll_close(ret); + return -EMFILE; + } + + return procFd; +} + +int SysEpollCreate1(int flags) +{ + int ret; + int procFd; + + ret = epoll_create(flags); + if (ret < 0) { + ret = -get_errno(); + } + + procFd = AllocAndAssocProcessFd((INTPTR)(ret), MIN_START_FD); + if (procFd == -1) { + epoll_close(ret); + return -EMFILE; + } + + return procFd; +} + +int SysEpollCtl(int epfd, int op, int fd, struct epoll_event *ev) +{ + int ret; + + CHECK_ASPACE(ev, sizeof(struct epoll_event)); + CPY_FROM_USER(ev); + + fd = GetAssociatedSystemFd(fd); + epfd = GetAssociatedSystemFd(epfd); + if ((fd < 0) || (epfd < 0)) { + ret = -EBADF; + goto OUT; + } + + ret = epoll_ctl(epfd, op, fd, ev); + if (ret < 0) { + ret =-EBADF; + goto OUT; + } + + CPY_TO_USER(ev); +OUT: + return (ret == -1)? -get_errno():ret; +} + +int SysEpollWait(int epfd, struct epoll_event *evs, int maxevents, int timeout) +{ + int ret = 0; + + CHECK_ASPACE(evs, sizeof(struct epoll_event)); + CPY_FROM_USER(evs); + + epfd = GetAssociatedSystemFd(epfd); + if (epfd < 0) { + ret = -EBADF; + goto OUT; + } + + ret = epoll_wait(epfd, evs, maxevents, timeout); + if (ret < 0) { + ret = -get_errno(); + } + + CPY_TO_USER(evs); +OUT: + return (ret == -1) ? -get_errno() : ret; +} + +int SysEpollPwait(int epfd, struct epoll_event *evs, int maxevents, int timeout, const sigset_t *mask) +{ + sigset_t_l origMask; + sigset_t_l setl; + int ret = 0; + + CHECK_ASPACE(mask, sizeof(sigset_t)); + + if (mask != NULL) { + ret = LOS_ArchCopyFromUser(&setl, mask, sizeof(sigset_t)); + if (ret != 0) { + return -EFAULT; + } + } + + CHECK_ASPACE(evs, sizeof(struct epoll_event)); + CPY_FROM_USER(evs); + + epfd = GetAssociatedSystemFd(epfd); + if (epfd < 0) { + ret = -EBADF; + goto OUT; + } + + OsSigprocMask(SIG_SETMASK, &setl, &origMask); + ret = epoll_wait(epfd, evs, maxevents, timeout); + if (ret < 0) { + ret = -get_errno(); + } + + OsSigprocMask(SIG_SETMASK, &origMask, NULL); + + CPY_TO_USER(evs); +OUT: + return (ret == -1) ? -get_errno() : ret; +} + #endif diff --git a/syscall/los_syscall.h b/syscall/los_syscall.h old mode 100644 new mode 100755 index eb2ae132..ed89260d --- a/syscall/los_syscall.h +++ b/syscall/los_syscall.h @@ -60,6 +60,7 @@ #include "sys/socket.h" #include "dirent.h" #include "fs/file.h" +#include "epoll.h" #endif #include #include "sys/resource.h" @@ -284,6 +285,11 @@ extern int SysPpoll(struct pollfd *fds, nfds_t nfds, const struct timespec *tmo_ extern int SysPrctl(int option, ...); extern ssize_t SysPread64(int fd, void *buf, size_t nbytes, off64_t offset); extern ssize_t SysPwrite64(int fd, const void *buf, size_t nbytes, off64_t offset); +extern int SysEpollCreate(int size); +extern int SysEpollCreate1(int size); +extern int SysEpollCtl(int epfd, int op, int fd, struct epoll_event *ev); +extern int SysEpollWait(int epfd, struct epoll_event *evs, int maxevents, int timeout); +extern int SysEpollPwait(int epfd, struct epoll_event *evs, int maxevents, int timeout, const sigset_t *mask); extern char *SysGetcwd(char *buf, size_t n); extern ssize_t SysSendFile(int outfd, int infd, off_t *offset, size_t count); extern int SysTruncate(const char *path, off_t length); diff --git a/syscall/syscall_lookup.h b/syscall/syscall_lookup.h old mode 100644 new mode 100755 index d023e2ef..611f29e5 --- a/syscall/syscall_lookup.h +++ b/syscall/syscall_lookup.h @@ -91,6 +91,11 @@ SYSCALL_HAND_DEF(__NR_ppoll, SysPpoll, int, ARG_NUM_5) SYSCALL_HAND_DEF(__NR_prctl, SysPrctl, int, ARG_NUM_7) SYSCALL_HAND_DEF(__NR_pread64, SysPread64, ssize_t, ARG_NUM_7) SYSCALL_HAND_DEF(__NR_pwrite64, SysPwrite64, ssize_t, ARG_NUM_7) +SYSCALL_HAND_DEF(__NR_epoll_create, SysEpollCreate, int, ARG_NUM_1) +SYSCALL_HAND_DEF(__NR_epoll_create1, SysEpollCreate1, int, ARG_NUM_1) +SYSCALL_HAND_DEF(__NR_epoll_ctl, SysEpollCtl, int, ARG_NUM_4) +SYSCALL_HAND_DEF(__NR_epoll_wait, SysEpollWait, int, ARG_NUM_4) +SYSCALL_HAND_DEF(__NR_epoll_pwait, SysEpollPwait, int, ARG_NUM_5) SYSCALL_HAND_DEF(__NR_getcwd, SysGetcwd, char *, ARG_NUM_2) SYSCALL_HAND_DEF(__NR_sendfile, SysSendFile, ssize_t, ARG_NUM_4) SYSCALL_HAND_DEF(__NR_truncate64, SysTruncate64, int, ARG_NUM_7) diff --git a/testsuites/unittest/IO/BUILD.gn b/testsuites/unittest/IO/BUILD.gn old mode 100644 new mode 100755 index fe03995a..0fafbf09 --- a/testsuites/unittest/IO/BUILD.gn +++ b/testsuites/unittest/IO/BUILD.gn @@ -88,6 +88,8 @@ sources_full = [ "full/IO_test_ppoll_003.cpp", "full/IO_test_pselect_001.cpp", "full/IO_test_pselect_002.cpp", + "full/IO_test_epoll_001.cpp", + "full/IO_test_epoll_002.cpp", ] if (LOSCFG_USER_TEST_LEVEL >= TEST_LEVEL_LOW) { diff --git a/testsuites/unittest/IO/It_test_IO.h b/testsuites/unittest/IO/It_test_IO.h index 003c9036..422531de 100644 --- a/testsuites/unittest/IO/It_test_IO.h +++ b/testsuites/unittest/IO/It_test_IO.h @@ -55,6 +55,7 @@ #include "pwd.h" #include "sys/uio.h" #include "syslog.h" +#include "sys/epoll.h" extern int CloseRmAllFile(int fd[], char filePathName[][50], int cnt); extern char *g_ioTestPath; @@ -136,5 +137,7 @@ extern VOID IO_TEST_STRFMON_L_002(VOID); extern VOID IO_TEST_PPOLL_001(VOID); extern VOID IO_TEST_PPOLL_002(VOID); extern VOID IO_TEST_PPOLL_003(VOID); +extern VOID IO_TEST_EPOLL_001(VOID); +extern VOID IO_TEST_EPOLL_002(VOID); #endif diff --git a/testsuites/unittest/IO/full/IO_test_epoll_001.cpp b/testsuites/unittest/IO/full/IO_test_epoll_001.cpp new file mode 100755 index 00000000..ecdca93a --- /dev/null +++ b/testsuites/unittest/IO/full/IO_test_epoll_001.cpp @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "It_test_IO.h" +#include +#include "signal.h" +#include "pthread.h" +#include +#include +#include + +static UINT32 testcase(VOID) +{ + fd_set rfds; + int retval; + pid_t pid; + int pipeFd[2]; /* 2, pipe id num */ + char buffer[40]; /* 40, buffer size */ + int i = 0; + int status; + + int epFd; + sigset_t mask; + struct epoll_event ev; + struct epoll_event evWait[2]; /* 2, evs num */ + + retval = pipe(pipeFd); + ICUNIT_GOTO_EQUAL(retval, 0, retval, OUT); + + /* Watch fd to see when it has input. */ + FD_ZERO(&rfds); + FD_SET(pipeFd[0], &rfds); + + /* Wait up to three seconds. */ + epFd = epoll_create1(100); /* 100, cretae input, */ + ICUNIT_GOTO_NOT_EQUAL(epFd, -1, epFd, OUT); + + ev.events = EPOLLIN | EPOLLOUT | EPOLLRDNORM | EPOLLWRNORM; + retval = epoll_ctl(epFd, EPOLL_CTL_ADD, pipeFd[0], &ev); + ICUNIT_GOTO_NOT_EQUAL(retval, -1, retval, OUT); + + pid = fork(); + if (pid == 0) { + close(pipeFd[1]); + + memset(evWait, 0, sizeof(struct epoll_event) * 2); /* 2, evs num */ + retval = epoll_wait(epFd, evWait, 2, 3000); /* 2, num of wait fd. 3000, wait time */ + close(pipeFd[0]); + + if (retval) { + exit(LOS_OK); + } else { + exit(LOS_NOK); + } + } else { + sleep(1); + close(pipeFd[0]); + retval = write(pipeFd[1], "0123456789012345678901234567890123456789", 40); /* write 40 bytes to stdin(fd 0) */ + ICUNIT_GOTO_EQUAL(retval, 40, retval, OUT); + close(pipeFd[1]); + + wait(&status); + status = WEXITSTATUS(status); + ICUNIT_ASSERT_EQUAL(status, LOS_OK, status); + } + + return LOS_OK; +OUT: + close(pipeFd[0]); + close(pipeFd[1]); + close(epFd); + return LOS_NOK; +} + + +VOID IO_TEST_EPOLL_001(VOID) +{ + TEST_ADD_CASE(__FUNCTION__, testcase, TEST_LIB, TEST_LIBC, TEST_LEVEL1, TEST_FUNCTION); +} diff --git a/testsuites/unittest/IO/full/IO_test_epoll_002.cpp b/testsuites/unittest/IO/full/IO_test_epoll_002.cpp new file mode 100755 index 00000000..8b54bdcd --- /dev/null +++ b/testsuites/unittest/IO/full/IO_test_epoll_002.cpp @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "It_test_IO.h" +#include +#include "signal.h" +#include "pthread.h" +#include +#include +#include + +static void SigPrint(int sig) +{ + return; +} + +static UINT32 testcase(VOID) +{ + fd_set rfds; + struct timespec tv; + int retval; + pid_t pid; + int pipeFd[2]; /* 2, pipe id num */ + char buffer[40]; /* 40, buffer size */ + int i = 0; + int status; + + int epFd; + sigset_t mask; + void (*retSig)(int); + struct epoll_event ev; + struct epoll_event evWait[2]; + + retSig = signal(SIGALRM, SigPrint); + ICUNIT_ASSERT_NOT_EQUAL(retSig, NULL, retSig); + + retSig = signal(SIGUSR1, SigPrint); + ICUNIT_ASSERT_NOT_EQUAL(retSig, NULL, retSig); + + retval = sigemptyset(&mask); + ICUNIT_ASSERT_EQUAL(retval, 0, retval); + + retval = sigaddset(&mask, SIGALRM); + ICUNIT_ASSERT_EQUAL(retval, 0, retval); + + retval = sigaddset(&mask, SIGUSR1); + ICUNIT_ASSERT_EQUAL(retval, 0, retval); + + retval = pipe(pipeFd); + ICUNIT_GOTO_EQUAL(retval, 0, retval, OUT); + + /* Watch fd to see when it has input. */ + FD_ZERO(&rfds); + FD_SET(pipeFd[0], &rfds); + + /* Wait up to three seconds. */ + tv.tv_sec = 3; /* 3, wait timer, second */ + tv.tv_nsec = 5; /* 5, wait timer, nano second */ + + epFd = epoll_create1(100); /* 100, cretae input, */ + ICUNIT_GOTO_NOT_EQUAL(epFd, -1, epFd, OUT); + + ev.events = EPOLLRDNORM; + retval = epoll_ctl(epFd, EPOLL_CTL_ADD, pipeFd[0], &ev); + + ICUNIT_GOTO_NOT_EQUAL(retval, -1, retval, OUT); + + pid = fork(); + if (pid == 0) { + close(pipeFd[1]); + + memset(evWait, 0, sizeof(struct epoll_event) * 2); /* 2, evs num */ + evWait[0].data.fd = pipeFd[0]; + + retval = epoll_pwait(epFd, evWait, 2, 3000, &mask); /* 2, num of wait fd. 3000, wait time */ + close(pipeFd[0]); + + if (retval) { + exit(LOS_OK); + } else { + exit(LOS_NOK); + } + } else { + sleep(1); + close(pipeFd[0]); + + retval = kill(pid, SIGALRM); + ICUNIT_ASSERT_EQUAL(retval, 0, retval); + + retval = kill(pid, SIGUSR1); + ICUNIT_ASSERT_EQUAL(retval, 0, retval); + close(pipeFd[1]); + + wait(&status); + status = WEXITSTATUS(status); + ICUNIT_ASSERT_EQUAL(status, LOS_OK, status); + } + + return LOS_OK; +OUT: + close(pipeFd[0]); + close(pipeFd[1]); + close(epFd); + return LOS_NOK; +} + + +VOID IO_TEST_EPOLL_002(VOID) +{ + TEST_ADD_CASE(__FUNCTION__, testcase, TEST_LIB, TEST_LIBC, TEST_LEVEL1, TEST_FUNCTION); +} diff --git a/testsuites/unittest/IO/io_test.cpp b/testsuites/unittest/IO/io_test.cpp index a689f7c6..186effd3 100644 --- a/testsuites/unittest/IO/io_test.cpp +++ b/testsuites/unittest/IO/io_test.cpp @@ -148,6 +148,29 @@ HWTEST_F(IoTest, IO_TEST_PPOLL_003, TestSize.Level0) IO_TEST_PPOLL_003(); } +/* * + * @tc.name: IO_TEST_EPOLL_001 + * @tc.desc: function for IoTest + * @tc.type: FUNC + * @tc.require: AR000EEMQ9 + */ + +HWTEST_F(IoTest, IO_TEST_EPOLL_001, TestSize.Level0) +{ + IO_TEST_EPOLL_001(); +} + +/* * + * @tc.name: IO_TEST_EPOLL_002 + * @tc.desc: function for IoTest + * @tc.type: FUNC + * @tc.require: AR000EEMQ9 + */ +HWTEST_F(IoTest, IO_TEST_EPOLL_002, TestSize.Level0) +{ + IO_TEST_EPOLL_002(); +} + /* * * @tc.name: IT_STDLIB_POLL_002 * @tc.desc: function for IoTest