Compare commits

..

No commits in common. "2b48933f2984d95c5bfd46fe330fbe172613e434" and "8392472bacb522c46e3359432b2c8013133e4efe" have entirely different histories.

71 changed files with 492 additions and 2575 deletions

View File

@ -14,7 +14,7 @@
#define dprintln(...) \
do { \
BAN::Formatter::print(__debug_putchar, __VA_ARGS__); \
BAN::Formatter::print(__debug_putchar,"\n"); \
BAN::Formatter::print(__debug_putchar,"\r\n"); \
fflush(stddbg); \
} while (false)
@ -22,7 +22,7 @@
do { \
BAN::Formatter::print(__debug_putchar, "\e[33m"); \
BAN::Formatter::print(__debug_putchar, __VA_ARGS__); \
BAN::Formatter::print(__debug_putchar, "\e[m\n"); \
BAN::Formatter::print(__debug_putchar, "\e[m\r\n"); \
fflush(stddbg); \
} while(false)
@ -30,7 +30,7 @@
do { \
BAN::Formatter::print(__debug_putchar, "\e[31m"); \
BAN::Formatter::print(__debug_putchar, __VA_ARGS__); \
BAN::Formatter::print(__debug_putchar, "\e[m\n"); \
BAN::Formatter::print(__debug_putchar, "\e[m\r\n"); \
fflush(stddbg); \
} while(false)

View File

@ -43,7 +43,6 @@ set(KERNEL_SOURCES
kernel/Interruptable.cpp
kernel/InterruptController.cpp
kernel/kernel.cpp
kernel/Lock/SpinLock.cpp
kernel/Memory/DMARegion.cpp
kernel/Memory/FileBackedRegion.cpp
kernel/Memory/Heap.cpp

View File

@ -1,12 +1,10 @@
#pragma once
#include <BAN/Array.h>
#include <BAN/CircularQueue.h>
#include <BAN/HashMap.h>
#include <BAN/HashSet.h>
#include <kernel/FS/Inode.h>
#include <limits.h>
#include <sys/epoll.h>
namespace Kernel
@ -18,7 +16,7 @@ namespace Kernel
static BAN::ErrorOr<BAN::RefPtr<Epoll>> create();
~Epoll();
BAN::ErrorOr<void> ctl(int op, int fd, BAN::RefPtr<Inode> inode, epoll_event event);
BAN::ErrorOr<void> ctl(int op, BAN::RefPtr<Inode> inode, epoll_event event);
BAN::ErrorOr<size_t> wait(BAN::Span<epoll_event> events, uint64_t waketime_ns);
void notify(BAN::RefPtr<Inode> inode, uint32_t event);
@ -61,45 +59,10 @@ namespace Kernel
}
};
struct ListenEventList
{
BAN::Array<epoll_event, OPEN_MAX> events;
uint32_t bitmap[(OPEN_MAX + 31) / 32] {};
bool has_fd(int fd) const
{
if (fd < 0 || static_cast<size_t>(fd) >= events.size())
return false;
return bitmap[fd / 32] & (1u << (fd % 32));
}
bool empty() const
{
for (auto val : bitmap)
if (val != 0)
return false;
return true;
}
void add_fd(int fd, epoll_event event)
{
ASSERT(!has_fd(fd));
bitmap[fd / 32] |= (1u << (fd % 32));
events[fd] = event;
}
void remove_fd(int fd)
{
ASSERT(has_fd(fd));
bitmap[fd / 32] &= ~(1u << (fd % 32));
events[fd] = {};
}
};
private:
ThreadBlocker m_thread_blocker;
BAN::HashMap<BAN::RefPtr<Inode>, uint32_t, InodeRefPtrHash> m_ready_events;
BAN::HashMap<BAN::RefPtr<Inode>, ListenEventList, InodeRefPtrHash> m_listening_events;
BAN::HashMap<BAN::RefPtr<Inode>, epoll_event, InodeRefPtrHash> m_listening_events;
};
}

View File

@ -46,7 +46,6 @@ 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 BAN::ErrorOr<void> utimens_impl(const timespec[2]) override;
virtual BAN::ErrorOr<void> fsync_impl() override;
virtual bool can_read_impl() const override { return true; }

View File

@ -44,7 +44,6 @@ 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 BAN::ErrorOr<void> utimens_impl(const timespec[2]) override;
virtual BAN::ErrorOr<void> fsync_impl() override { return {}; }
virtual bool can_read_impl() const override { return true; }

View File

@ -119,7 +119,6 @@ namespace Kernel
BAN::ErrorOr<void> truncate(size_t);
BAN::ErrorOr<void> chmod(mode_t);
BAN::ErrorOr<void> chown(uid_t, gid_t);
BAN::ErrorOr<void> utimens(const timespec[2]);
BAN::ErrorOr<void> fsync();
// Select/Non blocking API
@ -166,7 +165,6 @@ 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 BAN::ErrorOr<void> utimens_impl(const timespec[2]) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<void> fsync_impl() = 0;
// Select/Non blocking API
@ -184,7 +182,6 @@ namespace Kernel
BAN::WeakPtr<SharedFileData> m_shared_region;
Mutex m_epoll_mutex;
BAN::LinkedList<class Epoll*> m_epolls;
friend class Epoll;
friend class FileBackedRegion;
friend class OpenFileDescriptorSet;
friend class SharedFileData;

View File

@ -47,8 +47,6 @@ namespace Kernel
protected:
TmpInode(TmpFileSystem&, ino_t, const TmpInodeInfo&);
virtual BAN::ErrorOr<void> chmod_impl(mode_t) override;
virtual BAN::ErrorOr<void> utimens_impl(const timespec[2]) override;
virtual BAN::ErrorOr<void> fsync_impl() override { return {}; }
void sync();
@ -77,6 +75,7 @@ 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 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; }
@ -99,6 +98,7 @@ namespace Kernel
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override { return BAN::Error::from_errno(ENODEV); }
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 can_read_impl() const override { return false; }
virtual bool can_write_impl() const override { return false; }

View File

@ -88,8 +88,6 @@ namespace Kernel
void lock()
{
const auto tid = Thread::current_tid();
ASSERT(!tid || !Thread::current().has_spinlock());
if (tid == m_locker)
ASSERT(m_lock_depth > 0);
else
@ -113,8 +111,6 @@ namespace Kernel
bool try_lock()
{
const auto tid = Thread::current_tid();
ASSERT(!tid || !Thread::current().has_spinlock());
if (tid == m_locker)
ASSERT(m_lock_depth > 0);
else

View File

@ -18,11 +18,42 @@ namespace Kernel
public:
SpinLock() = default;
InterruptState lock();
InterruptState lock()
{
auto state = Processor::get_interrupt_state();
Processor::set_interrupt_state(InterruptState::Disabled);
bool try_lock_interrupts_disabled();
auto id = Processor::current_id().as_u32();
ASSERT(m_locker.load(BAN::MemoryOrder::memory_order_relaxed) != id);
void unlock(InterruptState state);
auto expected = PROCESSOR_NONE.as_u32();
while (!m_locker.compare_exchange(expected, id, BAN::MemoryOrder::memory_order_acquire))
{
Processor::pause();
expected = PROCESSOR_NONE.as_u32();
}
return state;
}
bool try_lock_interrupts_disabled()
{
ASSERT(Processor::get_interrupt_state() == InterruptState::Disabled);
auto id = Processor::current_id().as_u32();
ASSERT(m_locker.load(BAN::MemoryOrder::memory_order_relaxed) != id);
auto expected = PROCESSOR_NONE.as_u32();
return m_locker.compare_exchange(expected, id, BAN::MemoryOrder::memory_order_acquire);
}
void unlock(InterruptState state)
{
ASSERT(Processor::get_interrupt_state() == InterruptState::Disabled);
ASSERT(current_processor_has_lock());
m_locker.store(PROCESSOR_NONE.as_u32(), BAN::MemoryOrder::memory_order_release);
Processor::set_interrupt_state(state);
}
bool current_processor_has_lock() const
{

View File

@ -12,7 +12,6 @@
#error
#endif
#undef PAGE_SIZE
#define PAGE_SIZE ((uintptr_t)4096)
#define PAGE_SIZE_SHIFT 12
#define PAGE_ADDR_MASK (~(uintptr_t)0xFFF)

View File

@ -16,7 +16,6 @@
#include <kernel/Terminal/TTY.h>
#include <kernel/Thread.h>
#include <poll.h>
#include <sys/banan-os.h>
#include <sys/mman.h>
#include <sys/select.h>
@ -107,7 +106,7 @@ namespace Kernel
BAN::ErrorOr<long> sys_access(const char* path, int amode);
BAN::ErrorOr<long> sys_create_dir(const char*, mode_t);
BAN::ErrorOr<long> sys_hardlinkat(int fd1, const char* path1, int fd2, const char* path2, int flag);
BAN::ErrorOr<long> sys_unlinkat(int fd, const char* path, int flag);
BAN::ErrorOr<long> sys_unlink(const char*);
BAN::ErrorOr<long> sys_readlinkat(int fd, const char* path, char* buffer, size_t bufsize);
BAN::ErrorOr<long> sys_symlinkat(const char* path1, int fd, const char* path2);
@ -117,7 +116,6 @@ namespace Kernel
BAN::ErrorOr<long> sys_fchmodat(int fd, const char* path, mode_t mode, int flag);
BAN::ErrorOr<long> sys_fchownat(int fd, const char* path, uid_t uid, gid_t gid, int flag);
BAN::ErrorOr<long> sys_utimensat(int fd, const char* path, const struct timespec times[2], int flag);
BAN::ErrorOr<long> sys_socket(int domain, int type, int protocol);
BAN::ErrorOr<long> sys_socketpair(int domain, int type, int protocol, int socket_vector[2]);
@ -136,7 +134,6 @@ 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_ppoll(pollfd* fds, nfds_t nfds, const timespec* tmp_p, const sigset_t* sigmask);
BAN::ErrorOr<long> sys_epoll_create1(int flags);
BAN::ErrorOr<long> sys_epoll_ctl(int epfd, int op, int fd, struct epoll_event* event);
@ -150,7 +147,7 @@ namespace Kernel
BAN::ErrorOr<long> sys_seek(int fd, off_t offset, int whence);
BAN::ErrorOr<long> sys_tell(int fd);
BAN::ErrorOr<long> sys_ftruncate(int fd, off_t length);
BAN::ErrorOr<long> sys_truncate(int fd, off_t length);
BAN::ErrorOr<long> sys_fsync(int fd);
@ -194,7 +191,6 @@ namespace Kernel
BAN::ErrorOr<long> sys_pthread_exit(void* value);
BAN::ErrorOr<long> sys_pthread_join(pthread_t thread, void** value);
BAN::ErrorOr<long> sys_pthread_self();
BAN::ErrorOr<long> sys_pthread_kill(pthread_t thread, int signal);
BAN::ErrorOr<long> sys_tcgetpgrp(int fd);
BAN::ErrorOr<long> sys_tcsetpgrp(int fd, pid_t pgid);

View File

@ -57,7 +57,7 @@ namespace Kernel
virtual bool has_hungup_impl() const override { return false; }
protected:
TTY(termios termios, mode_t mode, uid_t uid, gid_t gid);
TTY(mode_t mode, uid_t uid, gid_t gid);
virtual bool putchar_impl(uint8_t ch) = 0;
virtual void update_cursor() {}

View File

@ -101,10 +101,6 @@ namespace Kernel
void save_sse();
void load_sse();
void add_spinlock() { m_spinlock_count++; }
void remove_spinlock() { m_spinlock_count--; }
bool has_spinlock() const { return !!m_spinlock_count; }
void add_mutex() { m_mutex_count++; }
void remove_mutex() { m_mutex_count--; }
@ -141,7 +137,6 @@ namespace Kernel
SpinLock m_signal_lock;
static_assert(_SIGMAX < 64);
BAN::Atomic<uint32_t> m_spinlock_count { 0 };
BAN::Atomic<uint32_t> m_mutex_count { 0 };
alignas(16) uint8_t m_sse_storage[512] {};

View File

@ -19,7 +19,7 @@ namespace Kernel
inode->del_epoll(this);
}
BAN::ErrorOr<void> Epoll::ctl(int op, int fd, BAN::RefPtr<Inode> inode, epoll_event event)
BAN::ErrorOr<void> Epoll::ctl(int op, BAN::RefPtr<Inode> inode, epoll_event event)
{
LockGuard _(m_mutex);
@ -28,89 +28,48 @@ namespace Kernel
switch (op)
{
case EPOLL_CTL_ADD:
{
if (it == m_listening_events.end())
it = TRY(m_listening_events.emplace(inode));
if (it->value.has_fd(fd))
if (it != m_listening_events.end())
return BAN::Error::from_errno(EEXIST);
TRY(m_ready_events.reserve(m_listening_events.size()));
TRY(m_listening_events.reserve(m_listening_events.size() + 1));
TRY(m_ready_events.reserve(m_listening_events.size() + 1));
TRY(inode->add_epoll(this));
it->value.add_fd(fd, event);
auto ready_it = m_ready_events.find(inode);
if (ready_it == m_ready_events.end())
ready_it = MUST(m_ready_events.insert(inode, 0));
ready_it->value |= event.events;
MUST(m_listening_events.insert(inode, event));
MUST(m_ready_events.insert(inode, event.events));
return {};
}
case EPOLL_CTL_MOD:
{
if (it == m_listening_events.end())
return BAN::Error::from_errno(ENOENT);
if (!it->value.has_fd(fd))
return BAN::Error::from_errno(ENOENT);
it->value.events[fd] = event;
auto ready_it = m_ready_events.find(inode);
if (ready_it == m_ready_events.end())
ready_it = MUST(m_ready_events.insert(inode, 0));
ready_it->value |= event.events;
MUST(m_ready_events.emplace_or_assign(inode, event.events));
it->value = event;
return {};
}
case EPOLL_CTL_DEL:
{
if (it == m_listening_events.end())
return BAN::Error::from_errno(ENOENT);
if (!it->value.has_fd(fd))
return BAN::Error::from_errno(ENOENT);
it->value.remove_fd(fd);
if (it->value.empty())
{
m_listening_events.remove(it);
m_ready_events.remove(inode);
}
inode->del_epoll(this);
return {};
}
}
return BAN::Error::from_errno(EINVAL);
}
BAN::ErrorOr<size_t> Epoll::wait(BAN::Span<epoll_event> event_span, uint64_t waketime_ns)
{
if (event_span.empty())
return BAN::Error::from_errno(EINVAL);
size_t count = 0;
for (;;)
{
bool failed_lock = false;
{
LockGuard _(m_mutex);
for (auto it = m_ready_events.begin(); it != m_ready_events.end() && count < event_span.size();)
{
auto& [inode, events] = *it;
auto& listen = m_listening_events[inode];
const uint32_t listen_mask = (listen.events & (EPOLLIN | EPOLLOUT)) | EPOLLERR | EPOLLHUP;
uint32_t listen_mask = EPOLLERR | EPOLLHUP;
for (int fd = 0; fd < OPEN_MAX; fd++)
if (listen.has_fd(fd))
listen_mask |= listen.events[fd].events;
events &= listen_mask;
// This prevents a possible deadlock
if (!inode->m_mutex.try_lock())
{
failed_lock = true;
continue;
}
#define CHECK_EVENT_BIT(mask, func) \
if ((events & mask) && !inode->func()) \
events &= ~mask;
@ -120,8 +79,6 @@ namespace Kernel
CHECK_EVENT_BIT(EPOLLHUP, has_hungup);
#undef CHECK_EVENT_BIT
inode->m_mutex.unlock();
if (events == 0)
{
m_ready_events.remove(it);
@ -129,27 +86,16 @@ namespace Kernel
continue;
}
for (int fd = 0; fd < OPEN_MAX && count < event_span.size(); fd++)
{
if (!listen.has_fd(fd))
continue;
auto& listen_event = listen.events[fd];
const auto new_events = listen_event.events & events;
if (new_events == 0)
continue;
event_span[count++] = {
.events = new_events,
.data = listen_event.data,
.events = events,
.data = listen.data,
};
if (listen_event.events & EPOLLONESHOT)
listen_event.events = 0;
// this doesn't work with multiple of the same inode
if (listen_event.events & EPOLLET)
events &= ~new_events;
}
if (listen.events & EPOLLONESHOT)
listen.events = 0;
if (listen.events & EPOLLET)
events &= ~listen_mask;
it++;
}
@ -161,8 +107,6 @@ namespace Kernel
const uint64_t current_ns = SystemTimer::get().ns_since_boot();
if (current_ns >= waketime_ns)
break;
if (failed_lock)
continue;
const uint64_t timeout_ns = BAN::Math::min<uint64_t>(100'000'000, waketime_ns - current_ns);
TRY(Thread::current().block_or_eintr_or_timeout_ns(m_thread_blocker, timeout_ns, false));
}
@ -174,13 +118,18 @@ namespace Kernel
{
LockGuard _(m_mutex);
if (!m_listening_events.contains(inode))
auto listen_it = m_listening_events.find(inode);
if (listen_it == m_listening_events.end())
return;
auto ready_it = m_ready_events.find(inode);
if (ready_it == m_ready_events.end())
ready_it = MUST(m_ready_events.insert(inode, 0));
event &= (listen_it->value.events & (EPOLLIN | EPOLLOUT)) | EPOLLERR | EPOLLHUP;
if (event == 0)
return;
if (auto ready_it = m_ready_events.find(inode); ready_it != m_ready_events.end())
ready_it->value |= event;
else
MUST(m_ready_events.insert(inode, event));
m_thread_blocker.unblock();
}

View File

@ -4,8 +4,6 @@
#include <kernel/FS/Ext2/Inode.h>
#include <kernel/Timer/Timer.h>
#include <sys/stat.h>
namespace Kernel
{
@ -289,28 +287,6 @@ namespace Kernel
return {};
}
BAN::ErrorOr<void> Ext2Inode::utimens_impl(const timespec times[2])
{
const uint32_t old_times[2] {
m_inode.atime,
m_inode.mtime,
};
if (times[0].tv_nsec != UTIME_OMIT)
m_inode.atime = times[0].tv_sec;
if (times[1].tv_nsec != UTIME_OMIT)
m_inode.mtime = times[1].tv_sec;
if (auto ret = sync(); ret.is_error())
{
m_inode.atime = old_times[0];
m_inode.mtime = old_times[1];
return ret.release_error();
}
return {};
}
BAN::ErrorOr<void> Ext2Inode::fsync_impl()
{
for (size_t i = 0; i < max_used_data_block_count(); i++)

View File

@ -231,12 +231,6 @@ namespace Kernel
return chown_impl(uid, gid);
}
BAN::ErrorOr<void> Inode::utimens(const timespec times[2])
{
LockGuard _(m_mutex);
return utimens_impl(times);
}
BAN::ErrorOr<void> Inode::fsync()
{
LockGuard _(m_mutex);

View File

@ -2,8 +2,6 @@
#include <kernel/FS/TmpFS/Inode.h>
#include <kernel/Timer/Timer.h>
#include <sys/stat.h>
namespace Kernel
{
@ -92,23 +90,6 @@ namespace Kernel
m_fs.delete_inode(ino());
}
BAN::ErrorOr<void> TmpInode::chmod_impl(mode_t new_mode)
{
ASSERT(!(new_mode & Mode::TYPE_MASK));
m_inode_info.mode &= ~Mode::TYPE_MASK;
m_inode_info.mode |= new_mode;
return {};
}
BAN::ErrorOr<void> TmpInode::utimens_impl(const timespec times[2])
{
if (times[0].tv_nsec != UTIME_OMIT)
m_inode_info.atime = times[0];
if (times[1].tv_nsec != UTIME_OMIT)
m_inode_info.atime = times[1];
return {};
}
void TmpInode::sync()
{
m_fs.write_inode(m_ino, m_inode_info);
@ -238,6 +219,12 @@ namespace Kernel
return {};
}
BAN::ErrorOr<void> TmpFileInode::chmod_impl(mode_t new_mode)
{
m_inode_info.mode = new_mode;
return {};
}
/* SOCKET INODE */
BAN::ErrorOr<BAN::RefPtr<TmpSocketInode>> TmpSocketInode::create_new(TmpFileSystem& fs, mode_t mode, uid_t uid, gid_t gid)
{
@ -261,6 +248,12 @@ namespace Kernel
{
}
BAN::ErrorOr<void> TmpSocketInode::chmod_impl(mode_t new_mode)
{
m_inode_info.mode = new_mode;
return {};
}
/* SYMLINK INODE */
BAN::ErrorOr<BAN::RefPtr<TmpSymlinkInode>> TmpSymlinkInode::create_new(TmpFileSystem& fs, mode_t mode, uid_t uid, gid_t gid, BAN::StringView target)

View File

@ -1,55 +0,0 @@
#include <kernel/Lock/SpinLock.h>
#include <kernel/Thread.h>
namespace Kernel
{
InterruptState SpinLock::lock()
{
auto state = Processor::get_interrupt_state();
Processor::set_interrupt_state(InterruptState::Disabled);
auto id = Processor::current_id().as_u32();
ASSERT(m_locker.load(BAN::MemoryOrder::memory_order_relaxed) != id);
auto expected = PROCESSOR_NONE.as_u32();
while (!m_locker.compare_exchange(expected, id, BAN::MemoryOrder::memory_order_acquire))
{
Processor::pause();
expected = PROCESSOR_NONE.as_u32();
}
if (Thread::current_tid())
Thread::current().add_spinlock();
return state;
}
bool SpinLock::try_lock_interrupts_disabled()
{
ASSERT(Processor::get_interrupt_state() == InterruptState::Disabled);
auto id = Processor::current_id().as_u32();
ASSERT(m_locker.load(BAN::MemoryOrder::memory_order_relaxed) != id);
auto expected = PROCESSOR_NONE.as_u32();
if (!m_locker.compare_exchange(expected, id, BAN::MemoryOrder::memory_order_acquire))
return false;
if (Thread::current_tid())
Thread::current().add_spinlock();
return true;
}
void SpinLock::unlock(InterruptState state)
{
ASSERT(Processor::get_interrupt_state() == InterruptState::Disabled);
ASSERT(current_processor_has_lock());
m_locker.store(PROCESSOR_NONE.as_u32(), BAN::MemoryOrder::memory_order_release);
if (Thread::current_tid())
Thread::current().remove_spinlock();
Processor::set_interrupt_state(state);
}
}

View File

@ -27,7 +27,9 @@ namespace Kernel
TRY(region->m_dirty_pages.resize(BAN::Math::div_round_up<size_t>(size, PAGE_SIZE)));
LockGuard _(inode->m_mutex);
if (!(region->m_shared_data = inode->m_shared_region.lock()))
if (inode->m_shared_region.valid())
region->m_shared_data = inode->m_shared_region.lock();
else
{
auto shared_data = TRY(BAN::RefPtr<SharedFileData>::create());
TRY(shared_data->pages.resize(BAN::Math::div_round_up<size_t>(inode->size(), PAGE_SIZE)));

View File

@ -281,11 +281,10 @@ namespace Kernel
if (!is_streaming())
m_packet_sizes.push(packet.size());
m_packet_thread_blocker.unblock();
m_packet_lock.unlock(state);
epoll_notify(EPOLLIN);
m_packet_thread_blocker.unblock();
m_packet_lock.unlock(state);
return {};
}

View File

@ -146,17 +146,9 @@ namespace Kernel
auto sock_info = TRY(parse_socket_info(domain, type, protocol));
auto socket = TRY(NetworkManager::get().create_socket(sock_info.domain, sock_info.type, 0777, m_credentials.euid(), m_credentials.egid()));
auto socket_sv = "<socket>"_sv;
if (sock_info.domain == Socket::Domain::UNIX)
socket_sv = "<unix socket>"_sv;
else if (sock_info.type == Socket::Type::STREAM)
socket_sv = "<tcp socket>";
else if (sock_info.type == Socket::Type::DGRAM)
socket_sv = "<udp socket>";
LockGuard _(m_mutex);
int fd = TRY(get_free_fd());
m_open_files[fd].description = TRY(BAN::RefPtr<OpenFileDescription>::create(VirtualFileSystem::File(socket, socket_sv), 0, O_RDWR | sock_info.status_flags));
m_open_files[fd].description = TRY(BAN::RefPtr<OpenFileDescription>::create(VirtualFileSystem::File(socket, "<socket>"_sv), 0, O_RDWR | sock_info.status_flags));
m_open_files[fd].descriptor_flags = sock_info.descriptor_flags;
return fd;
}

View File

@ -415,35 +415,12 @@ namespace Kernel::PCI
const uint8_t irq = get_interrupt(index);
interruptable.set_irq(irq);
const auto disable_msi =
[this]()
{
if (!m_offset_msi.has_value())
return;
uint16_t msg_ctrl = read_word(*m_offset_msi + 0x02);
msg_ctrl &= ~(1u << 0);
write_word(*m_offset_msi + 0x02, msg_ctrl);
};
const auto disable_msi_x =
[this]()
{
if (!m_offset_msi_x.has_value())
return;
uint16_t msg_ctrl = read_word(*m_offset_msi_x + 0x02);
msg_ctrl &= ~(1u << 15); // Disable
write_word(*m_offset_msi_x + 0x02, msg_ctrl);
};
switch (m_interrupt_mechanism)
{
case InterruptMechanism::NONE:
ASSERT_NOT_REACHED();
case InterruptMechanism::PIN:
enable_pin_interrupts();
disable_msi();
disable_msi_x();
if (!InterruptController::get().is_using_apic())
write_byte(PCI_REG_IRQ_LINE, irq);
InterruptController::get().enable_irq(irq);
@ -451,7 +428,6 @@ namespace Kernel::PCI
case InterruptMechanism::MSI:
{
disable_pin_interrupts();
disable_msi_x();
uint16_t msg_ctrl = read_word(*m_offset_msi + 0x02);
msg_ctrl &= ~(0x07 << 4); // Only one interrupt
@ -478,7 +454,6 @@ namespace Kernel::PCI
case InterruptMechanism::MSIX:
{
disable_pin_interrupts();
disable_msi();
uint16_t msg_ctrl = read_word(*m_offset_msi_x + 0x02);
msg_ctrl |= 1 << 15; // Enable

View File

@ -350,12 +350,6 @@ namespace Kernel
.self = reinterpret_cast<struct uthread*>(region->vaddr() + master_size),
.master_tls_addr = reinterpret_cast<void*>(master_addr),
.master_tls_size = master_size,
.cleanup_stack = nullptr,
.id = 0,
.errno_ = 0,
.cancel_type = 0,
.cancel_state = 0,
.canceled = 0,
};
const uintptr_t dtv[2] { 1, region->vaddr() };
@ -1158,19 +1152,12 @@ namespace Kernel
return 0;
}
BAN::ErrorOr<long> Process::sys_unlinkat(int fd, const char* path, int flag)
BAN::ErrorOr<long> Process::sys_unlink(const char* path)
{
if (flag && flag != AT_REMOVEDIR)
return BAN::Error::from_errno(EINVAL);
LockGuard _(m_process_lock);
TRY(validate_string_access(path));
auto [parent, file_name] = TRY(find_parent_file(fd, path, O_WRONLY));
if (TRY(parent.inode->find_inode(file_name))->mode().ifdir() != (flag == AT_REMOVEDIR))
return BAN::Error::from_errno(flag ? EPERM : ENOTDIR);
auto [parent, file_name] = TRY(find_parent_file(AT_FDCWD, path, O_WRONLY));
TRY(parent.inode->unlink(file_name));
return 0;
@ -1275,56 +1262,6 @@ namespace Kernel
return 0;
}
BAN::ErrorOr<long> Process::sys_utimensat(int fd, const char* path, const struct timespec _times[2], int flag)
{
if (flag & ~AT_SYMLINK_NOFOLLOW)
return BAN::Error::from_errno(EINVAL);
if (flag == AT_SYMLINK_NOFOLLOW)
flag = O_NOFOLLOW;
timespec times[2];
const uint64_t current_ns = SystemTimer::get().ns_since_boot();
times[0] = times[1] = timespec {
.tv_sec = static_cast<time_t>(current_ns / 1'000'000),
.tv_nsec = static_cast<long>(current_ns % 1'000'000),
};
if (_times)
{
LockGuard _(m_process_lock);
TRY(validate_pointer_access(_times, sizeof(timespec) * 2, false));
if (_times[0].tv_nsec != UTIME_NOW)
{
times[0] = _times[0];
if (auto ns = times[0].tv_nsec; ns != UTIME_OMIT && (ns < 0 || ns >= 1'000'000'000))
return BAN::Error::from_errno(EINVAL);
}
if (_times[1].tv_nsec != UTIME_NOW)
{
times[1] = _times[1];
if (auto ns = times[1].tv_nsec; ns != UTIME_OMIT && (ns < 0 || ns >= 1'000'000'000))
return BAN::Error::from_errno(EINVAL);
}
}
if (times[0].tv_nsec == UTIME_OMIT && times[1].tv_nsec == UTIME_OMIT)
return 0;
LockGuard _(m_process_lock);
auto inode = TRY(find_file(fd, path, flag)).inode;
if (!m_credentials.is_superuser() && inode->uid() != m_credentials.euid())
{
dwarnln("cannot chmod uid {} vs {}", inode->uid(), m_credentials.euid());
return BAN::Error::from_errno(EPERM);
}
TRY(inode->utimens(times));
return 0;
}
BAN::ErrorOr<long> Process::sys_socket(int domain, int type, int protocol)
{
LockGuard _(m_process_lock);
@ -1596,7 +1533,7 @@ namespace Kernel
}
auto epoll = TRY(Epoll::create());
for (int fd = 0; fd < arguments.nfds; fd++)
for (int fd = 0; fd < user_arguments->nfds; fd++)
{
uint32_t events = 0;
if (arguments.readfds && FD_ISSET(fd, arguments.readfds))
@ -1612,11 +1549,11 @@ namespace Kernel
if (inode_or_error.is_error())
continue;
TRY(epoll->ctl(EPOLL_CTL_ADD, fd, inode_or_error.release_value(), { .events = events, .data = { .fd = fd }}));
TRY(epoll->ctl(EPOLL_CTL_ADD, inode_or_error.release_value(), { .events = events, .data = { .fd = fd }}));
}
BAN::Vector<epoll_event> event_buffer;
TRY(event_buffer.resize(arguments.nfds));
TRY(event_buffer.resize(user_arguments->nfds));
const size_t waited_events = TRY(epoll->wait(event_buffer.span(), waketime_ns));
@ -1641,113 +1578,6 @@ namespace Kernel
return waited_events;
}
BAN::ErrorOr<long> Process::sys_ppoll(pollfd* fds, nfds_t nfds, const timespec* timeout, const sigset_t* sigmask)
{
auto* fds_region = TRY(validate_and_pin_pointer_access(fds, nfds * sizeof(pollfd), true));
BAN::ScopeGuard _([fds_region] { if (fds_region) fds_region->unpin(); });
const auto old_sigmask = Thread::current().m_signal_block_mask;
if (sigmask)
{
LockGuard _(m_process_lock);
TRY(validate_pointer_access(sigmask, sizeof(sigset_t), false));
Thread::current().m_signal_block_mask = *sigmask;
}
BAN::ScopeGuard sigmask_restore([old_sigmask] { Thread::current().m_signal_block_mask = old_sigmask; });
uint64_t waketime_ns = BAN::numeric_limits<uint64_t>::max();
if (timeout)
{
LockGuard _(m_process_lock);
TRY(validate_pointer_access(timeout, sizeof(timespec), false));
waketime_ns =
SystemTimer::get().ns_since_boot() +
(timeout->tv_sec * 1'000'000'000) +
timeout->tv_nsec;
}
uint32_t events_per_fd[OPEN_MAX] {};
for (nfds_t i = 0; i < nfds; i++)
{
if (fds[i].fd < 0 || fds[i].fd >= OPEN_MAX)
continue;
events_per_fd[fds[i].fd] |= fds[i].events;
}
size_t fd_count = 0;
auto epoll = TRY(Epoll::create());
for (int fd = 0; fd < OPEN_MAX; fd++)
{
if (events_per_fd[fd] == 0)
continue;
auto inode_or_error = m_open_file_descriptors.inode_of(fd);
if (inode_or_error.is_error())
continue;
uint32_t events = 0;
if (events_per_fd[fd] & (POLLIN | POLLRDNORM))
events |= EPOLLIN;
if (events_per_fd[fd] & (POLLOUT | POLLWRNORM))
events |= EPOLLOUT;
if (events_per_fd[fd] & POLLPRI)
events |= EPOLLPRI;
// POLLRDBAND
// POLLWRBAND
TRY(epoll->ctl(EPOLL_CTL_ADD, fd, inode_or_error.release_value(), { .events = events, .data = { .fd = fd }}));
fd_count++;
}
BAN::Vector<epoll_event> event_buffer;
TRY(event_buffer.resize(fd_count));
const size_t waited_events = TRY(epoll->wait(event_buffer.span(), waketime_ns));
size_t return_value = 0;
for (size_t i = 0; i < nfds; i++)
{
fds[i].revents = 0;
if (fds[i].fd < 0)
continue;
if (m_open_file_descriptors.inode_of(fds[i].fd).is_error())
{
fds[i].revents = POLLNVAL;
return_value++;
continue;
}
for (size_t j = 0; j < waited_events; j++)
{
if (fds[i].fd != event_buffer[j].data.fd)
continue;
const uint32_t wanted = fds[i].events;
const uint32_t got = event_buffer[j].events;
if (got & EPOLLIN)
fds[i].revents |= wanted & (POLLIN | POLLRDNORM);
if (got & EPOLLOUT)
fds[i].revents |= wanted & (POLLOUT | POLLWRNORM);
if (got & EPOLLPRI)
fds[i].revents |= wanted & POLLPRI;
if (got & EPOLLERR)
fds[i].revents |= POLLERR;
if (got & EPOLLHUP)
fds[i].revents |= POLLHUP;
// POLLRDBAND
// POLLWRBAND
if (fds[i].revents)
return_value++;
break;
}
}
return return_value;
}
BAN::ErrorOr<long> Process::sys_epoll_create1(int flags)
{
if (flags && (flags & ~EPOLL_CLOEXEC))
@ -1783,7 +1613,7 @@ namespace Kernel
event = *user_event;
}
TRY(static_cast<Epoll*>(epoll_inode.ptr())->ctl(op, fd, inode, event));
TRY(static_cast<Epoll*>(epoll_inode.ptr())->ctl(op, inode, event));
return 0;
}
@ -1856,7 +1686,7 @@ namespace Kernel
return TRY(m_open_file_descriptors.tell(fd));
}
BAN::ErrorOr<long> Process::sys_ftruncate(int fd, off_t length)
BAN::ErrorOr<long> Process::sys_truncate(int fd, off_t length)
{
TRY(m_open_file_descriptors.truncate(fd, length));
return 0;
@ -2481,7 +2311,11 @@ namespace Kernel
if (attr)
{
TRY(validate_pointer_access(attr, sizeof(*attr), false));
dwarnln("TODO: ignoring thread attr");
if (*attr)
{
dwarnln("pthread attr not supported");
return BAN::Error::from_errno(ENOTSUP);
}
}
LockGuard _(m_process_lock);
@ -2567,25 +2401,6 @@ namespace Kernel
return Thread::current().tid();
}
BAN::ErrorOr<long> Process::sys_pthread_kill(pthread_t tid, int signal)
{
if (signal != 0 && (signal < _SIGMIN || signal > _SIGMAX))
return BAN::Error::from_errno(EINVAL);
LockGuard _(m_process_lock);
for (auto* thread : m_threads)
{
if (thread->tid() != tid)
continue;
if (signal != 0)
thread->add_signal(signal);
return 0;
}
return BAN::Error::from_errno(ESRCH);
}
BAN::ErrorOr<long> Process::sys_tcgetpgrp(int fd)
{
LockGuard _(m_process_lock);

View File

@ -337,8 +337,6 @@ namespace Kernel
auto state = get_interrupt_state();
set_interrupt_state(InterruptState::Disabled);
ASSERT(!Thread::current().has_spinlock());
auto& processor_info = s_processors[current_id().as_u32()];
{

View File

@ -87,7 +87,6 @@ namespace Kernel
}
bool PseudoTerminalMaster::putchar(uint8_t ch)
{
{
SpinLockGuard _(m_buffer_lock);
@ -97,11 +96,10 @@ namespace Kernel
reinterpret_cast<uint8_t*>(m_buffer->vaddr())[(m_buffer_tail + m_buffer_size) % m_buffer->size()] = ch;
m_buffer_size++;
m_buffer_blocker.unblock();
}
epoll_notify(EPOLLIN);
m_buffer_blocker.unblock();
return true;
}
@ -132,10 +130,10 @@ namespace Kernel
m_buffer_size -= to_copy;
m_buffer_tail = (m_buffer_tail + to_copy) % m_buffer->size();
m_buffer_lock.unlock(state);
epoll_notify(EPOLLOUT);
m_buffer_lock.unlock(state);
return to_copy;
}
@ -158,15 +156,7 @@ namespace Kernel
}
PseudoTerminalSlave::PseudoTerminalSlave(BAN::String&& name, uint32_t number, mode_t mode, uid_t uid, gid_t gid)
: TTY({
.c_iflag = 0,
.c_oflag = 0,
.c_cflag = CS8,
.c_lflag = ECHO | ICANON,
.c_cc = {},
.c_ospeed = B38400,
.c_ispeed = B38400,
}, mode, uid, gid)
: TTY(mode, uid, gid)
, m_name(BAN::move(name))
, m_number(number)
{}

View File

@ -170,15 +170,7 @@ namespace Kernel
}
SerialTTY::SerialTTY(Serial serial)
: TTY({
.c_iflag = ICRNL,
.c_oflag = OPOST | ONLCR,
.c_cflag = CS8,
.c_lflag = ECHO | ICANON,
.c_cc = {},
.c_ospeed = B38400,
.c_ispeed = B38400,
}, 0600, 0, 0)
: TTY(0600, 0, 0)
, m_name(MUST(BAN::String::formatted("ttyS{}", s_next_tty_number++)))
, m_serial(serial)
{}
@ -243,6 +235,8 @@ namespace Kernel
while (!m_input.empty())
{
*ptr = m_input.front();
if (*ptr == '\r')
*ptr = '\n';
m_input.pop();
ptr++;
}

View File

@ -66,11 +66,18 @@ namespace Kernel
return makedev(DeviceNumber::TTY, s_minor++);
}
TTY::TTY(termios termios, mode_t mode, uid_t uid, gid_t gid)
TTY::TTY(mode_t mode, uid_t uid, gid_t gid)
: CharacterDevice(mode, uid, gid)
, m_termios(termios)
, m_rdev(next_tty_rdev())
{ }
{
// FIXME: add correct baud and flags
m_termios.c_iflag = 0;
m_termios.c_oflag = 0;
m_termios.c_cflag = CS8;
m_termios.c_lflag = ECHO | ICANON;
m_termios.c_ospeed = B38400;
m_termios.c_ispeed = B38400;
}
BAN::RefPtr<TTY> TTY::current()
{
@ -221,17 +228,6 @@ namespace Kernel
LockGuard _(m_mutex);
if ((m_termios.c_iflag & ISTRIP))
ch &= 0x7F;
if ((m_termios.c_iflag & IGNCR) && ch == '\r')
return;
uint8_t conv = ch;
if ((m_termios.c_iflag & ICRNL) && ch == '\r')
conv = '\n';
if ((m_termios.c_iflag & INLCR) && ch == '\n')
conv = '\r';
ch = conv;
// ^C
if (ch == '\x03')
{
@ -256,10 +252,6 @@ namespace Kernel
return;
}
// FIXME: don't ignore these bytes
if (m_output.bytes >= m_output.buffer.size())
return;
m_output.buffer[m_output.bytes++] = ch;
if (m_termios.c_lflag & ECHO)
@ -288,7 +280,7 @@ namespace Kernel
}
}
if (ch == '\n' || !(m_termios.c_lflag & ICANON) || m_output.bytes == m_output.buffer.size())
if (ch == '\n' || !(m_termios.c_lflag & ICANON))
{
m_output.flush = true;
epoll_notify(EPOLLIN);
@ -342,16 +334,9 @@ namespace Kernel
bool TTY::putchar(uint8_t ch)
{
SpinLockGuard _(m_write_lock);
if (!m_tty_ctrl.draw_graphics)
return true;
if (m_termios.c_oflag & OPOST)
{
if ((m_termios.c_oflag & ONLCR) && ch == '\n')
return putchar_impl('\r') && putchar_impl('\n');
if ((m_termios.c_oflag & OCRNL) && ch == '\r')
return putchar_impl('\n');
}
if (m_tty_ctrl.draw_graphics)
return putchar_impl(ch);
return true;
}
BAN::ErrorOr<size_t> TTY::read_impl(off_t, BAN::ByteSpan buffer)
@ -368,13 +353,7 @@ namespace Kernel
return 0;
}
const size_t max_to_copy = BAN::Math::min<size_t>(buffer.size(), m_output.bytes);
size_t to_copy = max_to_copy;
if (m_termios.c_lflag & ICANON)
for (to_copy = 1; to_copy < max_to_copy; to_copy++)
if (m_output.buffer[to_copy - 1] == '\n')
break;
size_t to_copy = BAN::Math::min<size_t>(buffer.size(), m_output.bytes);
memcpy(buffer.data(), m_output.buffer.data(), to_copy);
memmove(m_output.buffer.data(), m_output.buffer.data() + to_copy, m_output.bytes - to_copy);

View File

@ -36,15 +36,7 @@ namespace Kernel
}
VirtualTTY::VirtualTTY(BAN::RefPtr<TerminalDriver> driver)
: TTY({
.c_iflag = 0,
.c_oflag = 0,
.c_cflag = CS8,
.c_lflag = ECHO | ICANON,
.c_cc = {},
.c_ospeed = B38400,
.c_ispeed = B38400,
}, 0600, 0, 0)
: TTY(0600, 0, 0)
, m_name(MUST(BAN::String::formatted("tty{}", s_next_tty_number++)))
, m_terminal_driver(driver)
, m_palette(driver->palette())

View File

@ -140,8 +140,6 @@ namespace Kernel
pid_t Thread::current_tid()
{
if (Processor::count() == 0)
return 0;
return Processor::scheduler().current_tid();
}
@ -525,8 +523,6 @@ namespace Kernel
// Ignore the signal
case SIGCHLD:
case SIGURG:
case SIGWINCH:
case SIGCANCEL:
break;
// Stop the process:

View File

@ -1,7 +1,6 @@
set(LIBC_SOURCES
arpa/inet.cpp
assert.cpp
complex.cpp
ctype.cpp
dirent.cpp
dlfcn.cpp
@ -48,7 +47,6 @@ set(LIBC_SOURCES
time.cpp
unistd.cpp
utime.cpp
wchar-stdio.cpp
wchar.cpp
icxxabi.cpp

View File

@ -1,192 +0,0 @@
#include <BAN/Math.h>
#include <BAN/Traits.h>
#include <complex.h>
#include <math.h>
template<BAN::floating_point T> struct _complex_t;
template<> struct _complex_t<float> { using type = __complex__ float; };
template<> struct _complex_t<double> { using type = __complex__ double; };
template<> struct _complex_t<long double> { using type = __complex__ long double; };
template<BAN::floating_point T>
using _complex = _complex_t<T>::type;
template<BAN::floating_point T>
static constexpr T _cabs(_complex<T> z)
{
return BAN::Math::sqrt(creal(z) * creal(z) + cimag(z) * cimag(z));
}
template<BAN::floating_point T>
static constexpr T _carg(_complex<T> z)
{
return BAN::Math::atan2(cimag(z), creal(z));
}
template<BAN::floating_point T>
static constexpr _complex<T> _cproj(_complex<T> z)
{
if (!isfinite(creal(z)) || !isfinite(cimag(z)))
return INFINITY + I * copysign(0.0, cimag(z));
return z;
}
template<BAN::floating_point T>
static constexpr _complex<T> _conj(_complex<T> z)
{
cimag(z) = -cimag(z);
return z;
}
template<BAN::floating_point T>
static constexpr _complex<T> _cexp(_complex<T> z)
{
T sin, cos;
BAN::Math::sincos(cimag(z), sin, cos);
return BAN::Math::exp(creal(z)) * (cos + sin * I);
}
template<BAN::floating_point T>
static constexpr _complex<T> _clog(_complex<T> z)
{
return BAN::Math::log(_cabs<T>(z)) + I * _carg<T>(z);
}
template<BAN::floating_point T>
static constexpr _complex<T> _csqrt(_complex<T> z)
{
return BAN::Math::sqrt(_cabs<T>(z)) * _cexp<T>(I * _carg<T>(z) / 2);
}
template<BAN::floating_point T>
static constexpr _complex<T> _csin(_complex<T> z)
{
return (_cexp<T>(z * I) - _cexp<T>(-z * I)) / 2i;
}
template<BAN::floating_point T>
static constexpr _complex<T> _ccos(_complex<T> z)
{
return (_cexp<T>(z * I) + _cexp<T>(-z * I)) / 2i;
}
template<BAN::floating_point T>
static constexpr _complex<T> _ctan(_complex<T> z)
{
const _complex<T> exp_pos = _cexp<T>(+I * z);
const _complex<T> exp_neg = _cexp<T>(-I * z);
return -I * (exp_pos - exp_neg) / (exp_pos + exp_neg);
}
template<BAN::floating_point T>
static constexpr _complex<T> _cpow(_complex<T> x, _complex<T> y)
{
const T ln_r = BAN::Math::log(_cabs<T>(x));
const T theta = _carg<T>(x);
const T a = creal(y);
const T b = cimag(y);
return BAN::Math::exp(a * ln_r - b * theta) * _cexp<T>(I * (a * theta + b * ln_r));
}
template<BAN::floating_point T>
static constexpr _complex<T> _casin(_complex<T> z)
{
return -I * _clog<T>(_csqrt<T>(1 - z * z) + I * z);
}
template<BAN::floating_point T>
static constexpr _complex<T> _cacos(_complex<T> z)
{
return -I * _clog<T>(I * _csqrt<T>(1 - z * z) + z);
}
template<BAN::floating_point T>
static constexpr _complex<T> _catan(_complex<T> z)
{
return -I / 2 * _clog<T>((I - z) / (I + z));
}
template<BAN::floating_point T>
static constexpr _complex<T> _csinh(_complex<T> z)
{
return (_cexp<T>(z) - _cexp<T>(-z)) / 2;
}
template<BAN::floating_point T>
static constexpr _complex<T> _ccosh(_complex<T> z)
{
return (_cexp<T>(z) + _cexp<T>(-z)) / 2;
}
template<BAN::floating_point T>
static constexpr _complex<T> _ctanh(_complex<T> z)
{
const _complex<T> exp2x = _cexp<T>(2 * z);
return (exp2x - 1) / (exp2x + 1);
}
template<BAN::floating_point T>
static constexpr _complex<T> _casinh(_complex<T> z)
{
return _clog<T>(z + _csqrt<T>(z * z + 1));
}
template<BAN::floating_point T>
static constexpr _complex<T> _cacosh(_complex<T> z)
{
return _clog<T>(z + _csqrt<T>(z * z - 1));
}
template<BAN::floating_point T>
static constexpr _complex<T> _catanh(_complex<T> z)
{
return _clog<T>((1 + z) / (1 - z)) / 2;
}
#define COMPLEX_FUNCS(func) \
float func##f(float complex a) { return _##func<float>(a); } \
double func(double complex a) { return _##func<double>(a); } \
long double func##l(long double complex a) { return _##func<long double>(a); }
COMPLEX_FUNCS(cabs)
COMPLEX_FUNCS(carg)
#undef COMPLEX_FUNCS
#define COMPLEX_FUNCS(func) \
float complex func##f(float complex a) { return _##func<float>(a); } \
double complex func(double complex a) { return _##func<double>(a); } \
long double complex func##l(long double complex a) { return _##func<long double>(a); }
COMPLEX_FUNCS(cproj)
COMPLEX_FUNCS(conj)
COMPLEX_FUNCS(cexp)
COMPLEX_FUNCS(ctan)
COMPLEX_FUNCS(clog)
COMPLEX_FUNCS(csin)
COMPLEX_FUNCS(ccos)
COMPLEX_FUNCS(csqrt)
COMPLEX_FUNCS(csinh)
COMPLEX_FUNCS(ccosh)
COMPLEX_FUNCS(ctanh)
COMPLEX_FUNCS(cacos)
COMPLEX_FUNCS(casin)
COMPLEX_FUNCS(catan)
COMPLEX_FUNCS(cacosh)
COMPLEX_FUNCS(casinh)
COMPLEX_FUNCS(catanh)
#undef COMPLEX_FUNCS
#define COMPLEX_FUNCS(func) \
float complex func##f(float complex a, float complex b) { return _##func<float>(a, b); } \
double complex func(double complex a, double complex b) { return _##func<double>(a, b); } \
long double complex func##l(long double complex a, long double complex b) { return _##func<long double>(a, b); }
COMPLEX_FUNCS(cpow)
#undef COMPLEX_FUNCS

View File

@ -1,9 +1,12 @@
#include <errno.h>
#include <pthread.h>
extern uthread* _get_uthread();
#if __disable_thread_local_storage
static int s_errno = 0;
#else
static thread_local int s_errno = 0;
#endif
int* __errno_location()
{
return &_get_uthread()->errno_;
return &s_errno;
}

View File

@ -1,19 +1,15 @@
#include <fcntl.h>
#include <pthread.h>
#include <stdarg.h>
#include <sys/syscall.h>
#include <unistd.h>
int creat(const char* path, mode_t mode)
{
pthread_testcancel();
return open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
}
int open(const char* path, int oflag, ...)
{
pthread_testcancel();
va_list args;
va_start(args, oflag);
mode_t mode = va_arg(args, mode_t);
@ -24,8 +20,6 @@ int open(const char* path, int oflag, ...)
int openat(int fd, const char* path, int oflag, ...)
{
pthread_testcancel();
va_list args;
va_start(args, oflag);
mode_t mode = va_arg(args, mode_t);
@ -36,8 +30,6 @@ int openat(int fd, const char* path, int oflag, ...)
int fcntl(int fildes, int cmd, ...)
{
pthread_testcancel();
va_list args;
va_start(args, cmd);
int extra = va_arg(args, int);

View File

@ -12,12 +12,11 @@ __BEGIN_DECLS
#include <signal.h>
#define __need_off_t
#define __need_pthread_attr_t
#define __need_size_t
#define __need_ssize_t
#include <sys/types.h>
#include <bits/types/pthread_attr_t.h>
struct aiocb
{
int aio_fildes; /* File descriptor. */

View File

@ -0,0 +1,44 @@
// https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_types.h.html
#include <sys/cdefs.h>
__BEGIN_DECLS
#if !defined(__pthread_attr_t_defined) && (defined(__need_all_types) || defined(__need_pthread_attr_t) || defined(__need_pthread_types))
#define __pthread_attr_t_defined 1
typedef int pthread_attr_t;
#endif
#undef __need_pthread_attr_t
#if !defined(__pthread_t_defined) && (defined(__need_all_types) || defined(__need_pthread_t) || defined(__need_pthread_types))
#define __pthread_t_defined 1
typedef pid_t pthread_t;
#endif
#undef __need_pthread_t
#if !defined(__pthread_types_defined) && (defined(__need_all_types) || defined(__need_pthread_types))
#define __pthread_types_defined 1
typedef int pthread_once_t;
typedef unsigned pthread_key_t;
typedef pthread_t pthread_spinlock_t;
typedef struct { int type; int shared; } pthread_mutexattr_t;
typedef struct { pthread_mutexattr_t attr; pthread_t locker; unsigned lock_depth; } pthread_mutex_t;
typedef struct { int shared; } pthread_barrierattr_t;
typedef struct { pthread_barrierattr_t attr; unsigned target; unsigned waiting; } pthread_barrier_t;
typedef struct { int clock; int shared; } pthread_condattr_t;
struct _pthread_cond_block { struct _pthread_cond_block* next; int signaled; };
typedef struct { pthread_condattr_t attr; pthread_spinlock_t lock; struct _pthread_cond_block* block_list; } pthread_cond_t;
typedef struct { int shared; } pthread_rwlockattr_t;
typedef struct { pthread_rwlockattr_t attr; unsigned lockers; unsigned writers; } pthread_rwlock_t;
#endif
#undef __need_pthread_types
__END_DECLS

View File

@ -1,5 +1,5 @@
#ifndef _BITS_TYPES_LOCALE_T_H
#define _BITS_TYPES_LOCALE_T_H 1
#ifndef _BITS_LOCALE_T_H
#define _BITS_LOCALE_T_H 1
// https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/locale.h.html

View File

@ -1,25 +0,0 @@
#ifndef _BITS_TYPES_PTHREAD_ATTR_T_H
#define _BITS_TYPES_PTHREAD_ATTR_T_H 1
// https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/pthread.h.html
#include <sys/cdefs.h>
__BEGIN_DECLS
#include <bits/types/sched_param.h>
typedef struct
{
int inheritsched;
struct sched_param schedparam;
int schedpolicy;
int detachstate;
int scope;
size_t stacksize;
size_t guardsize;
} pthread_attr_t;
__END_DECLS
#endif

View File

@ -1,17 +0,0 @@
#ifndef _BITS_TYPES_PTHREAD_T_H
#define _BITS_TYPES_PTHREAD_T_H 1
// https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/pthread.h.html
#include <sys/cdefs.h>
__BEGIN_DECLS
#define __need_pid_t
#include <sys/types.h>
typedef pid_t pthread_t;
__END_DECLS
#endif

View File

@ -1,72 +0,0 @@
#ifndef _BITS_TYPES_PTHREAD_TYPES_H
#define _BITS_TYPES_PTHREAD_TYPES_H 1
// https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/pthread.h.html
#include <sys/cdefs.h>
__BEGIN_DECLS
#include <bits/types/pthread_attr_t.h>
#include <bits/types/pthread_t.h>
typedef int pthread_once_t;
typedef unsigned pthread_key_t;
typedef pthread_t pthread_spinlock_t;
typedef struct
{
int type;
int shared;
} pthread_mutexattr_t;
typedef struct
{
pthread_mutexattr_t attr;
pthread_t locker;
unsigned lock_depth;
} pthread_mutex_t;
typedef struct
{
int shared;
} pthread_barrierattr_t;
typedef struct
{
pthread_barrierattr_t attr;
unsigned target;
unsigned waiting;
} pthread_barrier_t;
typedef struct
{
int clock;
int shared;
} pthread_condattr_t;
struct _pthread_cond_block
{
struct _pthread_cond_block* next;
int signaled;
};
typedef struct
{
pthread_condattr_t attr;
pthread_spinlock_t lock;
struct _pthread_cond_block* block_list;
} pthread_cond_t;
typedef struct
{
int shared;
} pthread_rwlockattr_t;
typedef struct
{
pthread_rwlockattr_t attr;
unsigned lockers;
unsigned writers;
} pthread_rwlock_t;
__END_DECLS
#endif

View File

@ -1,23 +0,0 @@
#ifndef _BITS_TYPES_SCHED_PARAM_H
#define _BITS_TYPES_SCHED_PARAM_H 1
// https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sched.h.html
#include <sys/cdefs.h>
__BEGIN_DECLS
#include <time.h>
struct sched_param
{
int sched_priority; /* Process or thread execution scheduling priority. */
int sched_ss_low_priority; /* Low scheduling priority for sporadic server. */
struct timespec sched_ss_repl_period; /* Replenishment period for sporadic server. */
struct timespec sched_ss_init_budget; /* Initial budget for sporadic server. */
int sched_ss_max_repl; /* Maximum pending replenishments for sporadic server. */
};
__END_DECLS
#endif

View File

@ -1,5 +1,5 @@
#ifndef _BITS_TYPES_TIMEVAL_H
#define _BITS_TYPES_TIMEVAL_H 1
#ifndef _BITS_TIMEVAL_H
#define _BITS_TIMEVAL_H 1
#include <sys/cdefs.h>

View File

@ -13,14 +13,6 @@
__BEGIN_DECLS
#define creal(complex) (__real__ (complex))
#define crealf(complex) (__real__ (complex))
#define creall(complex) (__real__ (complex))
#define cimag(complex) (__imag__ (complex))
#define cimagf(complex) (__imag__ (complex))
#define cimagl(complex) (__imag__ (complex))
double cabs(double complex);
float cabsf(float complex);
long double cabsl(long double complex);
@ -54,6 +46,9 @@ long double complex ccosl(long double complex);
double complex cexp(double complex);
float complex cexpf(float complex);
long double complex cexpl(long double complex);
double cimag(double complex);
float cimagf(float complex);
long double cimagl(long double complex);
double complex clog(double complex);
float complex clogf(float complex);
long double complex clogl(long double complex);
@ -66,6 +61,9 @@ long double complex cpowl(long double complex, long double complex);
double complex cproj(double complex);
float complex cprojf(float complex);
long double complex cprojl(long double complex);
double creal(double complex);
float crealf(float complex);
long double creall(long double complex);
double complex csin(double complex);
float complex csinf(float complex);
double complex csinh(double complex);

View File

@ -7,13 +7,6 @@
__BEGIN_DECLS
// Maximum Values
#define _POSIX_CLOCKRES_MIN 20000000
// Minimum Values
#define _POSIX_AIO_LISTIO_MAX 2
#define _POSIX_AIO_MAX 1
#define _POSIX_ARG_MAX 4096
@ -64,83 +57,17 @@ __BEGIN_DECLS
#define _XOPEN_NAME_MAX 255
#define _XOPEN_PATH_MAX 1024
// Runtime Invariant Values (Possibly Indeterminate)
#define AIO_LISTIO_MAX _POSIX_AIO_LISTIO_MAX
#define AIO_MAX _POSIX_AIO_MAX
#define AIO_PRIO_DELTA_MAX 0
#define ARG_MAX _POSIX_ARG_MAX
#define ATEXIT_MAX 128
#define CHILD_MAX _POSIX_CHILD_MAX
#define DELAYTIMER_MAX _POSIX_DELAYTIMER_MAX
#define HOST_NAME_MAX 255
#define IOV_MAX _XOPEN_IOV_MAX
#define LOGIN_NAME_MAX 256
#define MQ_OPEN_MAX _POSIX_MQ_OPEN_MAX
#define MQ_PRIO_MAX _POSIX_MQ_PRIO_MAX
#define OPEN_MAX 64
#define PAGESIZE PAGE_SIZE
#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS
#define PTHREAD_KEYS_MAX _POSIX_THREAD_KEYS_MAX
#define PTHREAD_STACK_MIN PAGE_SIZE
#define PTHREAD_THREADS_MAX _POSIX_THREAD_THREADS_MAX
#define RTSIG_MAX _POSIX_RTSIG_MAX
#define SEM_NSEMS_MAX _POSIX_SEM_NSEMS_MAX
#define SEM_VALUE_MAX _POSIX_SEM_VALUE_MAX
#define SIGQUEUE_MAX _POSIX_SIGQUEUE_MAX
#define SS_REPL_MAX _POSIX_SS_REPL_MAX
#define STREAM_MAX _POSIX_STREAM_MAX
#define SYMLOOP_MAX _POSIX_SYMLOOP_MAX
#define TIMER_MAX _POSIX_TIMER_MAX
#define TRACE_EVENT_NAME_MAX _POSIX_TRACE_EVENT_NAME_MAX
#define TRACE_NAME_MAX _POSIX_TRACE_NAME_MAX
#define TRACE_SYS_MAX _POSIX_TRACE_SYS_MAX
#define TRACE_USER_EVENT_MAX _POSIX_TRACE_USER_EVENT_MAX
#define TTY_NAME_MAX PATH_MAX
#define TZNAME_MAX _POSIX_TZNAME_MAX
#ifndef PAGE_SIZE
#define PAGE_SIZE 4096
#endif
// Pathname Variable Values
#define FILESIZEBITS 32
#define LINK_MAX _POSIX_LINK_MAX
#define MAX_CANON _POSIX_MAX_CANON
#define MAX_INPUT _POSIX_MAX_INPUT
#define NAME_MAX 255
#define PATH_MAX _POSIX_PATH_MAX
#define PIPE_BUF PAGE_SIZE
//#define POSIX_ALLOC_SIZE_MIN
//#define POSIX_REC_INCR_XFER_SIZE
//#define POSIX_REC_MAX_XFER_SIZE
//#define POSIX_REC_MIN_XFER_SIZE
//#define POSIX_REC_XFER_ALIGN
#define SYMLINK_MAX _POSIX_SYMLINK_MAX
// Runtime Increasable Values
#define BC_BASE_MAX _POSIX2_BC_BASE_MAX
#define BC_DIM_MAX _POSIX2_BC_DIM_MAX
#define BC_SCALE_MAX _POSIX2_BC_SCALE_MAX
#define BC_STRING_MAX _POSIX2_BC_STRING_MAX
#define CHARCLASS_NAME_MAX _POSIX2_CHARCLASS_NAME_MAX
#define COLL_WEIGHTS_MAX _POSIX2_COLL_WEIGHTS_MAX
#define EXPR_NEST_MAX _POSIX2_EXPR_NEST_MAX
#define LINE_MAX _POSIX2_LINE_MAX
#define NGROUPS_MAX _POSIX_NGROUPS_MAX
#define RE_DUP_MAX _POSIX_RE_DUP_MAX
// Legacy things
#define PATH_MAX 256
#define PASS_MAX 256
#define LOGIN_NAME_MAX 256
#define HOST_NAME_MAX 255
#define TTY_NAME_MAX PATH_MAX
// Numerical Limits
#define PTHREAD_KEYS_MAX _POSIX_THREAD_KEYS_MAX
#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS
#define CHAR_MAX SCHAR_MAX
#define CHAR_MIN SCHAR_MIN

View File

@ -1,6 +0,0 @@
#ifndef _MEMORY_H
#define _MEMORY_H 1
#include <string.h>
#endif

View File

@ -10,12 +10,11 @@ __BEGIN_DECLS
#include <time.h>
#include <signal.h>
#define __need_pthread_attr_t
#define __need_size_t
#define __need_ssize_t
#include <sys/types.h>
#include <bits/types/pthread_attr_t.h>
typedef int mqd_t;
struct mq_attr

View File

@ -7,8 +7,6 @@
__BEGIN_DECLS
#include <signal.h>
struct pollfd
{
int fd; /* The following descriptor being polled. */
@ -30,7 +28,6 @@ typedef unsigned long nfds_t;
#define POLLNVAL 0x200
int poll(struct pollfd fds[], nfds_t nfds, int timeout);
int ppoll(struct pollfd fds[], nfds_t nfds, const struct timespec* timeout, const sigset_t* sigmask);
__END_DECLS

View File

@ -13,51 +13,29 @@ __BEGIN_DECLS
#define __need_size_t
#define __need_clockid_t
#define __need_pthread_types
#include <sys/types.h>
#include <bits/types/pthread_types.h>
struct _pthread_cleanup_t
{
void (*routine)(void*);
void* arg;
struct _pthread_cleanup_t* next;
};
struct uthread
{
struct uthread* self;
void* master_tls_addr;
size_t master_tls_size;
struct _pthread_cleanup_t* cleanup_stack;
pthread_t id;
int errno_;
int cancel_type;
int cancel_state;
int canceled;
uintptr_t dtv[];
};
#define PTHREAD_CANCELED (void*)1
#define PTHREAD_CANCEL_ASYNCHRONOUS 1
#define PTHREAD_CANCEL_DEFERRED 0
#define PTHREAD_CANCEL_DISABLE 0
#define PTHREAD_CANCEL_ENABLE 1
// cancellation points
// https://pubs.opengroup.org/onlinepubs/9799919799/functions/V2_chap02.html#tag_16_09_05_02
#define PTHREAD_PRIO_INHERIT 1
#define PTHREAD_PRIO_NONE 0
#define PTHREAD_PRIO_PROTECT 2
#define PTHREAD_EXPLICIT_SCHED 1
#define PTHREAD_INHERIT_SCHED 0
#define PTHREAD_SCOPE_PROCESS 1
#define PTHREAD_SCOPE_SYSTEM 0
#define PTHREAD_CANCEL_ASYNCHRONOUS 2
#define PTHREAD_CANCEL_ENABLE 3
#define PTHREAD_CANCEL_DEFERRED 4
#define PTHREAD_CANCEL_DISABLE 5
#define PTHREAD_CANCELED 6
#define PTHREAD_EXPLICIT_SCHED 9
#define PTHREAD_INHERIT_SCHED 10
#define PTHREAD_PRIO_INHERIT 18
#define PTHREAD_PRIO_NONE 19
#define PTHREAD_PRIO_PROTECT 20
#define PTHREAD_SCOPE_PROCESS 23
#define PTHREAD_SCOPE_SYSTEM 24
#define PTHREAD_CREATE_DETACHED 1
#define PTHREAD_CREATE_JOINABLE 0
@ -82,11 +60,6 @@ struct uthread
#define PTHREAD_MUTEX_INITIALIZER (pthread_mutex_t){ { PTHREAD_MUTEX_DEFAULT, 0 }, 0, 0 }
#define PTHREAD_RWLOCK_INITIALIZER (pthread_rwlock_t){ { 0 }, 0, 0 }
#define _PTHREAD_ATFORK_PREPARE 0
#define _PTHREAD_ATFORK_PARENT 1
#define _PTHREAD_ATFORK_CHILD 2
void _pthread_call_atfork(int state);
int pthread_atfork(void (*prepare)(void), void (*parent)(void), void(*child)(void));
int pthread_attr_destroy(pthread_attr_t* attr);
int pthread_attr_getdetachstate(const pthread_attr_t* attr, int* detachstate);

View File

@ -12,7 +12,14 @@ __BEGIN_DECLS
#define __need_pid_t
#include <sys/types.h>
#include <bits/types/sched_param.h>
struct sched_param
{
int sched_priority; /* Process or thread execution scheduling priority. */
int sched_ss_low_priority; /* Low scheduling priority for sporadic server. */
struct timespec sched_ss_repl_period; /* Replenishment period for sporadic server. */
struct timespec sched_ss_init_budget; /* Initial budget for sporadic server. */
int sched_ss_max_repl; /* Maximum pending replenishments for sporadic server. */
};
#define SCHED_FIFO 1
#define SCHED_RR 2

View File

@ -14,14 +14,13 @@ __BEGIN_DECLS
#define SIG_HOLD ((void (*)(int))2)
#define SIG_IGN ((void (*)(int))3)
#define __need_pthread_t
#define __need_size_t
#define __need_uid_t
#define __need_pid_t
#define __need_pthread_attr_t
#include <sys/types.h>
#include <bits/types/pthread_attr_t.h>
#include <bits/types/pthread_t.h>
typedef int sig_atomic_t;
typedef unsigned long long sigset_t;
@ -106,8 +105,7 @@ struct sigevent
#define SIGXCPU 27
#define SIGXFSZ 28
#define SIGWINCH 29
#define SIGCANCEL 30
#define SIGRTMIN 31
#define SIGRTMIN 30
#define SIGRTMAX (SIGRTMIN+32)
#define NSIG SIGRTMAX

View File

@ -56,7 +56,7 @@ __BEGIN_DECLS
O(SYS_POWEROFF, poweroff) \
O(SYS_FCHMODAT, fchmodat) \
O(SYS_CREATE_DIR, create_dir) \
O(SYS_UNLINKAT, unlinkat) \
O(SYS_UNLINK, unlink) \
O(SYS_READLINKAT, readlinkat) \
O(SYS_MSYNC, msync) \
O(SYS_PREAD, pread) \
@ -73,8 +73,7 @@ __BEGIN_DECLS
O(SYS_CONNECT, connect) \
O(SYS_LISTEN, listen) \
O(SYS_PSELECT, pselect) \
O(SYS_PPOLL, ppoll) \
O(SYS_FTRUNCATE, ftruncate) \
O(SYS_TRUNCATE, truncate) \
O(SYS_SMO_CREATE, smo_create) \
O(SYS_SMO_DELETE, smo_delete) \
O(SYS_SMO_MAP, smo_map) \
@ -95,7 +94,6 @@ __BEGIN_DECLS
O(SYS_FSYNC, fsync) \
O(SYS_SYMLINKAT, symlinkat) \
O(SYS_HARDLINKAT, hardlinkat) \
O(SYS_UTIMENSAT, utimensat) \
O(SYS_YIELD, yield) \
O(SYS_SET_TLS, set_tls) \
O(SYS_GET_TLS, get_tls) \
@ -103,7 +101,6 @@ __BEGIN_DECLS
O(SYS_PTHREAD_EXIT, pthread_exit) \
O(SYS_PTHREAD_JOIN, pthread_join) \
O(SYS_PTHREAD_SELF, pthread_self) \
O(SYS_PTHREAD_KILL, pthread_kill) \
O(SYS_EPOLL_CREATE1, epoll_create1) \
O(SYS_EPOLL_CTL, epoll_ctl) \
O(SYS_EPOLL_PWAIT2, epoll_pwait2) \

View File

@ -21,6 +21,9 @@ __BEGIN_DECLS
&& !defined(__need_nlink_t) \
&& !defined(__need_off_t) \
&& !defined(__need_pid_t) \
&& !defined(__need_pthread_attr_t) \
&& !defined(__need_pthread_t) \
&& !defined(__need_pthread_types) \
&& !defined(__need_size_t) \
&& !defined(__need_ssize_t) \
&& !defined(__need_suseconds_t) \
@ -119,12 +122,18 @@ __BEGIN_DECLS
#endif
#undef __need_off_t
#ifdef __need_pthread_t
#define __need_pid_t
#endif
#if !defined(__pid_t_defined) && (defined(__need_all_types) || defined(__need_pid_t))
#define __pid_t_defined 1
typedef int pid_t;
#endif
#undef __need_pid_t
#include <bits/pthread_types.h>
#if !defined(__size_t_defined) && (defined(__need_all_types) || defined(__need_size_t))
#define __size_t_defined 1
#define __need_size_t

View File

@ -11,106 +11,86 @@ __BEGIN_DECLS
#define _POSIX2_VERSION -1
#define _XOPEN_VERSION 700
// -1 not supported for compilation
// 0 might or might not be supported during runtime
// >0 always supported
// MISSING / UNSUPPORTED
#define _POSIX_ADVISORY_INFO -1 /* posix_{fadvice,fallocate,memalign,madvice} */
#define _POSIX_ASYNCHRONOUS_IO -1 /* aio_{cancel,error,fsync,read,return,suspend,write,listio} */
#define _POSIX_BARRIERS 200809L
#define _POSIX_CHOWN_RESTRICTED 200809L
#define _POSIX_CLOCK_SELECTION 0 /* pthread_condattr_{getclock,setclock}, clock_nanosleep */
#define _POSIX_CPUTIME 0 /* working CLOCK_CPUTIME */
#define _POSIX_FSYNC 200809L
#define _POSIX_IPV6 0 /* IPv6 :D */
#define _POSIX_JOB_CONTROL 200809L /* tcdrain, tcsendbreak */
#define _POSIX_MAPPED_FILES 200809L
#define _POSIX_MEMLOCK -1 /* mlockall, munlockall */
#define _POSIX_MEMLOCK_RANGE -1 /* mlock, munlock */
#define _POSIX_MEMORY_PROTECTION -1 /* mprotect */
#define _POSIX_MESSAGE_PASSING -1 /* mq_{close,getattr,notify,open,receive,send,sendattr,unlink} */
#define _POSIX_MONOTONIC_CLOCK 200809L
#define _POSIX_NO_TRUNC 200809L
#define _POSIX_PRIORITIZED_IO -1 /* aio_{read,write} */
#define _POSIX_PRIORITY_SCHEDULING -1 /* sched_{get_priority_min,get_priority_max,getparam,getscheduler,rr_get_interval,setparam,setscheduler} */
#define _POSIX_RAW_SOCKETS 0 /* raw sockets :D */
#define _POSIX_READER_WRITER_LOCKS 200809L
#define _POSIX_REALTIME_SIGNALS -1 /* siq{queue,timedwait,waitinfo} */
#define _POSIX_REGEXP -1 /* reg{comp,error,exec,free} */
#define _POSIX_SAVED_IDS 200809L
#define _POSIX_SEMAPHORES -1 /* sem_{close,destroy,getvalue,init,open,post,trywait,unlink,wait} */
#define _POSIX_SHARED_MEMORY_OBJECTS -1 /* shm_{open,unlink} */
#define _POSIX_SHELL 200809L
#define _POSIX_SPAWN -1 /* posix_spawn* */
#define _POSIX_SPIN_LOCKS 200809L
#define _POSIX_SPORADIC_SERVER -1 /* sched_{setparam,setscheduler} with SCHED_SPORADIC */
#define _POSIX_SYNCHRONIZED_IO 200809L
#define _POSIX_THREAD_ATTR_STACKADDR 0 /* pthread_attr_{get,set}stack{,addr} */
#define _POSIX_THREAD_ATTR_STACKSIZE 0 /* pthread_attr_{get,set}stack{,size} */
#define _POSIX_THREAD_CPUTIME -1 /* pthread_getcpuclockid, clock_{getres,gettime,settime,create} for thread CPU time */
#define _POSIX_THREAD_PRIO_INHERIT -1 /* pthread_mutexattr_{get,set}protocol */
#define _POSIX_THREAD_PRIO_PROTECT -1 /* pthread_mutex{,attr}_{get,set}prioceiling, pthread_mutexattr_{get,set}protocol */
#define _POSIX_THREAD_PRIORITY_SCHEDULING -1 /* pthread_attr_{get,set}{inheritsched,schedpolicy,scope}, pthread_{get,set}schedparam, pthread_setschedprio */
#define _POSIX_THREAD_PROCESS_SHARED 200809L
#define _POSIX_THREAD_ROBUST_PRIO_INHERIT 0 /* robust mutexes */
#define _POSIX_THREAD_ROBUST_PRIO_PROTECT 0 /* robust mutexes */
#define _POSIX_THREAD_SAFE_FUNCTIONS 200809L /* some *_r functions */
#define _POSIX_ADVISORY_INFO -1
#define _POSIX_ASYNCHRONOUS_IO -1
#define _POSIX_BARRIERS -1
#define _POSIX_CHOWN_RESTRICTED -1
#define _POSIX_CLOCK_SELECTION -1
#define _POSIX_CPUTIME -1
#define _POSIX_FSYNC -1
#define _POSIX_IPV6 -1
#define _POSIX_JOB_CONTROL -1
#define _POSIX_MAPPED_FILES -1
#define _POSIX_MEMLOCK -1
#define _POSIX_MEMLOCK_RANGE -1
#define _POSIX_MEMORY_PROTECTION -1
#define _POSIX_MESSAGE_PASSING -1
#define _POSIX_MONOTONIC_CLOCK -1
#define _POSIX_NO_TRUNC -1
#define _POSIX_PRIORITIZED_IO -1
#define _POSIX_PRIORITY_SCHEDULING -1
#define _POSIX_RAW_SOCKETS -1
#define _POSIX_READER_WRITER_LOCKS -1
#define _POSIX_REALTIME_SIGNALS -1
#define _POSIX_REGEXP -1
#define _POSIX_SAVED_IDS -1
#define _POSIX_SEMAPHORES -1
#define _POSIX_SHARED_MEMORY_OBJECTS -1
#define _POSIX_SHELL -1
#define _POSIX_SPAWN -1
#define _POSIX_SPIN_LOCKS -1
#define _POSIX_SPORADIC_SERVER -1
#define _POSIX_SYNCHRONIZED_IO xx
#define _POSIX_THREAD_ATTR_STACKADDR -1
#define _POSIX_THREAD_ATTR_STACKSIZE -1
#define _POSIX_THREAD_CPUTIME -1
#define _POSIX_THREAD_PRIO_INHERIT -1
#define _POSIX_THREAD_PRIO_PROTECT -1
#define _POSIX_THREAD_PRIORITY_SCHEDULING -1
#define _POSIX_THREAD_PROCESS_SHARED -1
#define _POSIX_THREAD_ROBUST_PRIO_INHERIT -1
#define _POSIX_THREAD_ROBUST_PRIO_PROTECT -1
#define _POSIX_THREAD_SAFE_FUNCTIONS -1
#define _POSIX_THREAD_SPORADIC_SERVER -1
#define _POSIX_THREADS 200809L
#define _POSIX_TIMEOUTS -1 /* mq_timed{receive,send}, sem_timedwait, posix_trace_timedgetnext_event */
#define _POSIX_TIMERS -1 /* timer_{create,delete,gettime,getoverrun,settime} */
#define _POSIX_TRACE -1 /* posix_trace_* */
#define _POSIX_TRACE_EVENT_FILTER -1 /* posix_trace_* */
#define _POSIX_TRACE_INHERIT -1 /* posix_trace_* */
#define _POSIX_TRACE_LOG -1 /* posix_trace_* */
#define _POSIX_TYPED_MEMORY_OBJECTS -1 /* posix_mem_offset, posix_typed_mem_{get_info,open} */
#define _POSIX2_C_BIND 200809L
#define _POSIX2_C_DEV -1 /* c99, lex, yacc */
#define _POSIX2_CHAR_TERM 200809L
#define _POSIX2_FORT_DEV -1 /* fortran stuff */
#define _POSIX2_FORT_RUN -1 /* fortran stuff */
#define _POSIX2_LOCALEDEF -1 /* localedef */
#define _POSIX2_PBS -1 /* batch stuff */
#define _POSIX2_PBS_ACCOUNTING -1 /* batch stuff */
#define _POSIX2_PBS_CHECKPOINT -1 /* batch stuff */
#define _POSIX2_PBS_LOCATE -1 /* batch stuff */
#define _POSIX2_PBS_MESSAGE -1 /* batch stuff */
#define _POSIX2_PBS_TRACK -1 /* batch stuff */
#define _POSIX2_SW_DEV -1 /* ar, make, nm, strip */
#define _POSIX2_UPE -1 /* bg, ex, fc, fg, jobs, more, talk, vi */
#define _XOPEN_CRYPT -1 /* crypt, encrypt, setkey */
#define _POSIX_THREADS -1
#define _POSIX_TIMEOUTS -1
#define _POSIX_TIMERS -1
#define _POSIX_TRACE -1
#define _POSIX_TRACE_EVENT_FILTER -1
#define _POSIX_TRACE_INHERIT -1
#define _POSIX_TRACE_LOG -1
#define _POSIX_TYPED_MEMORY_OBJECTS -1
#define _POSIX_V6_ILP32_OFF32 -1
#define _POSIX_V6_ILP32_OFFBIG -1
#define _POSIX_V6_LP64_OFF64 -1
#define _POSIX_V6_LPBIG_OFFBIG -1
#define _POSIX_V7_ILP32_OFF32 -1
#define _POSIX_V7_ILP32_OFFBIG -1
#define _POSIX_V7_LP64_OFF64 -1
#define _POSIX_V7_LPBIG_OFFBIG -1
#define _POSIX2_C_BIND -1
#define _POSIX2_C_DEV -1
#define _POSIX2_CHAR_TERM -1
#define _POSIX2_FORT_DEV -1
#define _POSIX2_FORT_RUN -1
#define _POSIX2_LOCALEDEF -1
#define _POSIX2_PBS -1
#define _POSIX2_PBS_ACCOUNTING -1
#define _POSIX2_PBS_CHECKPOINT -1
#define _POSIX2_PBS_LOCATE -1
#define _POSIX2_PBS_MESSAGE -1
#define _POSIX2_PBS_TRACK -1
#define _POSIX2_SW_DEV -1
#define _POSIX2_UPE -1
#define _XOPEN_CRYPT -1
#define _XOPEN_ENH_I18N -1
#define _XOPEN_REALTIME -1
#define _XOPEN_REALTIME_THREADS -1
#define _XOPEN_SHM -1
#define _XOPEN_STREAMS -1
#define _XOPEN_UNIX 200809L
#define _XOPEN_UNIX -1
#define _XOPEN_UUCP -1
#if defined(__x86_64__)
# define _POSIX_V6_ILP32_OFF32 -1
# define _POSIX_V6_ILP32_OFFBIG -1
# define _POSIX_V6_LP64_OFF64 1
# define _POSIX_V6_LPBIG_OFFBIG 1
# define _POSIX_V7_ILP32_OFF32 -1
# define _POSIX_V7_ILP32_OFFBIG -1
# define _POSIX_V7_LP64_OFF64 1
# define _POSIX_V7_LPBIG_OFFBIG 1
#elif defined(__i686__)
# define _POSIX_V6_ILP32_OFF32 1
# define _POSIX_V6_ILP32_OFFBIG -1
# define _POSIX_V6_LP64_OFF64 -1
# define _POSIX_V6_LPBIG_OFFBIG -1
# define _POSIX_V7_ILP32_OFF32 1
# define _POSIX_V7_ILP32_OFFBIG -1
# define _POSIX_V7_LP64_OFF64 -1
# define _POSIX_V7_LPBIG_OFFBIG -1
#else
#error "TODO: _POSIX_ compilation environment"
#endif
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
@ -124,370 +104,31 @@ __BEGIN_DECLS
#define __need_useconds_t
#include <sys/types.h>
enum
{
_CS_PATH = 1,
#define _CS_PATH _CS_PATH
_CS_POSIX_V6_ILP32_OFF32_CFLAGS,
#define _CS_POSIX_V6_ILP32_OFF32_CFLAGS _CS_POSIX_V6_ILP32_OFF32_CFLAGS
_CS_POSIX_V6_ILP32_OFF32_LDFLAGS,
#define _CS_POSIX_V6_ILP32_OFF32_LDFLAGS _CS_POSIX_V6_ILP32_OFF32_LDFLAGS
_CS_POSIX_V6_ILP32_OFF32_LIBS,
#define _CS_POSIX_V6_ILP32_OFF32_LIBS _CS_POSIX_V6_ILP32_OFF32_LIBS
_CS_POSIX_V6_ILP32_OFFBIG_CFLAGS,
#define _CS_POSIX_V6_ILP32_OFFBIG_CFLAGS _CS_POSIX_V6_ILP32_OFFBIG_CFLAGS
_CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS,
#define _CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS _CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS
_CS_POSIX_V6_ILP32_OFFBIG_LIBS,
#define _CS_POSIX_V6_ILP32_OFFBIG_LIBS _CS_POSIX_V6_ILP32_OFFBIG_LIBS
_CS_POSIX_V6_LP64_OFF64_CFLAGS,
#define _CS_POSIX_V6_LP64_OFF64_CFLAGS _CS_POSIX_V6_LP64_OFF64_CFLAGS
_CS_POSIX_V6_LP64_OFF64_LDFLAGS,
#define _CS_POSIX_V6_LP64_OFF64_LDFLAGS _CS_POSIX_V6_LP64_OFF64_LDFLAGS
_CS_POSIX_V6_LP64_OFF64_LIBS,
#define _CS_POSIX_V6_LP64_OFF64_LIBS _CS_POSIX_V6_LP64_OFF64_LIBS
_CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS,
#define _CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS _CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS
_CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS,
#define _CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS _CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS
_CS_POSIX_V6_LPBIG_OFFBIG_LIBS,
#define _CS_POSIX_V6_LPBIG_OFFBIG_LIBS _CS_POSIX_V6_LPBIG_OFFBIG_LIBS
_CS_POSIX_V6_WIDTH_RESTRICTED_ENVS,
#define _CS_POSIX_V6_WIDTH_RESTRICTED_ENVS _CS_POSIX_V6_WIDTH_RESTRICTED_ENVS
_CS_V6_ENV,
#define _CS_V6_ENV _CS_V6_ENV
_CS_POSIX_V7_ILP32_OFF32_CFLAGS,
#define _CS_POSIX_V7_ILP32_OFF32_CFLAGS _CS_POSIX_V7_ILP32_OFF32_CFLAGS
_CS_POSIX_V7_ILP32_OFF32_LDFLAGS,
#define _CS_POSIX_V7_ILP32_OFF32_LDFLAGS _CS_POSIX_V7_ILP32_OFF32_LDFLAGS
_CS_POSIX_V7_ILP32_OFF32_LIBS,
#define _CS_POSIX_V7_ILP32_OFF32_LIBS _CS_POSIX_V7_ILP32_OFF32_LIBS
_CS_POSIX_V7_ILP32_OFFBIG_CFLAGS,
#define _CS_POSIX_V7_ILP32_OFFBIG_CFLAGS _CS_POSIX_V7_ILP32_OFFBIG_CFLAGS
_CS_POSIX_V7_ILP32_OFFBIG_LDFLAGS,
#define _CS_POSIX_V7_ILP32_OFFBIG_LDFLAGS _CS_POSIX_V7_ILP32_OFFBIG_LDFLAGS
_CS_POSIX_V7_ILP32_OFFBIG_LIBS,
#define _CS_POSIX_V7_ILP32_OFFBIG_LIBS _CS_POSIX_V7_ILP32_OFFBIG_LIBS
_CS_POSIX_V7_LP64_OFF64_CFLAGS,
#define _CS_POSIX_V7_LP64_OFF64_CFLAGS _CS_POSIX_V7_LP64_OFF64_CFLAGS
_CS_POSIX_V7_LP64_OFF64_LDFLAGS,
#define _CS_POSIX_V7_LP64_OFF64_LDFLAGS _CS_POSIX_V7_LP64_OFF64_LDFLAGS
_CS_POSIX_V7_LP64_OFF64_LIBS,
#define _CS_POSIX_V7_LP64_OFF64_LIBS _CS_POSIX_V7_LP64_OFF64_LIBS
_CS_POSIX_V7_LPBIG_OFFBIG_CFLAGS,
#define _CS_POSIX_V7_LPBIG_OFFBIG_CFLAGS _CS_POSIX_V7_LPBIG_OFFBIG_CFLAGS
_CS_POSIX_V7_LPBIG_OFFBIG_LDFLAGS,
#define _CS_POSIX_V7_LPBIG_OFFBIG_LDFLAGS _CS_POSIX_V7_LPBIG_OFFBIG_LDFLAGS
_CS_POSIX_V7_LPBIG_OFFBIG_LIBS,
#define _CS_POSIX_V7_LPBIG_OFFBIG_LIBS _CS_POSIX_V7_LPBIG_OFFBIG_LIBS
_CS_POSIX_V7_THREADS_CFLAGS,
#define _CS_POSIX_V7_THREADS_CFLAGS _CS_POSIX_V7_THREADS_CFLAGS
_CS_POSIX_V7_THREADS_LDFLAGS,
#define _CS_POSIX_V7_THREADS_LDFLAGS _CS_POSIX_V7_THREADS_LDFLAGS
_CS_POSIX_V7_WIDTH_RESTRICTED_ENVS,
#define _CS_POSIX_V7_WIDTH_RESTRICTED_ENVS _CS_POSIX_V7_WIDTH_RESTRICTED_ENVS
_CS_V7_ENV,
#define _CS_V7_ENV _CS_V7_ENV
};
// FIXME: _CS prefixed definitions
enum
{
_PC_2_SYMLINKS = 1,
#define _PC_2_SYMLINKS _PC_2_SYMLINKS
_PC_2_SYMLINKS,
_PC_ALLOC_SIZE_MIN,
#define _PC_ALLOC_SIZE_MIN _PC_ALLOC_SIZE_MIN
_PC_ASYNC_IO,
#define _PC_ASYNC_IO _PC_ASYNC_IO
_PC_CHOWN_RESTRICTED,
#define _PC_CHOWN_RESTRICTED _PC_CHOWN_RESTRICTED
_PC_FILESIZEBITS,
#define _PC_FILESIZEBITS _PC_FILESIZEBITS
_PC_LINK_MAX,
#define _PC_LINK_MAX _PC_LINK_MAX
_PC_MAX_CANON,
#define _PC_MAX_CANON _PC_MAX_CANON
_PC_MAX_INPUT,
#define _PC_MAX_INPUT _PC_MAX_INPUT
_PC_NAME_MAX,
#define _PC_NAME_MAX _PC_NAME_MAX
_PC_NO_TRUNC,
#define _PC_NO_TRUNC _PC_NO_TRUNC
_PC_PATH_MAX,
#define _PC_PATH_MAX _PC_PATH_MAX
_PC_PIPE_BUF,
#define _PC_PIPE_BUF _PC_PIPE_BUF
_PC_PRIO_IO,
#define _PC_PRIO_IO _PC_PRIO_IO
_PC_REC_INCR_XFER_SIZE,
#define _PC_REC_INCR_XFER_SIZE _PC_REC_INCR_XFER_SIZE
_PC_REC_MAX_XFER_SIZE,
#define _PC_REC_MAX_XFER_SIZE _PC_REC_MAX_XFER_SIZE
_PC_REC_MIN_XFER_SIZE,
#define _PC_REC_MIN_XFER_SIZE _PC_REC_MIN_XFER_SIZE
_PC_REC_XFER_ALIGN,
#define _PC_REC_XFER_ALIGN _PC_REC_XFER_ALIGN
_PC_SYMLINK_MAX,
#define _PC_SYMLINK_MAX _PC_SYMLINK_MAX
_PC_SYNC_IO,
#define _PC_SYNC_IO _PC_SYNC_IO
_PC_TIMESTAMP_RESOLUTION,
#define _PC_TIMESTAMP_RESOLUTION _PC_TIMESTAMP_RESOLUTION
_PC_VDISABLE,
#define _PC_VDISABLE _PC_VDISABLE
};
enum
{
_SC_2_C_BIND = 1,
#define _SC_2_C_BIND _SC_2_C_BIND
_SC_2_C_DEV,
#define _SC_2_C_DEV _SC_2_C_DEV
_SC_2_CHAR_TERM,
#define _SC_2_CHAR_TERM _SC_2_CHAR_TERM
_SC_2_FORT_DEV,
#define _SC_2_FORT_DEV _SC_2_FORT_DEV
_SC_2_FORT_RUN,
#define _SC_2_FORT_RUN _SC_2_FORT_RUN
_SC_2_LOCALEDEF,
#define _SC_2_LOCALEDEF _SC_2_LOCALEDEF
_SC_2_PBS,
#define _SC_2_PBS _SC_2_PBS
_SC_2_PBS_ACCOUNTING,
#define _SC_2_PBS_ACCOUNTING _SC_2_PBS_ACCOUNTING
_SC_2_PBS_CHECKPOINT,
#define _SC_2_PBS_CHECKPOINT _SC_2_PBS_CHECKPOINT
_SC_2_PBS_LOCATE,
#define _SC_2_PBS_LOCATE _SC_2_PBS_LOCATE
_SC_2_PBS_MESSAGE,
#define _SC_2_PBS_MESSAGE _SC_2_PBS_MESSAGE
_SC_2_PBS_TRACK,
#define _SC_2_PBS_TRACK _SC_2_PBS_TRACK
_SC_2_SW_DEV,
#define _SC_2_SW_DEV _SC_2_SW_DEV
_SC_2_UPE,
#define _SC_2_UPE _SC_2_UPE
_SC_2_VERSION,
#define _SC_2_VERSION _SC_2_VERSION
_SC_ADVISORY_INFO,
#define _SC_ADVISORY_INFO _SC_ADVISORY_INFO
_SC_AIO_LISTIO_MAX,
#define _SC_AIO_LISTIO_MAX _SC_AIO_LISTIO_MAX
_SC_AIO_MAX,
#define _SC_AIO_MAX _SC_AIO_MAX
_SC_AIO_PRIO_DELTA_MAX,
#define _SC_AIO_PRIO_DELTA_MAX _SC_AIO_PRIO_DELTA_MAX
_SC_ARG_MAX,
#define _SC_ARG_MAX _SC_ARG_MAX
_SC_ASYNCHRONOUS_IO,
#define _SC_ASYNCHRONOUS_IO _SC_ASYNCHRONOUS_IO
_SC_ATEXIT_MAX,
#define _SC_ATEXIT_MAX _SC_ATEXIT_MAX
_SC_BARRIERS,
#define _SC_BARRIERS _SC_BARRIERS
_SC_BC_BASE_MAX,
#define _SC_BC_BASE_MAX _SC_BC_BASE_MAX
_SC_BC_DIM_MAX,
#define _SC_BC_DIM_MAX _SC_BC_DIM_MAX
_SC_BC_SCALE_MAX,
#define _SC_BC_SCALE_MAX _SC_BC_SCALE_MAX
_SC_BC_STRING_MAX,
#define _SC_BC_STRING_MAX _SC_BC_STRING_MAX
_SC_CHILD_MAX,
#define _SC_CHILD_MAX _SC_CHILD_MAX
_SC_CLK_TCK,
#define _SC_CLK_TCK _SC_CLK_TCK
_SC_CLOCK_SELECTION,
#define _SC_CLOCK_SELECTION _SC_CLOCK_SELECTION
_SC_COLL_WEIGHTS_MAX,
#define _SC_COLL_WEIGHTS_MAX _SC_COLL_WEIGHTS_MAX
_SC_CPUTIME,
#define _SC_CPUTIME _SC_CPUTIME
_SC_DELAYTIMER_MAX,
#define _SC_DELAYTIMER_MAX _SC_DELAYTIMER_MAX
_SC_EXPR_NEST_MAX,
#define _SC_EXPR_NEST_MAX _SC_EXPR_NEST_MAX
_SC_FSYNC,
#define _SC_FSYNC _SC_FSYNC
_SC_GETGR_R_SIZE_MAX,
#define _SC_GETGR_R_SIZE_MAX _SC_GETGR_R_SIZE_MAX
_SC_GETPW_R_SIZE_MAX,
#define _SC_GETPW_R_SIZE_MAX _SC_GETPW_R_SIZE_MAX
_SC_HOST_NAME_MAX,
#define _SC_HOST_NAME_MAX _SC_HOST_NAME_MAX
_SC_IOV_MAX,
#define _SC_IOV_MAX _SC_IOV_MAX
_SC_IPV6,
#define _SC_IPV6 _SC_IPV6
_SC_JOB_CONTROL,
#define _SC_JOB_CONTROL _SC_JOB_CONTROL
_SC_LINE_MAX,
#define _SC_LINE_MAX _SC_LINE_MAX
_SC_LOGIN_NAME_MAX,
#define _SC_LOGIN_NAME_MAX _SC_LOGIN_NAME_MAX
_SC_MAPPED_FILES,
#define _SC_MAPPED_FILES _SC_MAPPED_FILES
_SC_MEMLOCK,
#define _SC_MEMLOCK _SC_MEMLOCK
_SC_MEMLOCK_RANGE,
#define _SC_MEMLOCK_RANGE _SC_MEMLOCK_RANGE
_SC_MEMORY_PROTECTION,
#define _SC_MEMORY_PROTECTION _SC_MEMORY_PROTECTION
_SC_MESSAGE_PASSING,
#define _SC_MESSAGE_PASSING _SC_MESSAGE_PASSING
_SC_MONOTONIC_CLOCK,
#define _SC_MONOTONIC_CLOCK _SC_MONOTONIC_CLOCK
_SC_MQ_OPEN_MAX,
#define _SC_MQ_OPEN_MAX _SC_MQ_OPEN_MAX
_SC_MQ_PRIO_MAX,
#define _SC_MQ_PRIO_MAX _SC_MQ_PRIO_MAX
_SC_NGROUPS_MAX,
#define _SC_NGROUPS_MAX _SC_NGROUPS_MAX
_SC_OPEN_MAX,
#define _SC_OPEN_MAX _SC_OPEN_MAX
_SC_PAGE_SIZE,
#define _SC_PAGE_SIZE _SC_PAGE_SIZE
_SC_PAGESIZE,
#define _SC_PAGESIZE _SC_PAGESIZE
_SC_PRIORITIZED_IO,
#define _SC_PRIORITIZED_IO _SC_PRIORITIZED_IO
_SC_PRIORITY_SCHEDULING,
#define _SC_PRIORITY_SCHEDULING _SC_PRIORITY_SCHEDULING
_SC_RAW_SOCKETS,
#define _SC_RAW_SOCKETS _SC_RAW_SOCKETS
_SC_RE_DUP_MAX,
#define _SC_RE_DUP_MAX _SC_RE_DUP_MAX
_SC_READER_WRITER_LOCKS,
#define _SC_READER_WRITER_LOCKS _SC_READER_WRITER_LOCKS
_SC_REALTIME_SIGNALS,
#define _SC_REALTIME_SIGNALS _SC_REALTIME_SIGNALS
_SC_REGEXP,
#define _SC_REGEXP _SC_REGEXP
_SC_RTSIG_MAX,
#define _SC_RTSIG_MAX _SC_RTSIG_MAX
_SC_SAVED_IDS,
#define _SC_SAVED_IDS _SC_SAVED_IDS
_SC_SEM_NSEMS_MAX,
#define _SC_SEM_NSEMS_MAX _SC_SEM_NSEMS_MAX
_SC_SEM_VALUE_MAX,
#define _SC_SEM_VALUE_MAX _SC_SEM_VALUE_MAX
_SC_SEMAPHORES,
#define _SC_SEMAPHORES _SC_SEMAPHORES
_SC_SHARED_MEMORY_OBJECTS,
#define _SC_SHARED_MEMORY_OBJECTS _SC_SHARED_MEMORY_OBJECTS
_SC_SHELL,
#define _SC_SHELL _SC_SHELL
_SC_SIGQUEUE_MAX,
#define _SC_SIGQUEUE_MAX _SC_SIGQUEUE_MAX
_SC_SPAWN,
#define _SC_SPAWN _SC_SPAWN
_SC_SPIN_LOCKS,
#define _SC_SPIN_LOCKS _SC_SPIN_LOCKS
_SC_SPORADIC_SERVER,
#define _SC_SPORADIC_SERVER _SC_SPORADIC_SERVER
_SC_SS_REPL_MAX,
#define _SC_SS_REPL_MAX _SC_SS_REPL_MAX
_SC_STREAM_MAX,
#define _SC_STREAM_MAX _SC_STREAM_MAX
_SC_SYMLOOP_MAX,
#define _SC_SYMLOOP_MAX _SC_SYMLOOP_MAX
_SC_SYNCHRONIZED_IO,
#define _SC_SYNCHRONIZED_IO _SC_SYNCHRONIZED_IO
_SC_THREAD_ATTR_STACKADDR,
#define _SC_THREAD_ATTR_STACKADDR _SC_THREAD_ATTR_STACKADDR
_SC_THREAD_ATTR_STACKSIZE,
#define _SC_THREAD_ATTR_STACKSIZE _SC_THREAD_ATTR_STACKSIZE
_SC_THREAD_CPUTIME,
#define _SC_THREAD_CPUTIME _SC_THREAD_CPUTIME
_SC_THREAD_DESTRUCTOR_ITERATIONS,
#define _SC_THREAD_DESTRUCTOR_ITERATIONS _SC_THREAD_DESTRUCTOR_ITERATIONS
_SC_THREAD_KEYS_MAX,
#define _SC_THREAD_KEYS_MAX _SC_THREAD_KEYS_MAX
_SC_THREAD_PRIO_INHERIT,
#define _SC_THREAD_PRIO_INHERIT _SC_THREAD_PRIO_INHERIT
_SC_THREAD_PRIO_PROTECT,
#define _SC_THREAD_PRIO_PROTECT _SC_THREAD_PRIO_PROTECT
_SC_THREAD_PRIORITY_SCHEDULING,
#define _SC_THREAD_PRIORITY_SCHEDULING _SC_THREAD_PRIORITY_SCHEDULING
_SC_THREAD_PROCESS_SHARED,
#define _SC_THREAD_PROCESS_SHARED _SC_THREAD_PROCESS_SHARED
_SC_THREAD_ROBUST_PRIO_INHERIT,
#define _SC_THREAD_ROBUST_PRIO_INHERIT _SC_THREAD_ROBUST_PRIO_INHERIT
_SC_THREAD_ROBUST_PRIO_PROTECT,
#define _SC_THREAD_ROBUST_PRIO_PROTECT _SC_THREAD_ROBUST_PRIO_PROTECT
_SC_THREAD_SAFE_FUNCTIONS,
#define _SC_THREAD_SAFE_FUNCTIONS _SC_THREAD_SAFE_FUNCTIONS
_SC_THREAD_SPORADIC_SERVER,
#define _SC_THREAD_SPORADIC_SERVER _SC_THREAD_SPORADIC_SERVER
_SC_THREAD_STACK_MIN,
#define _SC_THREAD_STACK_MIN _SC_THREAD_STACK_MIN
_SC_THREAD_THREADS_MAX,
#define _SC_THREAD_THREADS_MAX _SC_THREAD_THREADS_MAX
_SC_THREADS,
#define _SC_THREADS _SC_THREADS
_SC_TIMEOUTS,
#define _SC_TIMEOUTS _SC_TIMEOUTS
_SC_TIMER_MAX,
#define _SC_TIMER_MAX _SC_TIMER_MAX
_SC_TIMERS,
#define _SC_TIMERS _SC_TIMERS
_SC_TRACE,
#define _SC_TRACE _SC_TRACE
_SC_TRACE_EVENT_FILTER,
#define _SC_TRACE_EVENT_FILTER _SC_TRACE_EVENT_FILTER
_SC_TRACE_EVENT_NAME_MAX,
#define _SC_TRACE_EVENT_NAME_MAX _SC_TRACE_EVENT_NAME_MAX
_SC_TRACE_INHERIT,
#define _SC_TRACE_INHERIT _SC_TRACE_INHERIT
_SC_TRACE_LOG,
#define _SC_TRACE_LOG _SC_TRACE_LOG
_SC_TRACE_NAME_MAX,
#define _SC_TRACE_NAME_MAX _SC_TRACE_NAME_MAX
_SC_TRACE_SYS_MAX,
#define _SC_TRACE_SYS_MAX _SC_TRACE_SYS_MAX
_SC_TRACE_USER_EVENT_MAX,
#define _SC_TRACE_USER_EVENT_MAX _SC_TRACE_USER_EVENT_MAX
_SC_TTY_NAME_MAX,
#define _SC_TTY_NAME_MAX _SC_TTY_NAME_MAX
_SC_TYPED_MEMORY_OBJECTS,
#define _SC_TYPED_MEMORY_OBJECTS _SC_TYPED_MEMORY_OBJECTS
_SC_TZNAME_MAX,
#define _SC_TZNAME_MAX _SC_TZNAME_MAX
_SC_V7_ILP32_OFF32,
#define _SC_V7_ILP32_OFF32 _SC_V7_ILP32_OFF32
_SC_V7_ILP32_OFFBIG,
#define _SC_V7_ILP32_OFFBIG _SC_V7_ILP32_OFFBIG
_SC_V7_LP64_OFF64,
#define _SC_V7_LP64_OFF64 _SC_V7_LP64_OFF64
_SC_V7_LPBIG_OFFBIG,
#define _SC_V7_LPBIG_OFFBIG _SC_V7_LPBIG_OFFBIG
_SC_V6_ILP32_OFF32,
#define _SC_V6_ILP32_OFF32 _SC_V6_ILP32_OFF32
_SC_V6_ILP32_OFFBIG,
#define _SC_V6_ILP32_OFFBIG _SC_V6_ILP32_OFFBIG
_SC_V6_LP64_OFF64,
#define _SC_V6_LP64_OFF64 _SC_V6_LP64_OFF64
_SC_V6_LPBIG_OFFBIG,
#define _SC_V6_LPBIG_OFFBIG _SC_V6_LPBIG_OFFBIG
_SC_VERSION,
#define _SC_VERSION _SC_VERSION
_SC_XOPEN_CRYPT,
#define _SC_XOPEN_CRYPT _SC_XOPEN_CRYPT
_SC_XOPEN_ENH_I18N,
#define _SC_XOPEN_ENH_I18N _SC_XOPEN_ENH_I18N
_SC_XOPEN_REALTIME,
#define _SC_XOPEN_REALTIME _SC_XOPEN_REALTIME
_SC_XOPEN_REALTIME_THREADS,
#define _SC_XOPEN_REALTIME_THREADS _SC_XOPEN_REALTIME_THREADS
_SC_XOPEN_SHM,
#define _SC_XOPEN_SHM _SC_XOPEN_SHM
_SC_XOPEN_STREAMS,
#define _SC_XOPEN_STREAMS _SC_XOPEN_STREAMS
_SC_XOPEN_UNIX,
#define _SC_XOPEN_UNIX _SC_XOPEN_UNIX
_SC_XOPEN_UUCP,
#define _SC_XOPEN_UUCP _SC_XOPEN_UUCP
_SC_XOPEN_VERSION,
#define _SC_XOPEN_VERSION _SC_XOPEN_VERSION
};
#define F_OK 0x01

View File

@ -30,7 +30,7 @@ typedef __WINT_TYPE__ wint_t;
wint_t btowc(int c);
wint_t fgetwc(FILE* stream);
wchar_t* fgetws(wchar_t* __restrict ws, int n, FILE* __restrict stream);
wint_t fputwc(wchar_t wc, FILE* stream);
wint_t fputwc(wchar_t c, FILE* stream);
int fputws(const wchar_t* __restrict ws, FILE* __restrict stream);
int fwide(FILE* stream, int mode);
int fwprintf(FILE* __restrict stream, const wchar_t* __restrict format, ...);

View File

@ -1,22 +1,56 @@
#include <poll.h>
#include <pthread.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <sys/select.h>
int poll(struct pollfd fds[], nfds_t nfds, int timeout)
{
pthread_testcancel();
if (timeout < 0)
return ppoll(fds, nfds, nullptr, nullptr);
const timespec timeout_ts {
.tv_sec = static_cast<time_t>(timeout / 1000),
.tv_nsec = static_cast<long>(timeout % 1000),
};
return ppoll(fds, nfds, &timeout_ts, nullptr);
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;
}
int ppoll(struct pollfd fds[], nfds_t nfds, const struct timespec* timeout, const sigset_t* sigmask)
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++)
{
pthread_testcancel();
return syscall(SYS_PPOLL, fds, nfds, timeout, sigmask);
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;
}

View File

@ -4,7 +4,6 @@
#include <BAN/PlacementNew.h>
#include <kernel/Arch.h>
#include <kernel/Thread.h>
#include <errno.h>
#include <pthread.h>
@ -47,14 +46,13 @@ asm(
extern "C" void _pthread_trampoline_cpp(void* arg)
{
auto info = *reinterpret_cast<pthread_trampoline_info_t*>(arg);
info.uthread->id = syscall(SYS_PTHREAD_SELF);
syscall(SYS_SET_TLS, info.uthread);
free(arg);
pthread_exit(info.start_routine(info.arg));
ASSERT_NOT_REACHED();
}
uthread* _get_uthread()
static uthread* get_uthread()
{
uthread* result;
#if ARCH(x86_64)
@ -77,13 +75,22 @@ static void free_uthread(uthread* uthread)
munmap(tls_addr, tls_size);
}
#if not __disable_thread_local_storage
struct pthread_cleanup_t
{
void (*routine)(void*);
void* arg;
pthread_cleanup_t* next;
};
static thread_local pthread_cleanup_t* s_cleanup_stack = nullptr;
void pthread_cleanup_pop(int execute)
{
uthread* uthread = _get_uthread();
ASSERT(uthread->cleanup_stack);
ASSERT(s_cleanup_stack);
auto* cleanup = uthread->cleanup_stack;
uthread->cleanup_stack = cleanup->next;
auto* cleanup = s_cleanup_stack;
s_cleanup_stack = cleanup->next;
if (execute)
cleanup->routine(cleanup->arg);
@ -93,17 +100,16 @@ void pthread_cleanup_pop(int execute)
void pthread_cleanup_push(void (*routine)(void*), void* arg)
{
auto* cleanup = static_cast<_pthread_cleanup_t*>(malloc(sizeof(_pthread_cleanup_t)));
auto* cleanup = static_cast<pthread_cleanup_t*>(malloc(sizeof(pthread_cleanup_t)));
ASSERT(cleanup);
uthread* uthread = _get_uthread();
cleanup->routine = routine;
cleanup->arg = arg;
cleanup->next = uthread->cleanup_stack;
cleanup->next = s_cleanup_stack;
uthread->cleanup_stack = cleanup;
s_cleanup_stack = cleanup;
}
#endif
#if not __disable_thread_local_storage
static thread_local struct {
@ -169,148 +175,38 @@ int pthread_attr_destroy(pthread_attr_t* attr)
int pthread_attr_init(pthread_attr_t* attr)
{
*attr = {
.inheritsched = PTHREAD_INHERIT_SCHED,
.schedparam = {},
.schedpolicy = SCHED_RR,
.detachstate = PTHREAD_CREATE_JOINABLE,
.scope = PTHREAD_SCOPE_SYSTEM,
.stacksize = Kernel::Thread::userspace_stack_size,
.guardsize = static_cast<size_t>(getpagesize()),
};
*attr = 0;
return 0;
}
int pthread_attr_setstacksize(pthread_attr_t* attr, size_t stacksize)
{
(void)attr;
(void)stacksize;
dwarnln("TODO: ignoring pthread_attr_setstacksize");
return 0;
}
int pthread_attr_getdetachstate(const pthread_attr_t* attr, int* detachstate)
{
*detachstate = attr->detachstate;
(void)attr;
*detachstate = PTHREAD_CREATE_JOINABLE;
return 0;
}
int pthread_attr_setdetachstate(pthread_attr_t* attr, int detachstate)
{
(void)attr;
switch (detachstate)
{
case PTHREAD_CREATE_DETACHED:
dwarnln("TODO: pthread_attr_setdetachstate");
return ENOTSUP;
case PTHREAD_CREATE_JOINABLE:
attr->detachstate = detachstate;
return 0;
}
default:
return EINVAL;
}
int pthread_attr_getguardsize(const pthread_attr_t* __restrict attr, size_t* __restrict guardsize)
{
*guardsize = attr->guardsize;
return 0;
}
int pthread_attr_setguardsize(pthread_attr_t* attr, size_t guardsize)
{
attr->guardsize = guardsize;
return 0;
}
int pthread_attr_getinheritsched(const pthread_attr_t* __restrict attr, int* __restrict inheritsched)
{
*inheritsched = attr->inheritsched;
return 0;
}
int pthread_attr_setinheritsched(pthread_attr_t* attr, int inheritsched)
{
switch (inheritsched)
{
case PTHREAD_INHERIT_SCHED:
case PTHREAD_EXPLICIT_SCHED:
attr->inheritsched = inheritsched;
return 0;
}
return EINVAL;
}
int pthread_attr_getschedparam(const pthread_attr_t* __restrict attr, struct sched_param* __restrict param)
{
*param = attr->schedparam;
return 0;
}
int pthread_attr_setschedparam(pthread_attr_t* __restrict attr, const struct sched_param* __restrict param)
{
attr->schedparam = *param;
return 0;
}
int pthread_attr_getschedpolicy(const pthread_attr_t* __restrict attr, int* __restrict policy)
{
*policy = attr->schedpolicy;
return 0;
}
int pthread_attr_setschedpolicy(pthread_attr_t* attr, int policy)
{
switch (policy)
{
case SCHED_FIFO:
case SCHED_SPORADIC:
case SCHED_OTHER:
return ENOTSUP;
case SCHED_RR:
attr->schedpolicy = policy;
return 0;
}
return EINVAL;
}
int pthread_attr_getscope(const pthread_attr_t* __restrict attr, int* __restrict contentionscope)
{
*contentionscope = attr->scope;
return 0;
}
int pthread_attr_setscope(pthread_attr_t* attr, int contentionscope)
{
switch (contentionscope)
{
case PTHREAD_SCOPE_PROCESS:
return ENOTSUP;
case PTHREAD_SCOPE_SYSTEM:
attr->scope = contentionscope;
return 0;
}
return EINVAL;
}
int pthread_attr_getstack(const pthread_attr_t* __restrict attr, void** __restrict stackaddr, size_t* __restrict stacksize)
{
(void)attr;
(void)stackaddr;
(void)stacksize;
dwarnln("TODO: pthread_attr_getstack");
return ENOTSUP;
}
int pthread_attr_setstack(pthread_attr_t* attr, void* stackaddr, size_t stacksize)
{
(void)attr;
(void)stackaddr;
(void)stacksize;
dwarnln("TODO: pthread_attr_setstack");
return ENOTSUP;
}
int pthread_attr_getstacksize(const pthread_attr_t* __restrict attr, size_t* __restrict stacksize)
{
*stacksize = attr->stacksize;
return 0;
}
int pthread_attr_setstacksize(pthread_attr_t* attr, size_t stacksize)
{
attr->stacksize = stacksize;
return 0;
}
int pthread_create(pthread_t* __restrict thread_id, const pthread_attr_t* __restrict attr, void* (*start_routine)(void*), void* __restrict arg)
@ -327,23 +223,14 @@ int pthread_create(pthread_t* __restrict thread_id, const pthread_attr_t* __rest
long syscall_ret = 0;
if (uthread* self = _get_uthread(); self->master_tls_addr == nullptr)
if (uthread* self = get_uthread(); self->master_tls_addr == nullptr)
{
uthread* uthread = static_cast<struct uthread*>(malloc(sizeof(struct uthread) + sizeof(uintptr_t)));
if (uthread == nullptr)
goto pthread_create_error;
*uthread = {
.self = uthread,
.master_tls_addr = nullptr,
.master_tls_size = 0,
.cleanup_stack = nullptr,
.id = -1,
.errno_ = 0,
.cancel_type = PTHREAD_CANCEL_DEFERRED,
.cancel_state = PTHREAD_CANCEL_ENABLE,
.canceled = false,
};
uthread->self = uthread;
uthread->master_tls_addr = nullptr;
uthread->master_tls_size = 0;
uthread->dtv[0] = 0;
info->uthread = uthread;
@ -362,17 +249,9 @@ int pthread_create(pthread_t* __restrict thread_id, const pthread_attr_t* __rest
memcpy(tls_addr, self->master_tls_addr, self->master_tls_size);
uthread* uthread = reinterpret_cast<struct uthread*>(tls_addr + self->master_tls_size);
*uthread = {
.self = uthread,
.master_tls_addr = self->master_tls_addr,
.master_tls_size = self->master_tls_size,
.cleanup_stack = nullptr,
.id = -1,
.errno_ = 0,
.cancel_type = PTHREAD_CANCEL_DEFERRED,
.cancel_state = PTHREAD_CANCEL_ENABLE,
.canceled = 0,
};
uthread->self = uthread;
uthread->master_tls_addr = self->master_tls_addr;
uthread->master_tls_size = self->master_tls_size;
const uintptr_t self_addr = reinterpret_cast<uintptr_t>(self);
const uintptr_t uthread_addr = reinterpret_cast<uintptr_t>(uthread);
@ -409,11 +288,9 @@ int pthread_detach(pthread_t thread)
void pthread_exit(void* value_ptr)
{
uthread* uthread = _get_uthread();
while (uthread->cleanup_stack)
pthread_cleanup_pop(1);
#if not __disable_thread_local_storage
while (s_cleanup_stack)
pthread_cleanup_pop(1);
for (size_t iteration = 0; iteration < PTHREAD_DESTRUCTOR_ITERATIONS; iteration++)
{
bool called = false;
@ -432,8 +309,7 @@ void pthread_exit(void* value_ptr)
break;
}
#endif
free_uthread(uthread);
free_uthread(get_uthread());
syscall(SYS_PTHREAD_EXIT, value_ptr);
ASSERT_NOT_REACHED();
}
@ -445,13 +321,19 @@ int pthread_equal(pthread_t t1, pthread_t t2)
int pthread_join(pthread_t thread, void** value_ptr)
{
pthread_testcancel();
return syscall(SYS_PTHREAD_JOIN, thread, value_ptr);
}
pthread_t pthread_self(void)
{
return _get_uthread()->id;
#if __disable_thread_local_storage
return syscall(SYS_PTHREAD_SELF);
#else
static thread_local pthread_t s_pthread_self { -1 };
if (s_pthread_self == -1) [[unlikely]]
s_pthread_self = syscall(SYS_PTHREAD_SELF);
return s_pthread_self;
#endif
}
int pthread_once(pthread_once_t* once_control, void (*init_routine)(void))
@ -470,168 +352,6 @@ int pthread_once(pthread_once_t* once_control, void (*init_routine)(void))
return 0;
}
struct pthread_atfork_t
{
void (*function)();
pthread_atfork_t* next;
};
static pthread_atfork_t* s_atfork_prepare = nullptr;
static pthread_atfork_t* s_atfork_parent = nullptr;
static pthread_atfork_t* s_atfork_child = nullptr;
static pthread_mutex_t s_atfork_mutex = PTHREAD_MUTEX_INITIALIZER;
void _pthread_call_atfork(int state)
{
pthread_mutex_lock(&s_atfork_mutex);
pthread_atfork_t* list = nullptr;
switch (state)
{
case _PTHREAD_ATFORK_PREPARE: list = s_atfork_prepare; break;
case _PTHREAD_ATFORK_PARENT: list = s_atfork_parent; break;
case _PTHREAD_ATFORK_CHILD: list = s_atfork_child; break;
default:
ASSERT_NOT_REACHED();
}
for (; list; list = list->next)
list->function();
pthread_mutex_unlock(&s_atfork_mutex);
}
int pthread_atfork(void (*prepare)(void), void (*parent)(void), void(*child)(void))
{
pthread_atfork_t* prepare_entry = nullptr;
if (prepare != nullptr)
prepare_entry = static_cast<pthread_atfork_t*>(malloc(sizeof(pthread_attr_t)));
pthread_atfork_t* parent_entry = nullptr;
if (parent != nullptr)
parent_entry = static_cast<pthread_atfork_t*>(malloc(sizeof(pthread_attr_t)));
pthread_atfork_t* child_entry = nullptr;
if (child != nullptr)
child_entry = static_cast<pthread_atfork_t*>(malloc(sizeof(pthread_attr_t)));
if ((prepare && !prepare_entry) || (parent && !parent_entry) || (child && !child_entry))
{
if (prepare_entry)
free(prepare_entry);
if (parent_entry)
free(parent_entry);
if (child_entry)
free(child_entry);
return ENOMEM;
}
const auto prepend_atfork =
[](pthread_atfork_t*& list, pthread_atfork_t* entry)
{
entry->next = list;
list = entry;
};
const auto append_atfork =
[](pthread_atfork_t*& list, pthread_atfork_t* entry)
{
while (list)
list = list->next;
entry->next = nullptr;
list = entry;
};
pthread_mutex_lock(&s_atfork_mutex);
if (prepare_entry)
{
prepare_entry->function = prepare;
prepend_atfork(s_atfork_prepare, prepare_entry);
}
if (parent_entry)
{
parent_entry->function = parent;
append_atfork(s_atfork_parent, parent_entry);
}
if (child_entry)
{
child_entry->function = parent;
append_atfork(s_atfork_child, child_entry);
}
pthread_mutex_unlock(&s_atfork_mutex);
return 0;
}
static void pthread_cancel_handler(int)
{
uthread* uthread = _get_uthread();
BAN::atomic_store(uthread->canceled, true);
if (BAN::atomic_load(uthread->cancel_state) != PTHREAD_CANCEL_ENABLE)
return;
switch (BAN::atomic_load(uthread->cancel_type))
{
case PTHREAD_CANCEL_ASYNCHRONOUS:
pthread_exit(PTHREAD_CANCELED);
case PTHREAD_CANCEL_DEFERRED:
return;
}
ASSERT_NOT_REACHED();
}
int pthread_cancel(pthread_t thread)
{
signal(SIGCANCEL, &pthread_cancel_handler);
return pthread_kill(thread, SIGCANCEL);
}
int pthread_setcancelstate(int state, int* oldstate)
{
switch (state)
{
case PTHREAD_CANCEL_ENABLE:
case PTHREAD_CANCEL_DISABLE:
break;
default:
return EINVAL;
}
BAN::atomic_exchange(_get_uthread()->cancel_state, state);
if (oldstate)
*oldstate = state;
return 0;
}
int pthread_setcanceltype(int type, int* oldtype)
{
switch (type)
{
case PTHREAD_CANCEL_DEFERRED:
case PTHREAD_CANCEL_ASYNCHRONOUS:
break;
default:
return EINVAL;
}
BAN::atomic_exchange(_get_uthread()->cancel_type, type);
if (oldtype)
*oldtype = type;
return 0;
}
void pthread_testcancel(void)
{
uthread* uthread = _get_uthread();
if (BAN::atomic_load(uthread->cancel_state) != PTHREAD_CANCEL_ENABLE)
return;
if (!BAN::atomic_load(uthread->canceled))
return;
pthread_exit(PTHREAD_CANCELED);
}
int pthread_spin_destroy(pthread_spinlock_t* lock)
{
(void)lock;
@ -1012,7 +732,7 @@ int pthread_condattr_getpshared(const pthread_condattr_t* __restrict attr, int*
return 0;
}
int pthread_condattr_setpshared(pthread_condattr_t* attr, int pshared)
int pthread_condattr_setpshared(pthread_barrierattr_t* attr, int pshared)
{
switch (pshared)
{
@ -1068,14 +788,11 @@ int pthread_cond_signal(pthread_cond_t* cond)
int pthread_cond_wait(pthread_cond_t* __restrict cond, pthread_mutex_t* __restrict mutex)
{
// pthread_testcancel in pthread_cond_timedwait
return pthread_cond_timedwait(cond, mutex, nullptr);
}
int pthread_cond_timedwait(pthread_cond_t* __restrict cond, pthread_mutex_t* __restrict mutex, const struct timespec* __restrict abstime)
{
pthread_testcancel();
constexpr auto has_timed_out =
[](const struct timespec* abstime, clockid_t clock_id) -> bool
{
@ -1208,7 +925,7 @@ struct tls_index
extern "C" void* __tls_get_addr(tls_index* ti)
{
return reinterpret_cast<void*>(_get_uthread()->dtv[ti->ti_module] + ti->ti_offset);
return reinterpret_cast<void*>(get_uthread()->dtv[ti->ti_module] + ti->ti_offset);
}
#if ARCH(i686)

View File

@ -38,18 +38,9 @@ void psignal(int signum, const char* message)
fprintf(stderr, "%s\n", strsignal(signum));
}
int pthread_kill(pthread_t thread, int sig)
{
if (syscall(SYS_PTHREAD_KILL, thread, sig) == -1)
return errno;
return 0;
}
int pthread_sigmask(int how, const sigset_t* __restrict set, sigset_t* __restrict oset)
{
if (syscall(SYS_SIGPROCMASK, how, set, oset) == -1)
return errno;
return 0;
return syscall(SYS_SIGPROCMASK, how, set, oset);
}
int raise(int sig)
@ -147,12 +138,7 @@ int sigpending(sigset_t* set)
int sigprocmask(int how, const sigset_t* __restrict set, sigset_t* __restrict oset)
{
if (int error = pthread_sigmask(how, set, oset))
{
errno = error;
return -1;
}
return 0;
return pthread_sigmask(how, set, oset);
}
int sigrelse(int sig)

View File

@ -190,8 +190,6 @@ int strcoll_l(const char *s1, const char *s2, locale_t locale)
u1 += BAN::UTF8::byte_length(*u1);
u2 += BAN::UTF8::byte_length(*u2);
}
// TODO: this isn't really correct :D
return wc1 - wc2;
}
}
@ -366,19 +364,6 @@ char* strtok_r(char* __restrict str, const char* __restrict sep, char** __restri
#undef CHAR_BITMASK
#undef CHAR_BITMASK_TEST
size_t strxfrm(char* __restrict s1, const char* __restrict s2, size_t n)
{
return strxfrm_l(s1, s2, n, __getlocale(LC_COLLATE));
}
size_t strxfrm_l(char* __restrict s1, const char* __restrict s2, size_t n, locale_t locale)
{
(void)locale;
// TODO: this isn't really correct :D
strncpy(s1, s2, n);
return strlen(s2);
}
char* strsignal(int signum)
{
static char buffer[128];

View File

@ -1,4 +1,3 @@
#include <pthread.h>
#include <sys/mman.h>
#include <sys/syscall.h>
#include <unistd.h>
@ -26,7 +25,6 @@ int munmap(void* addr, size_t len)
int msync(void* addr, size_t len, int flags)
{
pthread_testcancel();
return syscall(SYS_MSYNC, addr, len, flags);
}

View File

@ -1,11 +1,9 @@
#include <pthread.h>
#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)
{
pthread_testcancel();
sys_pselect_t arguments {
.nfds = nfds,
.readfds = readfds,
@ -19,7 +17,6 @@ int pselect(int nfds, fd_set* __restrict readfds, fd_set* __restrict writefds, f
int select(int nfds, fd_set* __restrict readfds, fd_set* __restrict writefds, fd_set* __restrict errorfds, struct timeval* __restrict timeout)
{
pthread_testcancel();
timespec* pts = nullptr;
timespec ts;
if (timeout)

View File

@ -1,17 +1,14 @@
#include <pthread.h>
#include <sys/socket.h>
#include <sys/syscall.h>
#include <unistd.h>
int accept(int socket, struct sockaddr* __restrict address, socklen_t* __restrict address_len)
{
pthread_testcancel();
return accept4(socket, address, address_len, 0);
}
int accept4(int socket, struct sockaddr* __restrict address, socklen_t* __restrict address_len, int flags)
{
pthread_testcancel();
return syscall(SYS_ACCEPT, socket, address, address_len, flags);
}
@ -22,7 +19,6 @@ int bind(int socket, const struct sockaddr* address, socklen_t address_len)
int connect(int socket, const struct sockaddr* address, socklen_t address_len)
{
pthread_testcancel();
return syscall(SYS_CONNECT, socket, address, address_len);
}
@ -33,13 +29,11 @@ int listen(int socket, int backlog)
ssize_t recv(int socket, void* __restrict buffer, size_t length, int flags)
{
pthread_testcancel();
return recvfrom(socket, buffer, length, flags, nullptr, nullptr);
}
ssize_t recvfrom(int socket, void* __restrict buffer, size_t length, int flags, struct sockaddr* __restrict address, socklen_t* __restrict address_len)
{
pthread_testcancel();
sys_recvfrom_t arguments {
.socket = socket,
.buffer = buffer,
@ -53,13 +47,11 @@ ssize_t recvfrom(int socket, void* __restrict buffer, size_t length, int flags,
ssize_t send(int socket, const void* message, size_t length, int flags)
{
pthread_testcancel();
return sendto(socket, message, length, flags, nullptr, 0);
}
ssize_t sendto(int socket, const void* message, size_t length, int flags, const struct sockaddr* dest_addr, socklen_t dest_len)
{
pthread_testcancel();
sys_sendto_t arguments {
.socket = socket,
.message = message,

View File

@ -53,13 +53,3 @@ int mkdir(const char* path, mode_t mode)
{
return syscall(SYS_CREATE_DIR, path, __UMASKED_MODE(mode));
}
int futimens(int fd, const struct timespec times[2])
{
return utimensat(fd, nullptr, times, 0);
}
int utimensat(int fd, const char* path, const struct timespec times[2], int flag)
{
return syscall(SYS_UTIMENSAT, fd, path, times, flag);
}

View File

@ -1,4 +1,3 @@
#include <fcntl.h>
#include <sys/syscall.h>
#include <sys/time.h>
#include <time.h>
@ -27,20 +26,3 @@ int setitimer(int which, const struct itimerval* __restrict value, struct itimer
{
return syscall(SYS_SETITIMER, which, value, ovalue);
}
int utimes(const char* path, const struct timeval times[2])
{
if (times == nullptr)
return utimensat(AT_FDCWD, path, nullptr, 0);
const timespec times_ts[2] {
timespec {
.tv_sec = times[0].tv_sec,
.tv_nsec = times[0].tv_usec * 1000,
},
timespec {
.tv_sec = times[1].tv_sec,
.tv_nsec = times[1].tv_usec * 1000,
},
};
return utimensat(AT_FDCWD, path, times_ts, 0);
}

View File

@ -1,11 +1,8 @@
#include <pthread.h>
#include <sys/uio.h>
#include <unistd.h>
ssize_t readv(int fildes, const struct iovec* iov, int iovcnt)
{
pthread_testcancel();
size_t result = 0;
for (int i = 0; i < iovcnt; i++)
{
@ -28,8 +25,6 @@ ssize_t readv(int fildes, const struct iovec* iov, int iovcnt)
ssize_t writev(int fildes, const struct iovec* iov, int iovcnt)
{
pthread_testcancel();
size_t result = 0;
for (int i = 0; i < iovcnt; i++)
{

View File

@ -1,16 +1,13 @@
#include <pthread.h>
#include <sys/syscall.h>
#include <sys/wait.h>
#include <unistd.h>
pid_t wait(int* stat_loc)
{
pthread_testcancel();
return waitpid(-1, stat_loc, 0);
}
pid_t waitpid(pid_t pid, int* stat_loc, int options)
{
pthread_testcancel();
return (pid_t)syscall(SYS_WAIT, pid, stat_loc, options);
}

View File

@ -2,7 +2,6 @@
#include <BAN/Debug.h>
#include <errno.h>
#include <pthread.h>
#include <sys/syscall.h>
#include <termios.h>
#include <unistd.h>
@ -65,19 +64,9 @@ int cfsetospeed(struct termios* termios, speed_t speed)
return 0;
}
int tcdrain(int fd)
{
pthread_testcancel();
int tcdrain(int);
dwarnln("TODO: tcdrain({})", fd);
return 0;
}
int tcflow(int fd, int action)
{
dwarnln("TODO: tcflow({}, {})", fd, action);
return -1;
}
int tcflow(int, int);
int tcflush(int fd, int queue_selector)
{
@ -92,11 +81,7 @@ int tcgetattr(int fildes, struct termios* termios)
pid_t tcgetsid(int);
int tcsendbreak(int fd, int duration)
{
dwarnln("FIXME: tcsendbreak({}, {})", fd, duration);
return -1;
}
int tcsendbreak(int, int);
int tcsetattr(int fildes, int optional_actions, const struct termios* termios)
{

View File

@ -4,7 +4,6 @@
#include <ctype.h>
#include <errno.h>
#include <langinfo.h>
#include <pthread.h>
#include <string.h>
#include <sys/syscall.h>
#include <time.h>
@ -21,7 +20,6 @@ int clock_gettime(clockid_t clock_id, struct timespec* tp)
int nanosleep(const struct timespec* rqtp, struct timespec* rmtp)
{
pthread_testcancel();
return syscall(SYS_NANOSLEEP, rqtp, rmtp);
}

View File

@ -34,16 +34,7 @@ extern "C" void _init_libc(char** environ, init_funcs_t init_funcs, init_funcs_t
if (::environ == nullptr)
::environ = environ;
if (uthread* self = reinterpret_cast<uthread*>(syscall(SYS_GET_TLS)))
{
self->cleanup_stack = nullptr;
self->id = syscall(SYS_PTHREAD_SELF);
self->errno_ = 0;
self->cancel_type = PTHREAD_CANCEL_DEFERRED;
self->cancel_state = PTHREAD_CANCEL_ENABLE;
self->canceled = false;
}
else
if (syscall(SYS_GET_TLS) == 0)
{
alignas(uthread) static uint8_t storage[sizeof(uthread) + sizeof(uintptr_t)];
@ -52,12 +43,6 @@ extern "C" void _init_libc(char** environ, init_funcs_t init_funcs, init_funcs_t
.self = &uthread,
.master_tls_addr = nullptr,
.master_tls_size = 0,
.cleanup_stack = nullptr,
.id = static_cast<pthread_t>(syscall(SYS_PTHREAD_SELF)),
.errno_ = 0,
.cancel_type = PTHREAD_CANCEL_DEFERRED,
.cancel_state = PTHREAD_CANCEL_ENABLE,
.canceled = false,
};
uthread.dtv[0] = 0;
@ -114,19 +99,16 @@ long syscall(long syscall, ...)
int close(int fd)
{
pthread_testcancel();
return syscall(SYS_CLOSE, fd);
}
ssize_t read(int fildes, void* buf, size_t nbyte)
{
pthread_testcancel();
return syscall(SYS_READ, fildes, buf, nbyte);
}
ssize_t write(int fildes, const void* buf, size_t nbyte)
{
pthread_testcancel();
return syscall(SYS_WRITE, fildes, buf, nbyte);
}
@ -142,13 +124,11 @@ ssize_t readlinkat(int fd, const char* __restrict path, char* __restrict buf, si
ssize_t pread(int fildes, void* buf, size_t nbyte, off_t offset)
{
pthread_testcancel();
return syscall(SYS_PREAD, fildes, buf, nbyte, offset);
}
ssize_t pwrite(int fildes, const void* buf, size_t nbyte, off_t offset)
{
pthread_testcancel();
return syscall(SYS_PWRITE, fildes, buf, nbyte, offset);
}
@ -157,24 +137,13 @@ off_t lseek(int fildes, off_t offset, int whence)
return syscall(SYS_SEEK, fildes, offset, whence);
}
int truncate(const char* path, off_t length)
{
const int fd = open(path, O_WRONLY);
if (fd == -1)
return -1;
int ret = ftruncate(fd, length);
close(fd);
return ret;
}
int ftruncate(int fildes, off_t length)
{
return syscall(SYS_FTRUNCATE, fildes, length);
return syscall(SYS_TRUNCATE, fildes, length);
}
int fsync(int fildes)
{
pthread_testcancel();
return syscall(SYS_FSYNC, fildes);
}
@ -433,12 +402,7 @@ int execvp(const char* pathname, char* const argv[])
pid_t fork(void)
{
_pthread_call_atfork(_PTHREAD_ATFORK_PREPARE);
const pid_t pid = syscall(SYS_FORK);
if (pid == -1)
return -1;
_pthread_call_atfork(pid ? _PTHREAD_ATFORK_PARENT : _PTHREAD_ATFORK_CHILD);
return pid;
return syscall(SYS_FORK);
}
int pipe(int fildes[2])
@ -448,7 +412,6 @@ int pipe(int fildes[2])
unsigned int sleep(unsigned int seconds)
{
pthread_testcancel();
unsigned int ret = syscall(SYS_SLEEP, seconds);
if (ret > 0)
errno = EINTR;
@ -517,28 +480,14 @@ void syncsync(int should_block)
syscall(SYS_SYNC, should_block);
}
int fdatasync(int fildes)
{
pthread_testcancel();
(void)fildes;
dprintln("TODO: fdatasync");
return syscall(SYS_SYNC, true);
}
int unlink(const char* path)
{
return unlinkat(AT_FDCWD, path, 0);
}
int unlinkat(int fd, const char* path, int flag)
{
return syscall(SYS_UNLINKAT, fd, path, flag);
return syscall(SYS_UNLINK, path);
}
int rmdir(const char* path)
{
return unlinkat(AT_FDCWD, path, AT_REMOVEDIR);
return syscall(SYS_UNLINK, path);
}
char* optarg = nullptr;
@ -822,199 +771,3 @@ int linkat(int fd1, const char *path1, int fd2, const char *path2, int flag)
{
return syscall(SYS_HARDLINKAT, fd1, path1, fd2, path2, flag);
}
size_t confstr(int name, char* buf, size_t len)
{
(void)buf;
(void)len;
switch (name)
{
#define CONFSTR_CASE(name) case name: return 0;
CONFSTR_CASE(_CS_PATH)
CONFSTR_CASE(_CS_POSIX_V6_ILP32_OFF32_CFLAGS)
CONFSTR_CASE(_CS_POSIX_V6_ILP32_OFF32_LDFLAGS)
CONFSTR_CASE(_CS_POSIX_V6_ILP32_OFF32_LIBS)
CONFSTR_CASE(_CS_POSIX_V6_ILP32_OFFBIG_CFLAGS)
CONFSTR_CASE(_CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS)
CONFSTR_CASE(_CS_POSIX_V6_ILP32_OFFBIG_LIBS)
CONFSTR_CASE(_CS_POSIX_V6_LP64_OFF64_CFLAGS)
CONFSTR_CASE(_CS_POSIX_V6_LP64_OFF64_LDFLAGS)
CONFSTR_CASE(_CS_POSIX_V6_LP64_OFF64_LIBS)
CONFSTR_CASE(_CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS)
CONFSTR_CASE(_CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS)
CONFSTR_CASE(_CS_POSIX_V6_LPBIG_OFFBIG_LIBS)
CONFSTR_CASE(_CS_POSIX_V6_WIDTH_RESTRICTED_ENVS)
CONFSTR_CASE(_CS_V6_ENV)
CONFSTR_CASE(_CS_POSIX_V7_ILP32_OFF32_CFLAGS)
CONFSTR_CASE(_CS_POSIX_V7_ILP32_OFF32_LDFLAGS)
CONFSTR_CASE(_CS_POSIX_V7_ILP32_OFF32_LIBS)
CONFSTR_CASE(_CS_POSIX_V7_ILP32_OFFBIG_CFLAGS)
CONFSTR_CASE(_CS_POSIX_V7_ILP32_OFFBIG_LDFLAGS)
CONFSTR_CASE(_CS_POSIX_V7_ILP32_OFFBIG_LIBS)
CONFSTR_CASE(_CS_POSIX_V7_LP64_OFF64_CFLAGS)
CONFSTR_CASE(_CS_POSIX_V7_LP64_OFF64_LDFLAGS)
CONFSTR_CASE(_CS_POSIX_V7_LP64_OFF64_LIBS)
CONFSTR_CASE(_CS_POSIX_V7_LPBIG_OFFBIG_CFLAGS)
CONFSTR_CASE(_CS_POSIX_V7_LPBIG_OFFBIG_LDFLAGS)
CONFSTR_CASE(_CS_POSIX_V7_LPBIG_OFFBIG_LIBS)
CONFSTR_CASE(_CS_POSIX_V7_THREADS_CFLAGS)
CONFSTR_CASE(_CS_POSIX_V7_THREADS_LDFLAGS)
CONFSTR_CASE(_CS_POSIX_V7_WIDTH_RESTRICTED_ENVS)
CONFSTR_CASE(_CS_V7_ENV)
#undef CONFSTR_CASE
}
errno = EINVAL;
return 0;
}
long pathconf(const char* path, int name);
long sysconf(int name)
{
switch (name)
{
#define POSIX2_CASE(name) case _SC_2_##name: return _POSIX2_##name;
POSIX2_CASE(C_BIND)
POSIX2_CASE(C_DEV)
POSIX2_CASE(CHAR_TERM)
POSIX2_CASE(FORT_DEV)
POSIX2_CASE(FORT_RUN)
POSIX2_CASE(LOCALEDEF)
POSIX2_CASE(PBS)
POSIX2_CASE(PBS_ACCOUNTING)
POSIX2_CASE(PBS_CHECKPOINT)
POSIX2_CASE(PBS_LOCATE)
POSIX2_CASE(PBS_MESSAGE)
POSIX2_CASE(PBS_TRACK)
POSIX2_CASE(SW_DEV)
POSIX2_CASE(UPE)
POSIX2_CASE(VERSION)
#undef POSIX2_CASE
#define POSIX_CASE(name) case _SC_##name: return _POSIX_##name;
POSIX_CASE(ADVISORY_INFO)
POSIX_CASE(AIO_LISTIO_MAX)
POSIX_CASE(AIO_MAX)
POSIX_CASE(ARG_MAX)
POSIX_CASE(ASYNCHRONOUS_IO)
POSIX_CASE(BARRIERS)
POSIX_CASE(CHILD_MAX)
POSIX_CASE(CLOCK_SELECTION)
POSIX_CASE(CPUTIME)
POSIX_CASE(DELAYTIMER_MAX)
POSIX_CASE(FSYNC)
POSIX_CASE(HOST_NAME_MAX)
POSIX_CASE(IPV6)
POSIX_CASE(JOB_CONTROL)
POSIX_CASE(LOGIN_NAME_MAX)
POSIX_CASE(MAPPED_FILES)
POSIX_CASE(MEMLOCK)
POSIX_CASE(MEMLOCK_RANGE)
POSIX_CASE(MEMORY_PROTECTION)
POSIX_CASE(MESSAGE_PASSING)
POSIX_CASE(MONOTONIC_CLOCK)
POSIX_CASE(MQ_OPEN_MAX)
POSIX_CASE(MQ_PRIO_MAX)
POSIX_CASE(NGROUPS_MAX)
POSIX_CASE(OPEN_MAX)
POSIX_CASE(PRIORITIZED_IO)
POSIX_CASE(PRIORITY_SCHEDULING)
POSIX_CASE(RAW_SOCKETS)
POSIX_CASE(RE_DUP_MAX)
POSIX_CASE(READER_WRITER_LOCKS)
POSIX_CASE(REALTIME_SIGNALS)
POSIX_CASE(REGEXP)
POSIX_CASE(RTSIG_MAX)
POSIX_CASE(SAVED_IDS)
POSIX_CASE(SEM_NSEMS_MAX)
POSIX_CASE(SEM_VALUE_MAX)
POSIX_CASE(SEMAPHORES)
POSIX_CASE(SHARED_MEMORY_OBJECTS)
POSIX_CASE(SHELL)
POSIX_CASE(SIGQUEUE_MAX)
POSIX_CASE(SPAWN)
POSIX_CASE(SPIN_LOCKS)
POSIX_CASE(SPORADIC_SERVER)
POSIX_CASE(SS_REPL_MAX)
POSIX_CASE(STREAM_MAX)
POSIX_CASE(SYMLOOP_MAX)
POSIX_CASE(SYNCHRONIZED_IO)
POSIX_CASE(THREAD_ATTR_STACKADDR)
POSIX_CASE(THREAD_ATTR_STACKSIZE)
POSIX_CASE(THREAD_CPUTIME)
POSIX_CASE(THREAD_DESTRUCTOR_ITERATIONS)
POSIX_CASE(THREAD_KEYS_MAX)
POSIX_CASE(THREAD_PRIO_INHERIT)
POSIX_CASE(THREAD_PRIO_PROTECT)
POSIX_CASE(THREAD_PRIORITY_SCHEDULING)
POSIX_CASE(THREAD_PROCESS_SHARED)
POSIX_CASE(THREAD_ROBUST_PRIO_INHERIT)
POSIX_CASE(THREAD_ROBUST_PRIO_PROTECT)
POSIX_CASE(THREAD_SAFE_FUNCTIONS)
POSIX_CASE(THREAD_SPORADIC_SERVER)
POSIX_CASE(THREAD_THREADS_MAX)
POSIX_CASE(THREADS)
POSIX_CASE(TIMEOUTS)
POSIX_CASE(TIMER_MAX)
POSIX_CASE(TIMERS)
POSIX_CASE(TRACE)
POSIX_CASE(TRACE_EVENT_FILTER)
POSIX_CASE(TRACE_EVENT_NAME_MAX)
POSIX_CASE(TRACE_INHERIT)
POSIX_CASE(TRACE_LOG)
POSIX_CASE(TRACE_NAME_MAX)
POSIX_CASE(TRACE_SYS_MAX)
POSIX_CASE(TRACE_USER_EVENT_MAX)
POSIX_CASE(TTY_NAME_MAX)
POSIX_CASE(TYPED_MEMORY_OBJECTS)
POSIX_CASE(TZNAME_MAX)
POSIX_CASE(V7_ILP32_OFF32)
POSIX_CASE(V7_ILP32_OFFBIG)
POSIX_CASE(V7_LP64_OFF64)
POSIX_CASE(V7_LPBIG_OFFBIG)
POSIX_CASE(V6_ILP32_OFF32)
POSIX_CASE(V6_ILP32_OFFBIG)
POSIX_CASE(V6_LP64_OFF64)
POSIX_CASE(V6_LPBIG_OFFBIG)
POSIX_CASE(VERSION)
#undef POSIX_CASE
#define LIMITS_CASE(name) case _SC_##name: return name;
LIMITS_CASE(AIO_PRIO_DELTA_MAX)
LIMITS_CASE(ATEXIT_MAX)
LIMITS_CASE(BC_BASE_MAX)
LIMITS_CASE(BC_DIM_MAX)
LIMITS_CASE(BC_SCALE_MAX)
LIMITS_CASE(BC_STRING_MAX)
LIMITS_CASE(COLL_WEIGHTS_MAX)
LIMITS_CASE(EXPR_NEST_MAX)
LIMITS_CASE(IOV_MAX)
LIMITS_CASE(LINE_MAX)
#undef LIMITS_CASE
#define XOPEN_CASE(name) case _SC_XOPEN_##name: return _XOPEN_##name;
XOPEN_CASE(CRYPT)
XOPEN_CASE(ENH_I18N)
XOPEN_CASE(REALTIME)
XOPEN_CASE(REALTIME_THREADS)
XOPEN_CASE(SHM)
XOPEN_CASE(STREAMS)
XOPEN_CASE(UNIX)
XOPEN_CASE(UUCP)
XOPEN_CASE(VERSION)
#undef XOPEN_CASE
case _SC_PAGE_SIZE:
case _SC_PAGESIZE: return getpagesize();
case _SC_CLK_TCK: return 100;
case _SC_GETGR_R_SIZE_MAX: return 1024;
case _SC_GETPW_R_SIZE_MAX: return 1024;
case _SC_THREAD_STACK_MIN: return PTHREAD_STACK_MIN;
}
errno = EINVAL;
return -1;
}

View File

@ -1,20 +1,11 @@
#include <fcntl.h>
#include <sys/stat.h>
#include <utime.h>
#include <sys/stat.h>
#include <stdio.h>
int utime(const char* filename, const struct utimbuf* times)
{
if (times == nullptr)
return utimensat(AT_FDCWD, filename, nullptr, 0);
const timespec times_ts[2] {
timespec {
.tv_sec = times->actime,
.tv_nsec = 0,
},
timespec {
.tv_sec = times->modtime,
.tv_nsec = 0,
},
};
return utimensat(AT_FDCWD, filename, times_ts, 0);
fprintf(stddbg, "TODO: utime(\"%s\", %p)\n", filename, times);
struct stat st;
return stat(filename, &st);
}

View File

@ -1,102 +0,0 @@
#include <BAN/UTF8.h>
#include <errno.h>
#include <wchar.h>
struct FILEScopeLock
{
FILEScopeLock(FILE* stream)
: m_stream(stream)
{
flockfile(m_stream);
}
~FILEScopeLock()
{
funlockfile(m_stream);
}
FILE* m_stream;
};
wint_t getwc(FILE* stream)
{
return fgetwc(stream);
}
wint_t fgetwc(FILE* stream)
{
FILEScopeLock _(stream);
char buffer[4];
buffer[0] = getc_unlocked(stream);
if (buffer[0] == EOF)
return WEOF;
const auto length = BAN::UTF8::byte_length(buffer[0]);
if (length == BAN::UTF8::invalid)
{
errno = EILSEQ;
return WEOF;
}
for (uint32_t i = 1; i < length; i++)
if ((buffer[i] = getc_unlocked(stream)) == EOF)
return WEOF;
const auto ret = BAN::UTF8::to_codepoint(buffer);
if (ret == BAN::UTF8::invalid)
{
errno = EILSEQ;
return WEOF;
}
return ret;
}
wint_t putwc(wchar_t wc, FILE* stream)
{
return fputwc(wc, stream);
}
wint_t fputwc(wchar_t wc, FILE* stream)
{
char buffer[4];
if (!BAN::UTF8::from_codepoints(&wc, 1, buffer))
{
errno = EILSEQ;
return WEOF;
}
FILEScopeLock _(stream);
const auto bytes = BAN::UTF8::byte_length(buffer[0]);
for (uint32_t i = 0; i < bytes; i++)
if (putc_unlocked(buffer[i], stream) == EOF)
return WEOF;
return wc;
}
wint_t ungetwc(wint_t wc, FILE* stream)
{
char buffer[4];
if (!BAN::UTF8::from_codepoints(&wc, 1, buffer))
{
errno = EILSEQ;
return WEOF;
}
FILEScopeLock _(stream);
const auto bytes = BAN::UTF8::byte_length(buffer[0]);
for (uint32_t i = 0; i < bytes; i++)
{
if (ungetc(buffer[i], stream) != EOF)
continue;
for (uint32_t j = 0; j < i; j++)
fgetc(stream);
return WEOF;
}
return wc;
}

View File

@ -1,112 +1,10 @@
#include <BAN/Assert.h>
#include <BAN/UTF8.h>
#include <errno.h>
#include <locale.h>
#include <wchar.h>
wint_t btowc(int c)
size_t mbrtowc(wchar_t* __restrict, const char* __restrict, size_t, mbstate_t* __restrict)
{
if (c == 0 || c > 0x7F)
return WEOF;
return c;
}
int wctob(wint_t c)
{
if (c > 0x7F)
return WEOF;
return c;
}
int wcwidth(wchar_t wc)
{
return wc != '\0';
}
size_t wcrtomb(char* __restrict s, wchar_t ws, mbstate_t* __restrict ps)
{
(void)ps;
// ws == '\0' doesn't seem to apply to UTF8?
if (s == nullptr)
return 1;
if (!BAN::UTF8::from_codepoints(&ws, 1, s))
{
errno = EILSEQ;
return -1;
}
return BAN::UTF8::byte_length(s[0]);
}
size_t mbrtowc(wchar_t* __restrict pwc, const char* __restrict s, size_t n, mbstate_t* __restrict ps)
{
(void)ps;
if (s == nullptr)
return 0;
const auto bytes = BAN::UTF8::byte_length(*s);
if (bytes == BAN::UTF8::invalid)
{
errno = EILSEQ;
return -1;
}
if (n < bytes)
return -1;
const auto codepoint = BAN::UTF8::to_codepoint(s);
if (codepoint == BAN::UTF8::invalid)
{
errno = EILSEQ;
return -1;
}
if (pwc != nullptr)
*pwc = codepoint;
if (codepoint == 0)
return 0;
return bytes;
}
int wcscoll(const wchar_t* ws1, const wchar_t* ws2)
{
return wcscoll_l(ws1, ws2, __getlocale(LC_COLLATE));
}
int wcscoll_l(const wchar_t* ws1, const wchar_t* ws2, locale_t locale)
{
(void)locale;
// TODO: this isn't really correct :D
return wcscmp(ws1, ws2);
}
size_t wcsxfrm(wchar_t* __restrict ws1, const wchar_t* __restrict ws2, size_t n)
{
return wcsxfrm_l(ws1, ws2, n, __getlocale(LC_COLLATE));
}
size_t wcsxfrm_l(wchar_t* __restrict ws1, const wchar_t* __restrict ws2, size_t n, locale_t locale)
{
(void)locale;
// TODO: this isn't really correct :D
wcsncpy(ws1, ws2, n);
return wcslen(ws2);
}
size_t wcsftime(wchar_t* __restrict wcs, size_t maxsize, const wchar_t* __restrict format, const struct tm* __restrict timeptr)
{
(void)wcs;
(void)maxsize;
(void)format;
(void)timeptr;
fprintf(stddbg, "TODO: wcsftime");
return 0;
ASSERT_NOT_REACHED();
}
int wcscmp(const wchar_t* ws1, const wchar_t* ws2)
@ -284,93 +182,3 @@ wchar_t* wmemset(wchar_t* ws, wchar_t wc, size_t n)
ws[i] = wc;
return ws;
}
// FIXME: actually support multibyte :D
wint_t towlower(wint_t wc)
{
return tolower(wc);
}
wint_t towupper(wint_t wc)
{
return toupper(wc);
}
#define DEFINE_ISW(class) \
int isw##class(wint_t wc) { \
return is##class(wc); \
}
DEFINE_ISW(alnum);
DEFINE_ISW(alpha);
DEFINE_ISW(blank);
DEFINE_ISW(cntrl);
DEFINE_ISW(digit);
DEFINE_ISW(graph);
DEFINE_ISW(lower);
DEFINE_ISW(print);
DEFINE_ISW(punct);
DEFINE_ISW(space);
DEFINE_ISW(upper);
DEFINE_ISW(xdigit);
#undef DEFINE_ISW
typedef enum {
_alnum = 1,
_alpha,
_blank,
_cntrl,
_digit,
_graph,
_lower,
_print,
_punct,
_space,
_upper,
_xdigit,
} wctype_values;
wctype_t wctype(const char* property)
{
#define CHECK_PROPERTY(class) \
if (strcmp(property, #class) == 0) \
return _##class
CHECK_PROPERTY(alnum);
CHECK_PROPERTY(alpha);
CHECK_PROPERTY(blank);
CHECK_PROPERTY(cntrl);
CHECK_PROPERTY(digit);
CHECK_PROPERTY(graph);
CHECK_PROPERTY(lower);
CHECK_PROPERTY(print);
CHECK_PROPERTY(punct);
CHECK_PROPERTY(space);
CHECK_PROPERTY(upper);
CHECK_PROPERTY(xdigit);
#undef CHECK_TYPE
return 0;
}
int iswctype(wint_t wc, wctype_t charclass)
{
switch (charclass)
{
#define CLASS_CASE(class) \
case _##class: \
return is##class(wc)
CLASS_CASE(alnum);
CLASS_CASE(alpha);
CLASS_CASE(blank);
CLASS_CASE(cntrl);
CLASS_CASE(digit);
CLASS_CASE(graph);
CLASS_CASE(lower);
CLASS_CASE(print);
CLASS_CASE(punct);
CLASS_CASE(space);
CLASS_CASE(upper);
CLASS_CASE(xdigit);
#undef CLASS_CASE
}
return 0;
}

View File

@ -928,6 +928,7 @@ static LoadedElf& load_elf(const char* path, int fd)
case PT_GNU_EH_FRAME:
case PT_GNU_STACK:
case PT_GNU_RELRO:
print(STDDBG_FILENO, "TODO: PT_GNU_*\n");
break;
case PT_TLS:
tls_header = program_header;