From c6fe3673653706dc780e5a1f37020e046b450ef1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Fri, 18 Jun 2021 20:01:13 +0200 Subject: [PATCH] POSIX: introduce ppoll will appear in the next version: https://www.opengroup.org/austin/docs/austin_1110.pdf Change-Id: I38014ad910881df260f0ec762831491e143328c4 Reviewed-on: https://review.haiku-os.org/c/haiku/+/4099 Tested-by: Commit checker robot Reviewed-by: Adrien Destugues --- headers/posix/poll.h | 18 +++++-- headers/private/kernel/vfs.h | 3 +- headers/private/system/syscalls.h | 2 +- src/system/kernel/wait_for_objects.cpp | 68 +++++++++++++++++--------- src/system/libroot/posix/poll.c | 24 ++++++++- 5 files changed, 87 insertions(+), 28 deletions(-) diff --git a/headers/posix/poll.h b/headers/posix/poll.h index 8935f66fae..b304a9c710 100644 --- a/headers/posix/poll.h +++ b/headers/posix/poll.h @@ -6,6 +6,10 @@ #define _POLL_H +#include +#include + + typedef unsigned long nfds_t; struct pollfd { @@ -29,10 +33,18 @@ struct pollfd { #define POLLNVAL 0x1000 /* invalid file descriptor */ -extern #ifdef __cplusplus -"C" +extern "C" { #endif -int poll(struct pollfd *fds, nfds_t numfds, int timeout); + +extern int poll(struct pollfd *fds, nfds_t numfds, int timeout); +extern int ppoll(struct pollfd *fds, nfds_t numfds, + const struct timespec *timeout, const sigset_t *sigMask); + +#ifdef __cplusplus +} +#endif + + #endif /* _POLL_H */ diff --git a/headers/private/kernel/vfs.h b/headers/private/kernel/vfs.h index 0bbdc82350..30392ed14c 100644 --- a/headers/private/kernel/vfs.h +++ b/headers/private/kernel/vfs.h @@ -211,7 +211,8 @@ status_t _user_access(int fd, const char *path, int mode, bool effectiveUserGroup); ssize_t _user_select(int numfds, fd_set *readSet, fd_set *writeSet, fd_set *errorSet, bigtime_t timeout, const sigset_t *sigMask); -ssize_t _user_poll(struct pollfd *fds, int numfds, bigtime_t timeout); +ssize_t _user_poll(struct pollfd *fds, int numfds, bigtime_t timeout, + const sigset_t *sigMask); int _user_open_attr_dir(int fd, const char *path, bool traverseLeafLink); ssize_t _user_read_attr(int fd, const char *attribute, off_t pos, diff --git a/headers/private/system/syscalls.h b/headers/private/system/syscalls.h index 11e2e200ac..d428c163b1 100644 --- a/headers/private/system/syscalls.h +++ b/headers/private/system/syscalls.h @@ -286,7 +286,7 @@ extern ssize_t _kern_select(int numfds, struct fd_set *readSet, struct fd_set *writeSet, struct fd_set *errorSet, bigtime_t timeout, const sigset_t *sigMask); extern ssize_t _kern_poll(struct pollfd *fds, int numFDs, - bigtime_t timeout); + bigtime_t timeout, const sigset_t *sigMask); extern int _kern_open_attr_dir(int fd, const char *path, bool traverseLeafLink); diff --git a/src/system/kernel/wait_for_objects.cpp b/src/system/kernel/wait_for_objects.cpp index 4eea735e3a..5a4548bb5f 100644 --- a/src/system/kernel/wait_for_objects.cpp +++ b/src/system/kernel/wait_for_objects.cpp @@ -550,7 +550,8 @@ common_select(int numFDs, fd_set *readSet, fd_set *writeSet, fd_set *errorSet, static int -common_poll(struct pollfd *fds, nfds_t numFDs, bigtime_t timeout, bool kernel) +common_poll(struct pollfd *fds, nfds_t numFDs, bigtime_t timeout, + const sigset_t *sigMask, bool kernel) { // allocate sync object select_sync* sync; @@ -580,11 +581,26 @@ common_poll(struct pollfd *fds, nfds_t numFDs, bigtime_t timeout, bool kernel) } } + // set new signal mask + sigset_t oldSigMask; + if (sigMask != NULL) { + sigprocmask(SIG_SETMASK, sigMask, &oldSigMask); + if (!kernel) { + Thread *thread = thread_get_current_thread(); + thread->old_sig_block_mask = oldSigMask; + thread->flags |= THREAD_FLAGS_OLD_SIGMASK; + } + } + if (!invalid) { status = acquire_sem_etc(sync->sem, 1, B_CAN_INTERRUPT | (timeout >= 0 ? B_ABSOLUTE_TIMEOUT : 0), timeout); } + // restore the old signal mask + if (sigMask != NULL && kernel) + sigprocmask(SIG_SETMASK, &oldSigMask, NULL); + // deselect file descriptors for (uint32 i = 0; i < numFDs; i++) { @@ -892,12 +908,13 @@ _kern_select(int numFDs, fd_set *readSet, fd_set *writeSet, fd_set *errorSet, ssize_t -_kern_poll(struct pollfd *fds, int numFDs, bigtime_t timeout) +_kern_poll(struct pollfd *fds, int numFDs, bigtime_t timeout, + const sigset_t *sigMask) { if (timeout >= 0) timeout += system_time(); - return common_poll(fds, numFDs, timeout, true); + return common_poll(fds, numFDs, timeout, sigMask, true); } @@ -1017,10 +1034,12 @@ err: ssize_t -_user_poll(struct pollfd *userfds, int numFDs, bigtime_t timeout) +_user_poll(struct pollfd *userfds, int numFDs, bigtime_t timeout, + const sigset_t *userSigMask) { - struct pollfd *fds; - size_t bytes; + struct pollfd *fds = NULL; + size_t bytes = 0; + sigset_t sigMask; int result; if (timeout >= 0) { @@ -1033,28 +1052,33 @@ _user_poll(struct pollfd *userfds, int numFDs, bigtime_t timeout) if (numFDs < 0) return B_BAD_VALUE; - if (numFDs == 0) { - // special case: no FDs - return common_poll(NULL, 0, timeout, false); + if (numFDs != 0) { + + if (!check_max_fds(numFDs)) + return B_BAD_VALUE; + + if (userfds == NULL || !IS_USER_ADDRESS(userfds)) + return B_BAD_ADDRESS; + + fds = (struct pollfd *)malloc(bytes = numFDs * sizeof(struct pollfd)); + if (fds == NULL) + return B_NO_MEMORY; + + if (user_memcpy(fds, userfds, bytes) < B_OK) { + result = B_BAD_ADDRESS; + goto err; + } } - if (!check_max_fds(numFDs)) - return B_BAD_VALUE; - - // copy parameters - if (userfds == NULL || !IS_USER_ADDRESS(userfds)) - return B_BAD_ADDRESS; - - fds = (struct pollfd *)malloc(bytes = numFDs * sizeof(struct pollfd)); - if (fds == NULL) - return B_NO_MEMORY; - - if (user_memcpy(fds, userfds, bytes) < B_OK) { + if (userSigMask != NULL + && (!IS_USER_ADDRESS(userSigMask) + || user_memcpy(&sigMask, userSigMask, sizeof(sigMask)) < B_OK)) { result = B_BAD_ADDRESS; goto err; } - result = common_poll(fds, numFDs, timeout, false); + result = common_poll(fds, numFDs, timeout, + userSigMask != NULL ? &sigMask : NULL, false); // copy back results if (numFDs > 0 && user_memcpy(userfds, fds, bytes) != 0) { diff --git a/src/system/libroot/posix/poll.c b/src/system/libroot/posix/poll.c index cbd0f37c2c..458683af47 100644 --- a/src/system/libroot/posix/poll.c +++ b/src/system/libroot/posix/poll.c @@ -15,8 +15,30 @@ #include +int __ppoll(struct pollfd *fds, nfds_t numfds, const struct timespec *tv, + const sigset_t *sigMask); + int poll(struct pollfd *fds, nfds_t numfds, int timeout) { - RETURN_AND_SET_ERRNO_TEST_CANCEL(_kern_poll(fds, numfds, timeout * 1000LL)); + RETURN_AND_SET_ERRNO_TEST_CANCEL(_kern_poll(fds, numfds, timeout * 1000LL, + NULL)); } + + +int +__ppoll(struct pollfd *fds, nfds_t numfds, const struct timespec *tv, + const sigset_t *sigMask) +{ + int status; + bigtime_t timeout = -1LL; + if (tv) + timeout = tv->tv_sec * 1000000LL + tv->tv_nsec / 1000LL; + + status = _kern_poll(fds, numfds, timeout, sigMask); + + RETURN_AND_SET_ERRNO_TEST_CANCEL(status); +} + + +B_DEFINE_WEAK_ALIAS(__ppoll, ppoll);