diff options
Diffstat (limited to 'components/libc')
| -rw-r--r-- | components/libc/compilers/common/ctime.c | 21 | ||||
| -rw-r--r-- | components/libc/compilers/common/include/dirent.h | 6 | ||||
| -rw-r--r-- | components/libc/compilers/common/include/sys/ioctl.h | 7 | ||||
| -rw-r--r-- | components/libc/compilers/common/include/sys/unistd.h | 2 | ||||
| -rw-r--r-- | components/libc/compilers/musl/fcntl.h | 33 | ||||
| -rw-r--r-- | components/libc/posix/Kconfig | 2 | ||||
| -rw-r--r-- | components/libc/posix/io/epoll/epoll.c | 68 | ||||
| -rw-r--r-- | components/libc/posix/io/poll/poll.c | 58 | ||||
| -rw-r--r-- | components/libc/posix/io/termios/termios.h | 14 |
9 files changed, 161 insertions, 50 deletions
diff --git a/components/libc/compilers/common/ctime.c b/components/libc/compilers/common/ctime.c index 44822ec379..a1bb3c439d 100644 --- a/components/libc/compilers/common/ctime.c +++ b/components/libc/compilers/common/ctime.c @@ -25,6 +25,7 @@ * 2023-08-12 Meco Man re-implement RT-Thread lightweight timezone API * 2023-09-15 xqyjlj perf rt_hw_interrupt_disable/enable * 2023-10-23 Shell add lock for _g_timerid + * 2023-11-16 Shell Fixup of nanosleep if previous call was interrupted */ #include "sys/time.h" @@ -544,20 +545,24 @@ int nanosleep(const struct timespec *rqtp, struct timespec *rmtp) unsigned long ns = rqtp->tv_sec * NANOSECOND_PER_SECOND + rqtp->tv_nsec; rt_ktime_boottime_get_ns(&old_ts); rt_ktime_hrtimer_ndelay(ns); - if (rt_get_errno() == -RT_EINTR) + if (rt_get_errno() == RT_EINTR) { if (rmtp) { + rt_base_t rsec, rnsec; rt_ktime_boottime_get_ns(&new_ts); - rmtp->tv_sec = 0; - rmtp->tv_nsec = - (old_ts.tv_nsec + ns) - ((new_ts.tv_sec - old_ts.tv_sec) * NANOSECOND_PER_SECOND + new_ts.tv_nsec); - - if (rmtp->tv_nsec > NANOSECOND_PER_SECOND) + rsec = old_ts.tv_sec + rqtp->tv_sec - new_ts.tv_sec; + rnsec = old_ts.tv_nsec + rqtp->tv_nsec - new_ts.tv_nsec; + if (rnsec < 0) + { + rmtp->tv_sec = rsec - 1; + rmtp->tv_nsec = NANOSECOND_PER_SECOND + rnsec; + } + else { - rmtp->tv_nsec %= NANOSECOND_PER_SECOND; - rmtp->tv_sec += rmtp->tv_nsec / NANOSECOND_PER_SECOND; + rmtp->tv_sec = rsec; + rmtp->tv_nsec = rnsec; } } rt_set_errno(EINTR); diff --git a/components/libc/compilers/common/include/dirent.h b/components/libc/compilers/common/include/dirent.h index f1a45d2986..51451e2d59 100644 --- a/components/libc/compilers/common/include/dirent.h +++ b/components/libc/compilers/common/include/dirent.h @@ -32,9 +32,13 @@ extern "C" { #define DT_UNKNOWN 0x00 #define DT_FIFO 0x01 -#define DT_SYMLINK 0x03 +#define DT_CHR 0x02 #define DT_DIR 0x04 +#define DT_BLK 0x06 #define DT_REG 0x08 +#define DT_LNK 0x0a +#define DT_SOCK 0x0c +#define DT_SYMLINK DT_LNK #ifndef HAVE_DIR_STRUCTURE #define HAVE_DIR_STRUCTURE diff --git a/components/libc/compilers/common/include/sys/ioctl.h b/components/libc/compilers/common/include/sys/ioctl.h index ab0c069550..908074863a 100644 --- a/components/libc/compilers/common/include/sys/ioctl.h +++ b/components/libc/compilers/common/include/sys/ioctl.h @@ -15,6 +15,10 @@ extern "C" { #endif +#ifdef RT_USING_MUSLLIBC +#include_next <sys/ioctl.h> +#else + struct winsize { unsigned short ws_row; @@ -23,9 +27,6 @@ struct winsize unsigned short ws_ypixel; }; -#ifdef RT_USING_MUSLLIBC -#include <bits/ioctl.h> -#else /* * Direction bits, which any architecture can choose to override * before including this file. diff --git a/components/libc/compilers/common/include/sys/unistd.h b/components/libc/compilers/common/include/sys/unistd.h index b9c64f3bb6..824891d57e 100644 --- a/components/libc/compilers/common/include/sys/unistd.h +++ b/components/libc/compilers/common/include/sys/unistd.h @@ -19,6 +19,8 @@ extern "C" { #endif +#define _POSIX_VDISABLE 0 + #define STDIN_FILENO 0 /* standard input file descriptor */ #define STDOUT_FILENO 1 /* standard output file descriptor */ #define STDERR_FILENO 2 /* standard error file descriptor */ diff --git a/components/libc/compilers/musl/fcntl.h b/components/libc/compilers/musl/fcntl.h index 05d466f848..9388f10de1 100644 --- a/components/libc/compilers/musl/fcntl.h +++ b/components/libc/compilers/musl/fcntl.h @@ -13,12 +13,37 @@ #include_next <fcntl.h> -#ifndef O_DIRECTORY -#define O_DIRECTORY 0x200000 -#endif +#define O_CREAT 0100 +#define O_EXCL 0200 +#define O_NOCTTY 0400 +#define O_TRUNC 01000 +#define O_APPEND 02000 +#define O_NONBLOCK 04000 +#define O_DSYNC 010000 +#define O_SYNC 04010000 +#define O_RSYNC 04010000 +#define O_DIRECTORY 040000 +#define O_NOFOLLOW 0100000 +#define O_CLOEXEC 02000000 + +#define O_ASYNC 020000 +#define O_DIRECT 0200000 +#define O_LARGEFILE 0400000 +#define O_NOATIME 01000000 +#define O_PATH 010000000 +#define O_TMPFILE 020040000 +#define O_NDELAY O_NONBLOCK #ifndef O_BINARY -#define O_BINARY 0x10000 +#define O_BINARY 00 #endif +#ifndef O_SEARCH +#define O_SEARCH O_PATH +#endif /* O_SEARCH */ + +#ifndef O_EXEC +#define O_EXEC O_PATH +#endif /* O_EXEC */ + #endif diff --git a/components/libc/posix/Kconfig b/components/libc/posix/Kconfig index d8627c242a..7d6539234f 100644 --- a/components/libc/posix/Kconfig +++ b/components/libc/posix/Kconfig @@ -27,7 +27,7 @@ if RT_USING_POSIX_FS select RT_USING_POSIX_POLL default y if RT_USING_SMART default n - + config RT_USING_POSIX_EVENTFD bool "Enable I/O event eventfd <sys/eventfd.h>" select RT_USING_POSIX_POLL diff --git a/components/libc/posix/io/epoll/epoll.c b/components/libc/posix/io/epoll/epoll.c index cd313c9247..26527fb611 100644 --- a/components/libc/posix/io/epoll/epoll.c +++ b/components/libc/posix/io/epoll/epoll.c @@ -4,9 +4,14 @@ * SPDX-License-Identifier: Apache-2.0 * * Change Logs: - * Date Author Notes - * 2023-07-29 zmq810150896 first version - * 2024/03/26 TroyMitchelle Add comments for all functions, members within structure members and fix incorrect naming of triggered + * Date Author Notes + * 2023-07-29 zmq810150896 first version + * 2024/03/26 TroyMitchelle Add comments for all functions, members within structure members and fix incorrect naming of triggered + * 2023-12-14 Shell When poll goes to sleep before the waitqueue has added a + * record and finished enumerating all the fd's, it may be + * incorrectly woken up. This is basically because the poll + * mechanism wakeup algorithm does not correctly distinguish + * the current wait state. */ #include <rtthread.h> @@ -27,6 +32,12 @@ struct rt_eventpoll; +enum rt_epoll_status { + RT_EPOLL_STAT_INIT, + RT_EPOLL_STAT_TRIG, + RT_EPOLL_STAT_WAITING, +}; + /* Monitor queue */ struct rt_fd_list { @@ -44,15 +55,15 @@ struct rt_fd_list struct rt_eventpoll { - rt_uint32_t triggered; /**< Indicates if the wait thread is triggered */ - rt_wqueue_t epoll_read; /**< Epoll read queue */ - rt_thread_t polling_thread; /**< Polling thread */ - struct rt_mutex lock; /**< Mutex lock */ - struct rt_fd_list *fdlist; /**< Monitor list */ - int eventpoll_num; /**< Number of ready lists */ - rt_pollreq_t req; /**< Poll request structure */ - struct rt_spinlock spinlock;/**< Spin lock */ - rt_slist_t rdl_head; /**< Ready list head */ + rt_wqueue_t epoll_read; /**< Epoll read queue */ + rt_thread_t polling_thread; /**< Polling thread */ + struct rt_mutex lock; /**< Mutex lock */ + struct rt_fd_list *fdlist; /**< Monitor list */ + int eventpoll_num; /**< Number of ready lists */ + rt_pollreq_t req; /**< Poll request structure */ + struct rt_spinlock spinlock; /**< Spin lock */ + rt_slist_t rdl_head; /**< Ready list head */ + enum rt_epoll_status status; /* the waited thread whether triggered */ }; static int epoll_close(struct dfs_file *file); @@ -85,8 +96,7 @@ static int epoll_close_fdlist(struct rt_fd_list *fdlist) while (list->next != RT_NULL) { fre_node = list->next; - if (fre_node->wqn.wqueue) - rt_wqueue_remove(&fre_node->wqn); + rt_wqueue_remove(&fre_node->wqn); list->next = fre_node->next; rt_free(fre_node); @@ -188,13 +198,14 @@ static int epoll_wqueue_callback(struct rt_wqueue_node *wait, void *key) struct rt_fd_list *fdlist; struct rt_eventpoll *ep; rt_base_t level; + int is_waiting = 0; if (key && !((rt_ubase_t)key & wait->key)) return -1; fdlist = rt_container_of(wait, struct rt_fd_list, wqn); - ep = fdlist->ep; + if (ep) { level = rt_spin_lock_irqsave(&ep->spinlock); @@ -203,16 +214,21 @@ static int epoll_wqueue_callback(struct rt_wqueue_node *wait, void *key) rt_slist_append(&ep->rdl_head, &fdlist->rdl_node); fdlist->exclusive = 0; fdlist->is_rdl_node = RT_TRUE; - ep->triggered = 1; ep->eventpoll_num++; + is_waiting = (ep->status == RT_EPOLL_STAT_WAITING); + ep->status = RT_EPOLL_STAT_TRIG; rt_wqueue_wakeup(&ep->epoll_read, (void *)POLLIN); } rt_spin_unlock_irqrestore(&ep->spinlock, level); } - return __wqueue_default_wake(wait, key); -} + if (is_waiting) + { + return __wqueue_default_wake(wait, key); + } + return -1; +} /** * @brief Adds a callback function to the wait queue associated with epoll. @@ -265,8 +281,8 @@ static void epoll_ctl_install(struct rt_fd_list *fdlist, struct rt_eventpoll *ep rt_slist_append(&ep->rdl_head, &fdlist->rdl_node); fdlist->exclusive = 0; fdlist->is_rdl_node = RT_TRUE; - ep->triggered = 1; - ep->eventpoll_num++; + ep->status = RT_EPOLL_STAT_TRIG; + ep->eventpoll_num ++; rt_spin_unlock_irqrestore(&ep->spinlock, level); rt_mutex_release(&ep->lock); } @@ -282,7 +298,7 @@ static void epoll_ctl_install(struct rt_fd_list *fdlist, struct rt_eventpoll *ep */ static void epoll_member_init(struct rt_eventpoll *ep) { - ep->triggered = 0; + ep->status = RT_EPOLL_STAT_INIT; ep->eventpoll_num = 0; ep->polling_thread = rt_thread_self(); ep->fdlist = RT_NULL; @@ -678,7 +694,7 @@ static int epoll_wait_timeout(struct rt_eventpoll *ep, int msec) level = rt_spin_lock_irqsave(&ep->spinlock); - if (timeout != 0 && !ep->triggered) + if (timeout != 0 && ep->status != RT_EPOLL_STAT_TRIG) { if (rt_thread_suspend_with_flag(thread, RT_KILLABLE) == RT_EOK) { @@ -690,15 +706,19 @@ static int epoll_wait_timeout(struct rt_eventpoll *ep, int msec) rt_timer_start(&(thread->thread_timer)); } + ep->status = RT_EPOLL_STAT_WAITING; + rt_spin_unlock_irqrestore(&ep->spinlock, level); rt_schedule(); level = rt_spin_lock_irqsave(&ep->spinlock); + if (ep->status == RT_EPOLL_STAT_WAITING) + ep->status = RT_EPOLL_STAT_INIT; } } - ret = !ep->triggered; + ret = !(ep->status == RT_EPOLL_STAT_TRIG); rt_spin_unlock_irqrestore(&ep->spinlock, level); return ret; @@ -867,7 +887,7 @@ static int epoll_do(struct rt_eventpoll *ep, struct epoll_event *events, int max if (event_num || istimeout) { level = rt_spin_lock_irqsave(&ep->spinlock); - ep->triggered = 0; + ep->status = RT_EPOLL_STAT_INIT; rt_spin_unlock_irqrestore(&ep->spinlock, level); if ((timeout >= 0) || (event_num > 0)) break; diff --git a/components/libc/posix/io/poll/poll.c b/components/libc/posix/io/poll/poll.c index 105727e4b3..2abc1cde6b 100644 --- a/components/libc/posix/io/poll/poll.c +++ b/components/libc/posix/io/poll/poll.c @@ -7,6 +7,12 @@ * Date Author Notes * 2016-12-28 Bernard first version * 2018-03-09 Bernard Add protection for pt->triggered. + * 2023-12-04 Shell Fix return code and error verification + * 2023-12-14 Shell When poll goes to sleep before the waitqueue has added a + * record and finished enumerating all the fd's, it may be + * incorrectly woken up. This is basically because the poll + * mechanism wakeup algorithm does not correctly distinguish + * the current wait state. */ #include <stdint.h> @@ -16,11 +22,16 @@ #include "poll.h" struct rt_poll_node; +enum rt_poll_status { + RT_POLL_STAT_INIT, + RT_POLL_STAT_TRIG, + RT_POLL_STAT_WAITING, +}; struct rt_poll_table { rt_pollreq_t req; - rt_uint32_t triggered; /* the waited thread whether triggered */ + enum rt_poll_status status; /* the waited thread whether triggered */ rt_thread_t polling_thread; struct rt_poll_node *nodes; }; @@ -36,15 +47,25 @@ static RT_DEFINE_SPINLOCK(_spinlock); static int __wqueue_pollwake(struct rt_wqueue_node *wait, void *key) { + rt_ubase_t level; struct rt_poll_node *pn; + int is_waiting; if (key && !((rt_ubase_t)key & wait->key)) return -1; pn = rt_container_of(wait, struct rt_poll_node, wqn); - pn->pt->triggered = 1; - return __wqueue_default_wake(wait, key); + level = rt_spin_lock_irqsave(&_spinlock); + is_waiting = (pn->pt->status == RT_POLL_STAT_WAITING); + + pn->pt->status = RT_POLL_STAT_TRIG; + rt_spin_unlock_irqrestore(&_spinlock, level); + + if (is_waiting) + return __wqueue_default_wake(wait, key); + + return -1; } static void _poll_add(rt_wqueue_t *wq, rt_pollreq_t *req) @@ -71,7 +92,7 @@ static void _poll_add(rt_wqueue_t *wq, rt_pollreq_t *req) static void poll_table_init(struct rt_poll_table *pt) { pt->req._proc = _poll_add; - pt->triggered = 0; + pt->status = RT_POLL_STAT_INIT; pt->nodes = RT_NULL; pt->polling_thread = rt_thread_self(); } @@ -89,7 +110,7 @@ static int poll_wait_timeout(struct rt_poll_table *pt, int msec) level = rt_spin_lock_irqsave(&_spinlock); - if (timeout != 0 && !pt->triggered) + if (timeout != 0 && pt->status != RT_POLL_STAT_TRIG) { if (rt_thread_suspend_with_flag(thread, RT_INTERRUPTIBLE) == RT_EOK) { @@ -99,17 +120,31 @@ static int poll_wait_timeout(struct rt_poll_table *pt, int msec) RT_TIMER_CTRL_SET_TIME, &timeout); rt_timer_start(&(thread->thread_timer)); + rt_set_errno(RT_ETIMEOUT); } - + else + { + rt_set_errno(0); + } + pt->status = RT_POLL_STAT_WAITING; rt_spin_unlock_irqrestore(&_spinlock, level); rt_schedule(); level = rt_spin_lock_irqsave(&_spinlock); + if (pt->status == RT_POLL_STAT_WAITING) + pt->status = RT_POLL_STAT_INIT; } } - ret = !pt->triggered; + ret = rt_get_errno(); + if (ret == RT_EINTR) + ret = -RT_EINTR; + else if (pt->status == RT_POLL_STAT_TRIG) + ret = RT_EOK; + else + ret = -RT_ETIMEOUT; + rt_spin_unlock_irqrestore(&_spinlock, level); return ret; @@ -170,7 +205,7 @@ static int poll_do(struct pollfd *fds, nfds_t nfds, struct rt_poll_table *pt, in { pf = fds; num = 0; - pt->triggered = 0; + pt->status = RT_POLL_STAT_INIT; for (n = 0; n < nfds; n ++) { @@ -194,8 +229,13 @@ static int poll_do(struct pollfd *fds, nfds_t nfds, struct rt_poll_table *pt, in if (num || istimeout) break; - if (poll_wait_timeout(pt, msec)) + ret = poll_wait_timeout(pt, msec); + if (ret == -RT_EINTR) + return -EINTR; + else if (ret == -RT_ETIMEOUT) istimeout = 1; + else + istimeout = 0; } return num; diff --git a/components/libc/posix/io/termios/termios.h b/components/libc/posix/io/termios/termios.h index 4a504daa7d..884159ae2e 100644 --- a/components/libc/posix/io/termios/termios.h +++ b/components/libc/posix/io/termios/termios.h @@ -36,6 +36,20 @@ struct termios { speed_t __c_ospeed; }; +#ifndef NCC +#define NCC 8 + +struct termio +{ + unsigned short c_iflag; /* input mode flags */ + unsigned short c_oflag; /* output mode flags */ + unsigned short c_cflag; /* control mode flags */ + unsigned short c_lflag; /* local mode flags */ + unsigned char c_line; /* line discipline */ + unsigned char c_cc[NCC]; /* control characters */ +}; +#endif + /* c_cc characters */ #define VINTR 0 #define VQUIT 1 |
