2023-08-02 15:18:38 +00:00
|
|
|
#include "Log.h"
|
2023-08-12 19:38:25 +00:00
|
|
|
#include "Pledge.h"
|
2023-08-02 12:48:20 +00:00
|
|
|
#include "fs/VFS.h"
|
|
|
|
#include "memory/MemoryManager.h"
|
|
|
|
#include "sys/Syscall.h"
|
|
|
|
#include "thread/Scheduler.h"
|
|
|
|
#include <bits/poll.h>
|
|
|
|
|
2023-08-08 08:41:46 +00:00
|
|
|
Result<u64> sys_poll(Registers*, SyscallArgs args)
|
2023-08-02 12:48:20 +00:00
|
|
|
{
|
|
|
|
struct pollfd* fds = (struct pollfd*)args[0];
|
|
|
|
nfds_t nfds = (nfds_t)args[1];
|
|
|
|
int timeout = (int)args[2];
|
|
|
|
|
2023-08-27 18:48:33 +00:00
|
|
|
struct pollfd* kfds = (struct pollfd*)TRY(malloc_impl(nfds * sizeof(pollfd), false, false));
|
2023-08-02 12:48:20 +00:00
|
|
|
auto guard = make_scope_guard([kfds] { free_impl(kfds); });
|
|
|
|
|
|
|
|
if (!MemoryManager::copy_from_user(fds, kfds, nfds * sizeof(pollfd))) return err(EFAULT);
|
|
|
|
|
|
|
|
auto* current = Scheduler::current();
|
2023-08-12 19:38:25 +00:00
|
|
|
TRY(check_pledge(current, Promise::p_stdio));
|
2023-08-02 12:48:20 +00:00
|
|
|
|
2023-08-22 09:54:00 +00:00
|
|
|
Vector<SharedPtr<VFS::Inode>> inodes;
|
|
|
|
TRY(inodes.try_reserve(nfds));
|
|
|
|
|
2023-08-02 12:48:20 +00:00
|
|
|
for (nfds_t i = 0; i < nfds; i++)
|
|
|
|
{
|
|
|
|
int fd = kfds[i].fd;
|
|
|
|
auto maybe_inode = current->resolve_fd(fd);
|
|
|
|
if (maybe_inode.has_error())
|
|
|
|
{
|
2023-08-02 15:18:38 +00:00
|
|
|
kwarnln("poll: fd %lu (%d) is not valid, storing POLLNVAL", i, fd);
|
2023-08-02 12:48:20 +00:00
|
|
|
kfds[i].revents |= POLLNVAL;
|
|
|
|
TRY(inodes.try_append({}));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
TRY(inodes.try_append(maybe_inode.release_value()->description->inode));
|
|
|
|
}
|
|
|
|
|
|
|
|
bool infinite = timeout < 0;
|
2023-08-02 15:18:38 +00:00
|
|
|
nfds_t fds_with_events;
|
2023-08-02 12:48:20 +00:00
|
|
|
|
|
|
|
do {
|
|
|
|
fds_with_events = 0;
|
|
|
|
for (nfds_t i = 0; i < nfds; i++)
|
|
|
|
{
|
|
|
|
auto& inode = inodes[i];
|
|
|
|
if (!inode) continue;
|
|
|
|
|
|
|
|
if (kfds[i].events & POLLIN && !inode->will_block_if_read())
|
|
|
|
{
|
|
|
|
fds_with_events++;
|
|
|
|
kfds[i].revents |= POLLIN;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!fds_with_events && (timeout > 0 || infinite))
|
|
|
|
{
|
|
|
|
kernel_sleep(10);
|
2023-08-02 15:18:38 +00:00
|
|
|
timeout -= (10 - (int)current->sleep_ticks_left);
|
2023-08-02 12:48:20 +00:00
|
|
|
if (current->interrupted)
|
|
|
|
{
|
|
|
|
guard.deactivate();
|
|
|
|
free_impl(kfds);
|
|
|
|
return err(EINTR);
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
2023-08-02 15:18:38 +00:00
|
|
|
|
|
|
|
break;
|
|
|
|
} while (1);
|
2023-08-02 12:48:20 +00:00
|
|
|
|
|
|
|
MemoryManager::copy_to_user(fds, kfds, nfds * sizeof(pollfd));
|
|
|
|
|
|
|
|
return fds_with_events;
|
|
|
|
}
|