Kernel/LibC: Implement super basic select
This does not really even block but it works... :D
This commit is contained in:
parent
f50b4be162
commit
3fc1edede0
|
@ -21,6 +21,10 @@ namespace Kernel
|
|||
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override { return 0; }
|
||||
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan buffer) override;
|
||||
|
||||
virtual bool can_read_impl() const override { return false; }
|
||||
virtual bool can_write_impl() const override { return true; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
const dev_t m_rdev;
|
||||
};
|
||||
|
|
|
@ -30,6 +30,10 @@ namespace Kernel
|
|||
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
|
||||
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
|
||||
|
||||
virtual bool can_read_impl() const override { return true; }
|
||||
virtual bool can_write_impl() const override { return true; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
FramebufferDevice(mode_t mode, uid_t uid, gid_t gid, dev_t rdev, paddr_t paddr, uint32_t width, uint32_t height, uint32_t pitch, uint8_t bpp);
|
||||
BAN::ErrorOr<void> initialize();
|
||||
|
|
|
@ -23,6 +23,10 @@ namespace Kernel
|
|||
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override { return 0; }
|
||||
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan buffer) override { return buffer.size(); };
|
||||
|
||||
virtual bool can_read_impl() const override { return false; }
|
||||
virtual bool can_write_impl() const override { return true; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
const dev_t m_rdev;
|
||||
};
|
||||
|
|
|
@ -21,6 +21,10 @@ namespace Kernel
|
|||
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
|
||||
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan buffer) override { return buffer.size(); };
|
||||
|
||||
virtual bool can_read_impl() const override { return true; }
|
||||
virtual bool can_write_impl() const override { return false; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
const dev_t m_rdev;
|
||||
};
|
||||
|
|
|
@ -43,6 +43,10 @@ namespace Kernel
|
|||
virtual BAN::ErrorOr<void> truncate_impl(size_t) override;
|
||||
virtual BAN::ErrorOr<void> chmod_impl(mode_t) override;
|
||||
|
||||
virtual bool can_read_impl() const override { return true; }
|
||||
virtual bool can_write_impl() const override { return true; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
// Returns maximum number of data blocks in use
|
||||
// NOTE: the inode might have more blocks than what this suggests if it has been shrinked
|
||||
|
|
|
@ -113,7 +113,11 @@ namespace Kernel
|
|||
BAN::ErrorOr<void> truncate(size_t);
|
||||
BAN::ErrorOr<void> chmod(mode_t);
|
||||
BAN::ErrorOr<void> chown(uid_t, gid_t);
|
||||
bool has_data() const;
|
||||
|
||||
// Select/Non blocking API
|
||||
bool can_read() const;
|
||||
bool can_write() const;
|
||||
bool has_error() const;
|
||||
|
||||
BAN::ErrorOr<long> ioctl(int request, void* arg);
|
||||
|
||||
|
@ -144,7 +148,11 @@ namespace Kernel
|
|||
virtual BAN::ErrorOr<void> truncate_impl(size_t) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<void> chmod_impl(mode_t) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<void> chown_impl(uid_t, gid_t) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual bool has_data_impl() const { dwarnln("nonblock not supported"); return true; }
|
||||
|
||||
// Select/Non blocking API
|
||||
virtual bool can_read_impl() const = 0;
|
||||
virtual bool can_write_impl() const = 0;
|
||||
virtual bool has_error_impl() const = 0;
|
||||
|
||||
virtual BAN::ErrorOr<long> ioctl_impl(int request, void* arg) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
|
||||
|
|
|
@ -34,6 +34,10 @@ namespace Kernel
|
|||
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
|
||||
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
|
||||
|
||||
virtual bool can_read_impl() const override { return !m_buffer.empty(); }
|
||||
virtual bool can_write_impl() const override { return true; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
Pipe(const Credentials&);
|
||||
|
||||
|
|
|
@ -43,7 +43,10 @@ namespace Kernel
|
|||
// You may not write here and this is always non blocking
|
||||
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override { return BAN::Error::from_errno(EINVAL); }
|
||||
virtual BAN::ErrorOr<void> truncate_impl(size_t) override { return BAN::Error::from_errno(EINVAL); }
|
||||
virtual bool has_data_impl() const override { return true; }
|
||||
|
||||
virtual bool can_read_impl() const override { return true; }
|
||||
virtual bool can_write_impl() const override { return false; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
ProcROInode(Process&, size_t (Process::*)(off_t, BAN::ByteSpan) const, TmpFileSystem&, const TmpInodeInfo&);
|
||||
|
|
|
@ -72,7 +72,10 @@ namespace Kernel
|
|||
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
|
||||
virtual BAN::ErrorOr<void> truncate_impl(size_t) override;
|
||||
virtual BAN::ErrorOr<void> chmod_impl(mode_t) override;
|
||||
virtual bool has_data_impl() const override { return true; }
|
||||
|
||||
virtual bool can_read_impl() const override { return true; }
|
||||
virtual bool can_write_impl() const override { return true; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
TmpFileInode(TmpFileSystem&, ino_t, const TmpInodeInfo&);
|
||||
|
@ -91,7 +94,10 @@ namespace Kernel
|
|||
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override { return BAN::Error::from_errno(ENODEV); }
|
||||
virtual BAN::ErrorOr<void> truncate_impl(size_t) override { return BAN::Error::from_errno(ENODEV); }
|
||||
virtual BAN::ErrorOr<void> chmod_impl(mode_t) override;
|
||||
virtual bool has_data_impl() const override { return true; }
|
||||
|
||||
virtual bool can_read_impl() const override { return false; }
|
||||
virtual bool can_write_impl() const override { return false; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
TmpSocketInode(TmpFileSystem&, ino_t, const TmpInodeInfo&);
|
||||
|
@ -110,6 +116,10 @@ namespace Kernel
|
|||
protected:
|
||||
virtual BAN::ErrorOr<BAN::String> link_target_impl() override;
|
||||
|
||||
virtual bool can_read_impl() const override { return false; }
|
||||
virtual bool can_write_impl() const override { return false; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
TmpSymlinkInode(TmpFileSystem&, ino_t, const TmpInodeInfo&);
|
||||
};
|
||||
|
@ -136,6 +146,10 @@ namespace Kernel
|
|||
virtual BAN::ErrorOr<void> create_directory_impl(BAN::StringView, mode_t, uid_t, gid_t) override final;
|
||||
virtual BAN::ErrorOr<void> unlink_impl(BAN::StringView) override;
|
||||
|
||||
virtual bool can_read_impl() const override { return false; }
|
||||
virtual bool can_write_impl() const override { return false; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
template<TmpFuncs::for_each_valid_entry_callback F>
|
||||
void for_each_valid_entry(F callback);
|
||||
|
|
|
@ -48,7 +48,10 @@ namespace Kernel::Input
|
|||
|
||||
protected:
|
||||
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
|
||||
virtual bool has_data_impl() const override;
|
||||
|
||||
virtual bool can_read_impl() const override { return !m_event_queue.empty(); }
|
||||
virtual bool can_write_impl() const override { return false; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -42,7 +42,10 @@ namespace Kernel::Input
|
|||
|
||||
protected:
|
||||
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
|
||||
virtual bool has_data_impl() const override;
|
||||
|
||||
virtual bool can_read_impl() const override { return !m_event_queue.empty(); }
|
||||
virtual bool can_write_impl() const override { return false; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -46,6 +46,10 @@ namespace Kernel
|
|||
|
||||
virtual BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::ConstByteSpan) override;
|
||||
|
||||
virtual bool can_read_impl() const override { return false; }
|
||||
virtual bool can_write_impl() const override { return false; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
BAN::ErrorOr<void> read_mac_address();
|
||||
|
||||
|
|
|
@ -57,6 +57,10 @@ namespace Kernel
|
|||
virtual BAN::ErrorOr<size_t> sendto_impl(BAN::ConstByteSpan message, const sockaddr* address, socklen_t address_len) override;
|
||||
virtual BAN::ErrorOr<size_t> recvfrom_impl(BAN::ByteSpan message, sockaddr* address, socklen_t* address_len) override;
|
||||
|
||||
virtual bool can_read_impl() const override { return m_recv_window.data_size; }
|
||||
virtual bool can_write_impl() const override { return m_state == State::Established; }
|
||||
virtual bool has_error_impl() const override { return m_state != State::Established && m_state != State::Listen && m_state != State::SynSent && m_state != State::SynReceived; }
|
||||
|
||||
private:
|
||||
enum class State
|
||||
{
|
||||
|
|
|
@ -38,6 +38,10 @@ namespace Kernel
|
|||
virtual BAN::ErrorOr<size_t> sendto_impl(BAN::ConstByteSpan message, const sockaddr* address, socklen_t address_len) override;
|
||||
virtual BAN::ErrorOr<size_t> recvfrom_impl(BAN::ByteSpan buffer, sockaddr* address, socklen_t* address_len) override;
|
||||
|
||||
virtual bool can_read_impl() const override { return !m_packets.empty(); }
|
||||
virtual bool can_write_impl() const override { return true; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
UDPSocket(NetworkLayer&, ino_t, const TmpInodeInfo&);
|
||||
|
||||
|
|
|
@ -26,6 +26,10 @@ namespace Kernel
|
|||
virtual BAN::ErrorOr<size_t> sendto_impl(BAN::ConstByteSpan, const sockaddr*, socklen_t) override;
|
||||
virtual BAN::ErrorOr<size_t> recvfrom_impl(BAN::ByteSpan, sockaddr*, socklen_t*) override;
|
||||
|
||||
virtual bool can_read_impl() const override;
|
||||
virtual bool can_write_impl() const override;
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
UnixDomainSocket(SocketType, ino_t, const TmpInodeInfo&);
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include <sys/banan-os.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/socket.h>
|
||||
#include <termios.h>
|
||||
|
||||
|
@ -126,6 +127,8 @@ namespace Kernel
|
|||
|
||||
BAN::ErrorOr<long> sys_ioctl(int fildes, int request, void* arg);
|
||||
|
||||
BAN::ErrorOr<long> sys_pselect(sys_pselect_t* arguments);
|
||||
|
||||
BAN::ErrorOr<long> sys_pipe(int fildes[2]);
|
||||
BAN::ErrorOr<long> sys_dup(int fildes);
|
||||
BAN::ErrorOr<long> sys_dup2(int fildes, int fildes2);
|
||||
|
|
|
@ -24,6 +24,11 @@ namespace Kernel
|
|||
virtual dev_t rdev() const override { return m_rdev; }
|
||||
virtual BAN::StringView name() const override { return m_name; }
|
||||
|
||||
protected:
|
||||
virtual bool can_read_impl() const override { return false; }
|
||||
virtual bool can_write_impl() const override { return false; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
NVMeController(PCI::Device& pci_device);
|
||||
virtual BAN::ErrorOr<void> initialize() override;
|
||||
|
|
|
@ -46,6 +46,10 @@ namespace Kernel
|
|||
protected:
|
||||
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
|
||||
|
||||
virtual bool can_read_impl() const override { return true; }
|
||||
virtual bool can_write_impl() const override { return true; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
const dev_t m_rdev;
|
||||
};
|
||||
|
|
|
@ -39,6 +39,10 @@ namespace Kernel
|
|||
virtual BAN::ErrorOr<void> write_sectors_impl(uint64_t lba, uint64_t sector_count, BAN::ConstByteSpan) = 0;
|
||||
void add_disk_cache();
|
||||
|
||||
virtual bool can_read_impl() const override { return true; }
|
||||
virtual bool can_write_impl() const override { return true; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
SpinLock m_lock;
|
||||
BAN::Optional<DiskCache> m_disk_cache;
|
||||
|
|
|
@ -44,7 +44,9 @@ namespace Kernel
|
|||
virtual BAN::ErrorOr<void> chmod_impl(mode_t) override;
|
||||
virtual BAN::ErrorOr<void> chown_impl(uid_t, gid_t) override;
|
||||
|
||||
virtual bool has_data_impl() const override;
|
||||
virtual bool can_read_impl() const override { return m_output.flush; }
|
||||
virtual bool can_write_impl() const override { return true; }
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
|
||||
protected:
|
||||
TTY(mode_t mode, uid_t uid, gid_t gid)
|
||||
|
|
|
@ -201,10 +201,22 @@ namespace Kernel
|
|||
return chown_impl(uid, gid);
|
||||
}
|
||||
|
||||
bool Inode::has_data() const
|
||||
bool Inode::can_read() const
|
||||
{
|
||||
LockGuard _(m_lock);
|
||||
return has_data_impl();
|
||||
return can_read_impl();
|
||||
}
|
||||
|
||||
bool Inode::can_write() const
|
||||
{
|
||||
LockGuard _(m_lock);
|
||||
return can_write_impl();
|
||||
}
|
||||
|
||||
bool Inode::has_error() const
|
||||
{
|
||||
LockGuard _(m_lock);
|
||||
return has_error_impl();
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> Inode::ioctl(int request, void* arg)
|
||||
|
|
|
@ -208,10 +208,4 @@ namespace Kernel::Input
|
|||
}
|
||||
}
|
||||
|
||||
bool PS2Keyboard::has_data_impl() const
|
||||
{
|
||||
CriticalScope _;
|
||||
return !m_event_queue.empty();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -192,10 +192,4 @@ namespace Kernel::Input
|
|||
}
|
||||
}
|
||||
|
||||
bool PS2Mouse::has_data_impl() const
|
||||
{
|
||||
CriticalScope _;
|
||||
return !m_event_queue.empty();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -248,6 +248,29 @@ namespace Kernel
|
|||
return {};
|
||||
}
|
||||
|
||||
bool UnixDomainSocket::can_read_impl() const
|
||||
{
|
||||
if (m_info.has<ConnectionInfo>())
|
||||
{
|
||||
auto& connection_info = m_info.get<ConnectionInfo>();
|
||||
if (!connection_info.connection)
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_packet_size_total > 0;
|
||||
}
|
||||
|
||||
bool UnixDomainSocket::can_write_impl() const
|
||||
{
|
||||
if (m_info.has<ConnectionInfo>())
|
||||
{
|
||||
auto& connection_info = m_info.get<ConnectionInfo>();
|
||||
return connection_info.connection.valid();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<size_t> UnixDomainSocket::sendto_impl(BAN::ConstByteSpan message, const sockaddr* address, socklen_t address_len)
|
||||
{
|
||||
if (message.size() > s_packet_buffer_size)
|
||||
|
|
|
@ -331,7 +331,7 @@ namespace Kernel
|
|||
{
|
||||
TRY(validate_fd(fd));
|
||||
auto& open_file = m_open_files[fd];
|
||||
if ((open_file->flags & O_NONBLOCK) && !open_file->inode->has_data())
|
||||
if ((open_file->flags & O_NONBLOCK) && !open_file->inode->can_read())
|
||||
return 0;
|
||||
size_t nread = TRY(open_file->inode->read(open_file->offset, buffer));
|
||||
open_file->offset += nread;
|
||||
|
@ -342,6 +342,8 @@ namespace Kernel
|
|||
{
|
||||
TRY(validate_fd(fd));
|
||||
auto& open_file = m_open_files[fd];
|
||||
if ((open_file->flags & O_NONBLOCK) && !open_file->inode->can_write())
|
||||
return 0;
|
||||
if (open_file->flags & O_APPEND)
|
||||
open_file->offset = open_file->inode->size();
|
||||
size_t nwrite = TRY(open_file->inode->write(open_file->offset, buffer));
|
||||
|
|
|
@ -1018,6 +1018,86 @@ namespace Kernel
|
|||
return TRY(inode->ioctl(request, arg));
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> Process::sys_pselect(sys_pselect_t* arguments)
|
||||
{
|
||||
LockGuard _(m_lock);
|
||||
|
||||
TRY(validate_pointer_access(arguments, sizeof(sys_pselect_t)));
|
||||
if (arguments->readfds)
|
||||
TRY(validate_pointer_access(arguments->readfds, sizeof(fd_set)));
|
||||
if (arguments->writefds)
|
||||
TRY(validate_pointer_access(arguments->writefds, sizeof(fd_set)));
|
||||
if (arguments->errorfds)
|
||||
TRY(validate_pointer_access(arguments->errorfds, sizeof(fd_set)));
|
||||
if (arguments->timeout)
|
||||
TRY(validate_pointer_access(arguments->timeout, sizeof(timespec)));
|
||||
if (arguments->sigmask)
|
||||
TRY(validate_pointer_access(arguments->sigmask, sizeof(sigset_t)));
|
||||
|
||||
if (arguments->sigmask)
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
|
||||
uint64_t timedout_ms = SystemTimer::get().ms_since_boot();
|
||||
if (arguments->timeout)
|
||||
{
|
||||
timedout_ms += arguments->timeout->tv_sec * 1000;
|
||||
timedout_ms += arguments->timeout->tv_nsec / 1'000'000;
|
||||
}
|
||||
|
||||
fd_set readfds; FD_ZERO(&readfds);
|
||||
fd_set writefds; FD_ZERO(&writefds);
|
||||
fd_set errorfds; FD_ZERO(&errorfds);
|
||||
|
||||
long set_bits = 0;
|
||||
while (set_bits == 0)
|
||||
{
|
||||
if (arguments->timeout && SystemTimer::get().ms_since_boot() >= timedout_ms)
|
||||
break;
|
||||
|
||||
auto update_fds =
|
||||
[&](int fd, fd_set* source, fd_set* dest, bool (Inode::*func)() const)
|
||||
{
|
||||
if (source == nullptr)
|
||||
return;
|
||||
|
||||
if (!FD_ISSET(fd, source))
|
||||
return;
|
||||
|
||||
auto inode_or_error = m_open_file_descriptors.inode_of(fd);
|
||||
if (inode_or_error.is_error())
|
||||
return;
|
||||
|
||||
auto inode = inode_or_error.release_value();
|
||||
auto mode = inode->mode();
|
||||
if (!mode.ifreg() && !mode.ififo() && !mode.ifsock() && !inode->is_pipe() && !inode->is_tty())
|
||||
return;
|
||||
|
||||
if ((inode_or_error.value().ptr()->*func)())
|
||||
{
|
||||
FD_SET(fd, dest);
|
||||
set_bits++;
|
||||
}
|
||||
};
|
||||
|
||||
for (int i = 0; i < arguments->nfds; i++)
|
||||
{
|
||||
update_fds(i, arguments->readfds, &readfds, &Inode::can_read);
|
||||
update_fds(i, arguments->writefds, &writefds, &Inode::can_write);
|
||||
update_fds(i, arguments->errorfds, &errorfds, &Inode::can_read);
|
||||
}
|
||||
|
||||
SystemTimer::get().sleep(1);
|
||||
}
|
||||
|
||||
if (arguments->readfds)
|
||||
memcpy(arguments->readfds, &readfds, sizeof(fd_set));
|
||||
if (arguments->writefds)
|
||||
memcpy(arguments->writefds, &writefds, sizeof(fd_set));
|
||||
if (arguments->errorfds)
|
||||
memcpy(arguments->errorfds, &errorfds, sizeof(fd_set));
|
||||
return set_bits;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> Process::sys_pipe(int fildes[2])
|
||||
{
|
||||
LockGuard _(m_lock);
|
||||
|
|
|
@ -237,6 +237,9 @@ namespace Kernel
|
|||
case SYS_LISTEN:
|
||||
ret = Process::current().sys_listen((int)arg1, (int)arg2);
|
||||
break;
|
||||
case SYS_PSELECT:
|
||||
ret = Process::current().sys_pselect((sys_pselect_t*)arg1);
|
||||
break;
|
||||
default:
|
||||
dwarnln("Unknown syscall {}", syscall);
|
||||
break;
|
||||
|
|
|
@ -358,12 +358,6 @@ namespace Kernel
|
|||
return buffer.size();
|
||||
}
|
||||
|
||||
bool TTY::has_data_impl() const
|
||||
{
|
||||
LockGuard _(m_lock);
|
||||
return m_output.flush;
|
||||
}
|
||||
|
||||
void TTY::putchar_current(uint8_t ch)
|
||||
{
|
||||
ASSERT(s_tty);
|
||||
|
|
|
@ -21,6 +21,7 @@ set(LIBC_SOURCES
|
|||
stropts.cpp
|
||||
sys/banan-os.cpp
|
||||
sys/mman.cpp
|
||||
sys/select.cpp
|
||||
sys/socket.cpp
|
||||
sys/stat.cpp
|
||||
sys/wait.cpp
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
#ifndef _BITS_TIMEVAL_H
|
||||
#define _BITS_TIMEVAL_H 1
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
#define __need_time_t
|
||||
#define __need_suseconds_t
|
||||
#include <sys/types.h>
|
||||
|
||||
struct timeval
|
||||
{
|
||||
time_t tv_sec; /* Seconds. */
|
||||
suseconds_t tc_usec; /* Microseconds. */
|
||||
};
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif
|
|
@ -7,9 +7,7 @@
|
|||
|
||||
__BEGIN_DECLS
|
||||
|
||||
#define __need_time_t
|
||||
#define __need_suseconds_t
|
||||
#include <sys/types.h>
|
||||
#include <bits/types/timeval.h>
|
||||
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
|
@ -50,6 +48,16 @@ typedef struct {
|
|||
(setp)->__bits[i] = (__fd_mask)0; \
|
||||
} while (0)
|
||||
|
||||
struct sys_pselect_t
|
||||
{
|
||||
int nfds;
|
||||
fd_set* readfds;
|
||||
fd_set* writefds;
|
||||
fd_set* errorfds;
|
||||
const struct timespec* timeout;
|
||||
const sigset_t* sigmask;
|
||||
};
|
||||
|
||||
int pselect(int nfds, fd_set* __restrict readfds, fd_set* __restrict writefds, fd_set* __restrict errorfds, const struct timespec* __restrict timeout, const sigset_t* __restrict sigmask);
|
||||
int select(int nfds, fd_set* __restrict readfds, fd_set* __restrict writefds, fd_set* __restrict errorfds, struct timeval* __restrict timeout);
|
||||
|
||||
|
|
|
@ -71,6 +71,7 @@ __BEGIN_DECLS
|
|||
#define SYS_ACCEPT 70
|
||||
#define SYS_CONNECT 71
|
||||
#define SYS_LISTEN 72
|
||||
#define SYS_PSELECT 73
|
||||
|
||||
__END_DECLS
|
||||
|
||||
|
|
|
@ -7,18 +7,10 @@
|
|||
|
||||
__BEGIN_DECLS
|
||||
|
||||
#define __need_time_t
|
||||
#define __need_suseconds_t
|
||||
#include <sys/types.h>
|
||||
|
||||
// NOTE: select is declared from here
|
||||
#include <sys/select.h>
|
||||
|
||||
struct timeval
|
||||
{
|
||||
time_t tv_sec; /* Seconds. */
|
||||
suseconds_t tc_usec; /* Microseconds. */
|
||||
};
|
||||
#include <bits/types/timeval.h>
|
||||
|
||||
struct itimerval
|
||||
{
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
#include <sys/select.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int pselect(int nfds, fd_set* __restrict readfds, fd_set* __restrict writefds, fd_set* __restrict errorfds, const struct timespec* __restrict timeout, const sigset_t* __restrict sigmask)
|
||||
{
|
||||
sys_pselect_t arguments {
|
||||
.nfds = nfds,
|
||||
.readfds = readfds,
|
||||
.writefds = writefds,
|
||||
.errorfds = errorfds,
|
||||
.timeout = timeout,
|
||||
.sigmask = sigmask
|
||||
};
|
||||
return syscall(SYS_PSELECT, &arguments);
|
||||
}
|
||||
|
||||
int select(int nfds, fd_set* __restrict readfds, fd_set* __restrict writefds, fd_set* __restrict errorfds, struct timeval* __restrict timeout)
|
||||
{
|
||||
timespec* pts = nullptr;
|
||||
timespec ts;
|
||||
if (timeout)
|
||||
{
|
||||
ts.tv_sec = timeout->tv_sec;
|
||||
ts.tv_nsec = timeout->tc_usec * 1000;
|
||||
pts = &ts;
|
||||
}
|
||||
|
||||
// TODO: "select may update timeout", should we?
|
||||
return pselect(nfds, readfds, writefds, errorfds, pts, nullptr);
|
||||
}
|
Loading…
Reference in New Issue