diff --git a/userspace/libraries/LibC/CMakeLists.txt b/userspace/libraries/LibC/CMakeLists.txt index 8f4f73f5..271f0629 100644 --- a/userspace/libraries/LibC/CMakeLists.txt +++ b/userspace/libraries/LibC/CMakeLists.txt @@ -12,6 +12,7 @@ set(LIBC_SOURCES malloc.cpp math.cpp netdb.cpp + poll.cpp printf_impl.cpp pwd.cpp scanf_impl.cpp diff --git a/userspace/libraries/LibC/poll.cpp b/userspace/libraries/LibC/poll.cpp new file mode 100644 index 00000000..db9d8a28 --- /dev/null +++ b/userspace/libraries/LibC/poll.cpp @@ -0,0 +1,56 @@ +#include +#include + +int poll(struct pollfd fds[], nfds_t nfds, int timeout) +{ + fd_set rfds, wfds, efds; + FD_ZERO(&rfds); + FD_ZERO(&wfds); + FD_ZERO(&efds); + + for (nfds_t i = 0; i < nfds; i++) + fds[i].revents = 0; + + constexpr short rmask = POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI | POLLHUP; + constexpr short wmask = POLLOUT | POLLWRNORM | POLLWRBAND; + constexpr short emask = POLLERR; + + int max_fd = 0; + for (nfds_t i = 0; i < nfds; i++) + { + if (fds[i].fd < 0) + continue; + + if (fds[i].events & rmask) + FD_SET(fds[i].fd, &rfds); + if (fds[i].events & wmask) + FD_SET(fds[i].fd, &wfds); + if (fds[i].events & emask) + FD_SET(fds[i].fd, &efds); + + if (fds[i].fd > max_fd) + max_fd = fds[i].fd; + } + + timeval tv; + tv.tv_sec = timeout / 1000; + tv.tv_usec = timeout % 1000 * 1000; + int nselect = select(max_fd + 1, &rfds, &wfds, &efds, &tv); + if (nselect == -1) + return -1; + + for (nfds_t i = 0; i < nfds; i++) + { + if (fds[i].fd < 0) + continue; + + if (FD_ISSET(fds[i].fd, &rfds)) + fds[i].revents |= fds[i].events & rmask; + if (FD_ISSET(fds[i].fd, &wfds)) + fds[i].revents |= fds[i].events & wmask; + if (FD_ISSET(fds[i].fd, &efds)) + fds[i].revents |= fds[i].events & emask; + } + + return nselect; +}