Compare commits
22 Commits
8392472bac
...
2b48933f29
Author | SHA1 | Date |
---|---|---|
|
2b48933f29 | |
|
4ac6cbe70e | |
|
cc07c3df94 | |
|
31bcad2535 | |
|
b75970958e | |
|
91756c057e | |
|
df7f245cf8 | |
|
dbdefa0f4a | |
|
56fdf6002c | |
|
c957f1ddca | |
|
423386a052 | |
|
1c882ea361 | |
|
b1065fa01d | |
|
8ff9c030bf | |
|
9b875fb930 | |
|
857bac4b78 | |
|
30074c290d | |
|
60d1c26114 | |
|
692ba43182 | |
|
6542a037df | |
|
9f4b451501 | |
|
1bd454b8fd |
|
@ -14,7 +14,7 @@
|
|||
#define dprintln(...) \
|
||||
do { \
|
||||
BAN::Formatter::print(__debug_putchar, __VA_ARGS__); \
|
||||
BAN::Formatter::print(__debug_putchar,"\r\n"); \
|
||||
BAN::Formatter::print(__debug_putchar,"\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\r\n"); \
|
||||
BAN::Formatter::print(__debug_putchar, "\e[m\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\r\n"); \
|
||||
BAN::Formatter::print(__debug_putchar, "\e[m\n"); \
|
||||
fflush(stddbg); \
|
||||
} while(false)
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ 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
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
#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
|
||||
|
@ -16,7 +18,7 @@ namespace Kernel
|
|||
static BAN::ErrorOr<BAN::RefPtr<Epoll>> create();
|
||||
~Epoll();
|
||||
|
||||
BAN::ErrorOr<void> ctl(int op, BAN::RefPtr<Inode> inode, epoll_event event);
|
||||
BAN::ErrorOr<void> ctl(int op, int fd, 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);
|
||||
|
@ -59,10 +61,45 @@ 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>, epoll_event, InodeRefPtrHash> m_listening_events;
|
||||
BAN::HashMap<BAN::RefPtr<Inode>, uint32_t, InodeRefPtrHash> m_ready_events;
|
||||
BAN::HashMap<BAN::RefPtr<Inode>, ListenEventList, InodeRefPtrHash> m_listening_events;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -46,6 +46,7 @@ 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; }
|
||||
|
|
|
@ -44,6 +44,7 @@ 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; }
|
||||
|
|
|
@ -119,6 +119,7 @@ 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
|
||||
|
@ -165,6 +166,7 @@ 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
|
||||
|
@ -182,6 +184,7 @@ 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;
|
||||
|
|
|
@ -47,6 +47,8 @@ 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();
|
||||
|
@ -75,7 +77,6 @@ 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; }
|
||||
|
@ -98,7 +99,6 @@ 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; }
|
||||
|
|
|
@ -88,6 +88,8 @@ 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
|
||||
|
@ -111,6 +113,8 @@ 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
|
||||
|
|
|
@ -18,42 +18,11 @@ namespace Kernel
|
|||
public:
|
||||
SpinLock() = default;
|
||||
|
||||
InterruptState lock()
|
||||
{
|
||||
auto state = Processor::get_interrupt_state();
|
||||
Processor::set_interrupt_state(InterruptState::Disabled);
|
||||
InterruptState lock();
|
||||
|
||||
auto id = Processor::current_id().as_u32();
|
||||
ASSERT(m_locker.load(BAN::MemoryOrder::memory_order_relaxed) != id);
|
||||
bool try_lock_interrupts_disabled();
|
||||
|
||||
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);
|
||||
}
|
||||
void unlock(InterruptState state);
|
||||
|
||||
bool current_processor_has_lock() const
|
||||
{
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#error
|
||||
#endif
|
||||
|
||||
#undef PAGE_SIZE
|
||||
#define PAGE_SIZE ((uintptr_t)4096)
|
||||
#define PAGE_SIZE_SHIFT 12
|
||||
#define PAGE_ADDR_MASK (~(uintptr_t)0xFFF)
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#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>
|
||||
|
@ -106,7 +107,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_unlink(const char*);
|
||||
BAN::ErrorOr<long> sys_unlinkat(int fd, const char* path, int flag);
|
||||
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);
|
||||
|
@ -116,6 +117,7 @@ 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]);
|
||||
|
@ -134,6 +136,7 @@ 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);
|
||||
|
@ -147,7 +150,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_truncate(int fd, off_t length);
|
||||
BAN::ErrorOr<long> sys_ftruncate(int fd, off_t length);
|
||||
|
||||
BAN::ErrorOr<long> sys_fsync(int fd);
|
||||
|
||||
|
@ -191,6 +194,7 @@ 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);
|
||||
|
|
|
@ -57,7 +57,7 @@ namespace Kernel
|
|||
virtual bool has_hungup_impl() const override { return false; }
|
||||
|
||||
protected:
|
||||
TTY(mode_t mode, uid_t uid, gid_t gid);
|
||||
TTY(termios termios, mode_t mode, uid_t uid, gid_t gid);
|
||||
|
||||
virtual bool putchar_impl(uint8_t ch) = 0;
|
||||
virtual void update_cursor() {}
|
||||
|
|
|
@ -101,6 +101,10 @@ 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--; }
|
||||
|
||||
|
@ -137,6 +141,7 @@ 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] {};
|
||||
|
|
|
@ -19,7 +19,7 @@ namespace Kernel
|
|||
inode->del_epoll(this);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Epoll::ctl(int op, BAN::RefPtr<Inode> inode, epoll_event event)
|
||||
BAN::ErrorOr<void> Epoll::ctl(int op, int fd, BAN::RefPtr<Inode> inode, epoll_event event)
|
||||
{
|
||||
LockGuard _(m_mutex);
|
||||
|
||||
|
@ -28,27 +28,51 @@ namespace Kernel
|
|||
switch (op)
|
||||
{
|
||||
case EPOLL_CTL_ADD:
|
||||
if (it != m_listening_events.end())
|
||||
{
|
||||
if (it == m_listening_events.end())
|
||||
it = TRY(m_listening_events.emplace(inode));
|
||||
if (it->value.has_fd(fd))
|
||||
return BAN::Error::from_errno(EEXIST);
|
||||
TRY(m_listening_events.reserve(m_listening_events.size() + 1));
|
||||
TRY(m_ready_events.reserve(m_listening_events.size() + 1));
|
||||
TRY(m_ready_events.reserve(m_listening_events.size()));
|
||||
TRY(inode->add_epoll(this));
|
||||
MUST(m_listening_events.insert(inode, event));
|
||||
MUST(m_ready_events.insert(inode, event.events));
|
||||
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;
|
||||
|
||||
return {};
|
||||
}
|
||||
case EPOLL_CTL_MOD:
|
||||
{
|
||||
if (it == m_listening_events.end())
|
||||
return BAN::Error::from_errno(ENOENT);
|
||||
MUST(m_ready_events.emplace_or_assign(inode, event.events));
|
||||
it->value = event;
|
||||
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;
|
||||
|
||||
return {};
|
||||
}
|
||||
case EPOLL_CTL_DEL:
|
||||
{
|
||||
if (it == m_listening_events.end())
|
||||
return BAN::Error::from_errno(ENOENT);
|
||||
m_listening_events.remove(it);
|
||||
m_ready_events.remove(inode);
|
||||
inode->del_epoll(this);
|
||||
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);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
|
@ -56,20 +80,37 @@ namespace Kernel
|
|||
|
||||
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;
|
||||
|
@ -79,6 +120,8 @@ namespace Kernel
|
|||
CHECK_EVENT_BIT(EPOLLHUP, has_hungup);
|
||||
#undef CHECK_EVENT_BIT
|
||||
|
||||
inode->m_mutex.unlock();
|
||||
|
||||
if (events == 0)
|
||||
{
|
||||
m_ready_events.remove(it);
|
||||
|
@ -86,16 +129,27 @@ namespace Kernel
|
|||
continue;
|
||||
}
|
||||
|
||||
event_span[count++] = {
|
||||
.events = events,
|
||||
.data = listen.data,
|
||||
};
|
||||
for (int fd = 0; fd < OPEN_MAX && count < event_span.size(); fd++)
|
||||
{
|
||||
if (!listen.has_fd(fd))
|
||||
continue;
|
||||
auto& listen_event = listen.events[fd];
|
||||
|
||||
if (listen.events & EPOLLONESHOT)
|
||||
listen.events = 0;
|
||||
const auto new_events = listen_event.events & events;
|
||||
if (new_events == 0)
|
||||
continue;
|
||||
|
||||
if (listen.events & EPOLLET)
|
||||
events &= ~listen_mask;
|
||||
event_span[count++] = {
|
||||
.events = new_events,
|
||||
.data = listen_event.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;
|
||||
}
|
||||
|
||||
it++;
|
||||
}
|
||||
|
@ -107,6 +161,8 @@ 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));
|
||||
}
|
||||
|
@ -118,18 +174,13 @@ namespace Kernel
|
|||
{
|
||||
LockGuard _(m_mutex);
|
||||
|
||||
auto listen_it = m_listening_events.find(inode);
|
||||
if (listen_it == m_listening_events.end())
|
||||
if (!m_listening_events.contains(inode))
|
||||
return;
|
||||
|
||||
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));
|
||||
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;
|
||||
|
||||
m_thread_blocker.unblock();
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
#include <kernel/FS/Ext2/Inode.h>
|
||||
#include <kernel/Timer/Timer.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
|
@ -287,6 +289,28 @@ 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++)
|
||||
|
|
|
@ -231,6 +231,12 @@ 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);
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
#include <kernel/FS/TmpFS/Inode.h>
|
||||
#include <kernel/Timer/Timer.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
|
@ -90,6 +92,23 @@ 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);
|
||||
|
@ -219,12 +238,6 @@ 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)
|
||||
{
|
||||
|
@ -248,12 +261,6 @@ 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)
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
#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);
|
||||
}
|
||||
|
||||
}
|
|
@ -27,9 +27,7 @@ namespace Kernel
|
|||
TRY(region->m_dirty_pages.resize(BAN::Math::div_round_up<size_t>(size, PAGE_SIZE)));
|
||||
|
||||
LockGuard _(inode->m_mutex);
|
||||
if (inode->m_shared_region.valid())
|
||||
region->m_shared_data = inode->m_shared_region.lock();
|
||||
else
|
||||
if (!(region->m_shared_data = inode->m_shared_region.lock()))
|
||||
{
|
||||
auto shared_data = TRY(BAN::RefPtr<SharedFileData>::create());
|
||||
TRY(shared_data->pages.resize(BAN::Math::div_round_up<size_t>(inode->size(), PAGE_SIZE)));
|
||||
|
|
|
@ -281,10 +281,11 @@ namespace Kernel
|
|||
if (!is_streaming())
|
||||
m_packet_sizes.push(packet.size());
|
||||
|
||||
epoll_notify(EPOLLIN);
|
||||
|
||||
m_packet_thread_blocker.unblock();
|
||||
m_packet_lock.unlock(state);
|
||||
|
||||
epoll_notify(EPOLLIN);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
|
|
|
@ -146,9 +146,17 @@ 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;
|
||||
}
|
||||
|
|
|
@ -415,12 +415,35 @@ 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);
|
||||
|
@ -428,6 +451,7 @@ 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
|
||||
|
@ -454,6 +478,7 @@ 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
|
||||
|
|
|
@ -350,6 +350,12 @@ 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() };
|
||||
|
||||
|
@ -1152,12 +1158,19 @@ namespace Kernel
|
|||
return 0;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> Process::sys_unlink(const char* path)
|
||||
BAN::ErrorOr<long> Process::sys_unlinkat(int fd, const char* path, int flag)
|
||||
{
|
||||
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(AT_FDCWD, path, O_WRONLY));
|
||||
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);
|
||||
|
||||
TRY(parent.inode->unlink(file_name));
|
||||
|
||||
return 0;
|
||||
|
@ -1262,6 +1275,56 @@ 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);
|
||||
|
@ -1533,7 +1596,7 @@ namespace Kernel
|
|||
}
|
||||
|
||||
auto epoll = TRY(Epoll::create());
|
||||
for (int fd = 0; fd < user_arguments->nfds; fd++)
|
||||
for (int fd = 0; fd < arguments.nfds; fd++)
|
||||
{
|
||||
uint32_t events = 0;
|
||||
if (arguments.readfds && FD_ISSET(fd, arguments.readfds))
|
||||
|
@ -1549,11 +1612,11 @@ namespace Kernel
|
|||
if (inode_or_error.is_error())
|
||||
continue;
|
||||
|
||||
TRY(epoll->ctl(EPOLL_CTL_ADD, inode_or_error.release_value(), { .events = events, .data = { .fd = fd }}));
|
||||
TRY(epoll->ctl(EPOLL_CTL_ADD, fd, inode_or_error.release_value(), { .events = events, .data = { .fd = fd }}));
|
||||
}
|
||||
|
||||
BAN::Vector<epoll_event> event_buffer;
|
||||
TRY(event_buffer.resize(user_arguments->nfds));
|
||||
TRY(event_buffer.resize(arguments.nfds));
|
||||
|
||||
const size_t waited_events = TRY(epoll->wait(event_buffer.span(), waketime_ns));
|
||||
|
||||
|
@ -1578,6 +1641,113 @@ 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))
|
||||
|
@ -1613,7 +1783,7 @@ namespace Kernel
|
|||
event = *user_event;
|
||||
}
|
||||
|
||||
TRY(static_cast<Epoll*>(epoll_inode.ptr())->ctl(op, inode, event));
|
||||
TRY(static_cast<Epoll*>(epoll_inode.ptr())->ctl(op, fd, inode, event));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1686,7 +1856,7 @@ namespace Kernel
|
|||
return TRY(m_open_file_descriptors.tell(fd));
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> Process::sys_truncate(int fd, off_t length)
|
||||
BAN::ErrorOr<long> Process::sys_ftruncate(int fd, off_t length)
|
||||
{
|
||||
TRY(m_open_file_descriptors.truncate(fd, length));
|
||||
return 0;
|
||||
|
@ -2311,11 +2481,7 @@ namespace Kernel
|
|||
if (attr)
|
||||
{
|
||||
TRY(validate_pointer_access(attr, sizeof(*attr), false));
|
||||
if (*attr)
|
||||
{
|
||||
dwarnln("pthread attr not supported");
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
}
|
||||
dwarnln("TODO: ignoring thread attr");
|
||||
}
|
||||
|
||||
LockGuard _(m_process_lock);
|
||||
|
@ -2401,6 +2567,25 @@ 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);
|
||||
|
|
|
@ -337,6 +337,8 @@ 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()];
|
||||
|
||||
{
|
||||
|
|
|
@ -88,18 +88,20 @@ namespace Kernel
|
|||
|
||||
bool PseudoTerminalMaster::putchar(uint8_t ch)
|
||||
{
|
||||
SpinLockGuard _(m_buffer_lock);
|
||||
{
|
||||
SpinLockGuard _(m_buffer_lock);
|
||||
|
||||
if (m_buffer_size >= m_buffer->size())
|
||||
return false;
|
||||
if (m_buffer_size >= m_buffer->size())
|
||||
return false;
|
||||
|
||||
reinterpret_cast<uint8_t*>(m_buffer->vaddr())[(m_buffer_tail + m_buffer_size) % m_buffer->size()] = ch;
|
||||
m_buffer_size++;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -130,10 +132,10 @@ namespace Kernel
|
|||
m_buffer_size -= to_copy;
|
||||
m_buffer_tail = (m_buffer_tail + to_copy) % m_buffer->size();
|
||||
|
||||
epoll_notify(EPOLLOUT);
|
||||
|
||||
m_buffer_lock.unlock(state);
|
||||
|
||||
epoll_notify(EPOLLOUT);
|
||||
|
||||
return to_copy;
|
||||
}
|
||||
|
||||
|
@ -156,7 +158,15 @@ namespace Kernel
|
|||
}
|
||||
|
||||
PseudoTerminalSlave::PseudoTerminalSlave(BAN::String&& name, uint32_t number, mode_t mode, uid_t uid, gid_t gid)
|
||||
: TTY(mode, uid, 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)
|
||||
, m_name(BAN::move(name))
|
||||
, m_number(number)
|
||||
{}
|
||||
|
|
|
@ -170,7 +170,15 @@ namespace Kernel
|
|||
}
|
||||
|
||||
SerialTTY::SerialTTY(Serial serial)
|
||||
: TTY(0600, 0, 0)
|
||||
: 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)
|
||||
, m_name(MUST(BAN::String::formatted("ttyS{}", s_next_tty_number++)))
|
||||
, m_serial(serial)
|
||||
{}
|
||||
|
@ -235,8 +243,6 @@ namespace Kernel
|
|||
while (!m_input.empty())
|
||||
{
|
||||
*ptr = m_input.front();
|
||||
if (*ptr == '\r')
|
||||
*ptr = '\n';
|
||||
m_input.pop();
|
||||
ptr++;
|
||||
}
|
||||
|
|
|
@ -66,18 +66,11 @@ namespace Kernel
|
|||
return makedev(DeviceNumber::TTY, s_minor++);
|
||||
}
|
||||
|
||||
TTY::TTY(mode_t mode, uid_t uid, gid_t gid)
|
||||
TTY::TTY(termios termios, 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()
|
||||
{
|
||||
|
@ -228,6 +221,17 @@ 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')
|
||||
{
|
||||
|
@ -252,6 +256,10 @@ 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)
|
||||
|
@ -280,7 +288,7 @@ namespace Kernel
|
|||
}
|
||||
}
|
||||
|
||||
if (ch == '\n' || !(m_termios.c_lflag & ICANON))
|
||||
if (ch == '\n' || !(m_termios.c_lflag & ICANON) || m_output.bytes == m_output.buffer.size())
|
||||
{
|
||||
m_output.flush = true;
|
||||
epoll_notify(EPOLLIN);
|
||||
|
@ -334,9 +342,16 @@ namespace Kernel
|
|||
bool TTY::putchar(uint8_t ch)
|
||||
{
|
||||
SpinLockGuard _(m_write_lock);
|
||||
if (m_tty_ctrl.draw_graphics)
|
||||
return putchar_impl(ch);
|
||||
return true;
|
||||
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');
|
||||
}
|
||||
return putchar_impl(ch);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<size_t> TTY::read_impl(off_t, BAN::ByteSpan buffer)
|
||||
|
@ -353,7 +368,13 @@ namespace Kernel
|
|||
return 0;
|
||||
}
|
||||
|
||||
size_t to_copy = BAN::Math::min<size_t>(buffer.size(), m_output.bytes);
|
||||
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;
|
||||
|
||||
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);
|
||||
|
|
|
@ -36,7 +36,15 @@ namespace Kernel
|
|||
}
|
||||
|
||||
VirtualTTY::VirtualTTY(BAN::RefPtr<TerminalDriver> driver)
|
||||
: TTY(0600, 0, 0)
|
||||
: 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)
|
||||
, m_name(MUST(BAN::String::formatted("tty{}", s_next_tty_number++)))
|
||||
, m_terminal_driver(driver)
|
||||
, m_palette(driver->palette())
|
||||
|
|
|
@ -140,6 +140,8 @@ namespace Kernel
|
|||
|
||||
pid_t Thread::current_tid()
|
||||
{
|
||||
if (Processor::count() == 0)
|
||||
return 0;
|
||||
return Processor::scheduler().current_tid();
|
||||
}
|
||||
|
||||
|
@ -523,6 +525,8 @@ namespace Kernel
|
|||
// Ignore the signal
|
||||
case SIGCHLD:
|
||||
case SIGURG:
|
||||
case SIGWINCH:
|
||||
case SIGCANCEL:
|
||||
break;
|
||||
|
||||
// Stop the process:
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
set(LIBC_SOURCES
|
||||
arpa/inet.cpp
|
||||
assert.cpp
|
||||
complex.cpp
|
||||
ctype.cpp
|
||||
dirent.cpp
|
||||
dlfcn.cpp
|
||||
|
@ -47,6 +48,7 @@ set(LIBC_SOURCES
|
|||
time.cpp
|
||||
unistd.cpp
|
||||
utime.cpp
|
||||
wchar-stdio.cpp
|
||||
wchar.cpp
|
||||
icxxabi.cpp
|
||||
|
||||
|
|
|
@ -0,0 +1,192 @@
|
|||
#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
|
|
@ -1,12 +1,9 @@
|
|||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#if __disable_thread_local_storage
|
||||
static int s_errno = 0;
|
||||
#else
|
||||
static thread_local int s_errno = 0;
|
||||
#endif
|
||||
extern uthread* _get_uthread();
|
||||
|
||||
int* __errno_location()
|
||||
{
|
||||
return &s_errno;
|
||||
return &_get_uthread()->errno_;
|
||||
}
|
||||
|
|
|
@ -1,15 +1,19 @@
|
|||
#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);
|
||||
|
@ -20,6 +24,8 @@ 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);
|
||||
|
@ -30,6 +36,8 @@ 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);
|
||||
|
|
|
@ -12,11 +12,12 @@ __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. */
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
// 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
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef _BITS_LOCALE_T_H
|
||||
#define _BITS_LOCALE_T_H 1
|
||||
#ifndef _BITS_TYPES_LOCALE_T_H
|
||||
#define _BITS_TYPES_LOCALE_T_H 1
|
||||
|
||||
// https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/locale.h.html
|
||||
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
#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
|
|
@ -0,0 +1,17 @@
|
|||
#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
|
|
@ -0,0 +1,72 @@
|
|||
#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
|
|
@ -0,0 +1,23 @@
|
|||
#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
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef _BITS_TIMEVAL_H
|
||||
#define _BITS_TIMEVAL_H 1
|
||||
#ifndef _BITS_TYPES_TIMEVAL_H
|
||||
#define _BITS_TYPES_TIMEVAL_H 1
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
|
|
|
@ -13,6 +13,14 @@
|
|||
|
||||
__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);
|
||||
|
@ -46,9 +54,6 @@ 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);
|
||||
|
@ -61,9 +66,6 @@ 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);
|
||||
|
|
|
@ -7,67 +7,140 @@
|
|||
|
||||
__BEGIN_DECLS
|
||||
|
||||
#define _POSIX_AIO_LISTIO_MAX 2
|
||||
#define _POSIX_AIO_MAX 1
|
||||
#define _POSIX_ARG_MAX 4096
|
||||
#define _POSIX_CHILD_MAX 25
|
||||
#define _POSIX_DELAYTIMER_MAX 32
|
||||
#define _POSIX_HOST_NAME_MAX 255
|
||||
#define _POSIX_LINK_MAX 8
|
||||
#define _POSIX_LOGIN_NAME_MAX 9
|
||||
#define _POSIX_MAX_CANON 255
|
||||
#define _POSIX_MAX_INPUT 255
|
||||
#define _POSIX_MQ_OPEN_MAX 8
|
||||
#define _POSIX_MQ_PRIO_MAX 32
|
||||
#define _POSIX_NAME_MAX 14
|
||||
#define _POSIX_NGROUPS_MAX 8
|
||||
#define _POSIX_OPEN_MAX 20
|
||||
#define _POSIX_PATH_MAX 256
|
||||
#define _POSIX_PIPE_BUF 512
|
||||
#define _POSIX_RE_DUP_MAX 255
|
||||
#define _POSIX_RTSIG_MAX 8
|
||||
#define _POSIX_SEM_NSEMS_MAX 256
|
||||
#define _POSIX_SEM_VALUE_MAX 32767
|
||||
#define _POSIX_SIGQUEUE_MAX 32
|
||||
#define _POSIX_SSIZE_MAX 32767
|
||||
#define _POSIX_SS_REPL_MAX 4
|
||||
#define _POSIX_STREAM_MAX 8
|
||||
#define _POSIX_SYMLINK_MAX 255
|
||||
#define _POSIX_SYMLOOP_MAX 8
|
||||
// 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
|
||||
#define _POSIX_CHILD_MAX 25
|
||||
#define _POSIX_DELAYTIMER_MAX 32
|
||||
#define _POSIX_HOST_NAME_MAX 255
|
||||
#define _POSIX_LINK_MAX 8
|
||||
#define _POSIX_LOGIN_NAME_MAX 9
|
||||
#define _POSIX_MAX_CANON 255
|
||||
#define _POSIX_MAX_INPUT 255
|
||||
#define _POSIX_MQ_OPEN_MAX 8
|
||||
#define _POSIX_MQ_PRIO_MAX 32
|
||||
#define _POSIX_NAME_MAX 14
|
||||
#define _POSIX_NGROUPS_MAX 8
|
||||
#define _POSIX_OPEN_MAX 20
|
||||
#define _POSIX_PATH_MAX 256
|
||||
#define _POSIX_PIPE_BUF 512
|
||||
#define _POSIX_RE_DUP_MAX 255
|
||||
#define _POSIX_RTSIG_MAX 8
|
||||
#define _POSIX_SEM_NSEMS_MAX 256
|
||||
#define _POSIX_SEM_VALUE_MAX 32767
|
||||
#define _POSIX_SIGQUEUE_MAX 32
|
||||
#define _POSIX_SSIZE_MAX 32767
|
||||
#define _POSIX_SS_REPL_MAX 4
|
||||
#define _POSIX_STREAM_MAX 8
|
||||
#define _POSIX_SYMLINK_MAX 255
|
||||
#define _POSIX_SYMLOOP_MAX 8
|
||||
#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4
|
||||
#define _POSIX_THREAD_KEYS_MAX 128
|
||||
#define _POSIX_THREAD_THREADS_MAX 64
|
||||
#define _POSIX_TIMER_MAX 32
|
||||
#define _POSIX_TRACE_EVENT_NAME_MAX 30
|
||||
#define _POSIX_TRACE_NAME_MAX 8
|
||||
#define _POSIX_TRACE_SYS_MAX 8
|
||||
#define _POSIX_TRACE_USER_EVENT_MAX 32
|
||||
#define _POSIX_TTY_NAME_MAX 9
|
||||
#define _POSIX_TZNAME_MAX 6
|
||||
#define _POSIX2_BC_BASE_MAX 99
|
||||
#define _POSIX2_BC_DIM_MAX 2048
|
||||
#define _POSIX2_BC_SCALE_MAX 99
|
||||
#define _POSIX2_BC_STRING_MAX 1000
|
||||
#define _POSIX2_CHARCLASS_NAME_MAX 14
|
||||
#define _POSIX2_COLL_WEIGHTS_MAX 2
|
||||
#define _POSIX2_EXPR_NEST_MAX 32
|
||||
#define _POSIX2_LINE_MAX 2048
|
||||
#define _POSIX2_RE_DUP_MAX 255
|
||||
#define _XOPEN_IOV_MAX 16
|
||||
#define _XOPEN_NAME_MAX 255
|
||||
#define _XOPEN_PATH_MAX 1024
|
||||
#define _POSIX_THREAD_KEYS_MAX 128
|
||||
#define _POSIX_THREAD_THREADS_MAX 64
|
||||
#define _POSIX_TIMER_MAX 32
|
||||
#define _POSIX_TRACE_EVENT_NAME_MAX 30
|
||||
#define _POSIX_TRACE_NAME_MAX 8
|
||||
#define _POSIX_TRACE_SYS_MAX 8
|
||||
#define _POSIX_TRACE_USER_EVENT_MAX 32
|
||||
#define _POSIX_TTY_NAME_MAX 9
|
||||
#define _POSIX_TZNAME_MAX 6
|
||||
#define _POSIX2_BC_BASE_MAX 99
|
||||
#define _POSIX2_BC_DIM_MAX 2048
|
||||
#define _POSIX2_BC_SCALE_MAX 99
|
||||
#define _POSIX2_BC_STRING_MAX 1000
|
||||
#define _POSIX2_CHARCLASS_NAME_MAX 14
|
||||
#define _POSIX2_COLL_WEIGHTS_MAX 2
|
||||
#define _POSIX2_EXPR_NEST_MAX 32
|
||||
#define _POSIX2_LINE_MAX 2048
|
||||
#define _POSIX2_RE_DUP_MAX 255
|
||||
#define _XOPEN_IOV_MAX 16
|
||||
#define _XOPEN_NAME_MAX 255
|
||||
#define _XOPEN_PATH_MAX 1024
|
||||
|
||||
#define ARG_MAX _POSIX_ARG_MAX
|
||||
#define OPEN_MAX 64
|
||||
#define NAME_MAX 255
|
||||
#define PATH_MAX 256
|
||||
#define PASS_MAX 256
|
||||
#define LOGIN_NAME_MAX 256
|
||||
#define HOST_NAME_MAX 255
|
||||
#define TTY_NAME_MAX PATH_MAX
|
||||
|
||||
#define PTHREAD_KEYS_MAX _POSIX_THREAD_KEYS_MAX
|
||||
// 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 PASS_MAX 256
|
||||
|
||||
|
||||
// Numerical Limits
|
||||
|
||||
#define CHAR_MAX SCHAR_MAX
|
||||
#define CHAR_MIN SCHAR_MIN
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef _MEMORY_H
|
||||
#define _MEMORY_H 1
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#endif
|
|
@ -10,11 +10,12 @@ __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
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
__BEGIN_DECLS
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
struct pollfd
|
||||
{
|
||||
int fd; /* The following descriptor being polled. */
|
||||
|
@ -28,6 +30,7 @@ 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
|
||||
|
||||
|
|
|
@ -13,29 +13,51 @@ __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_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_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_CREATE_DETACHED 1
|
||||
#define PTHREAD_CREATE_JOINABLE 0
|
||||
|
@ -60,6 +82,11 @@ 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);
|
||||
|
|
|
@ -12,14 +12,7 @@ __BEGIN_DECLS
|
|||
#define __need_pid_t
|
||||
#include <sys/types.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. */
|
||||
};
|
||||
#include <bits/types/sched_param.h>
|
||||
|
||||
#define SCHED_FIFO 1
|
||||
#define SCHED_RR 2
|
||||
|
|
|
@ -14,13 +14,14 @@ __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;
|
||||
|
||||
|
@ -105,7 +106,8 @@ struct sigevent
|
|||
#define SIGXCPU 27
|
||||
#define SIGXFSZ 28
|
||||
#define SIGWINCH 29
|
||||
#define SIGRTMIN 30
|
||||
#define SIGCANCEL 30
|
||||
#define SIGRTMIN 31
|
||||
#define SIGRTMAX (SIGRTMIN+32)
|
||||
|
||||
#define NSIG SIGRTMAX
|
||||
|
|
|
@ -56,7 +56,7 @@ __BEGIN_DECLS
|
|||
O(SYS_POWEROFF, poweroff) \
|
||||
O(SYS_FCHMODAT, fchmodat) \
|
||||
O(SYS_CREATE_DIR, create_dir) \
|
||||
O(SYS_UNLINK, unlink) \
|
||||
O(SYS_UNLINKAT, unlinkat) \
|
||||
O(SYS_READLINKAT, readlinkat) \
|
||||
O(SYS_MSYNC, msync) \
|
||||
O(SYS_PREAD, pread) \
|
||||
|
@ -73,7 +73,8 @@ __BEGIN_DECLS
|
|||
O(SYS_CONNECT, connect) \
|
||||
O(SYS_LISTEN, listen) \
|
||||
O(SYS_PSELECT, pselect) \
|
||||
O(SYS_TRUNCATE, truncate) \
|
||||
O(SYS_PPOLL, ppoll) \
|
||||
O(SYS_FTRUNCATE, ftruncate) \
|
||||
O(SYS_SMO_CREATE, smo_create) \
|
||||
O(SYS_SMO_DELETE, smo_delete) \
|
||||
O(SYS_SMO_MAP, smo_map) \
|
||||
|
@ -94,6 +95,7 @@ __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) \
|
||||
|
@ -101,6 +103,7 @@ __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) \
|
||||
|
|
|
@ -21,9 +21,6 @@ __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) \
|
||||
|
@ -122,18 +119,12 @@ __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
|
||||
|
|
|
@ -7,89 +7,109 @@
|
|||
|
||||
__BEGIN_DECLS
|
||||
|
||||
#define _POSIX_VERSION 200809L
|
||||
#define _POSIX_VERSION 200809L
|
||||
#define _POSIX2_VERSION -1
|
||||
#define _XOPEN_VERSION 700
|
||||
#define _XOPEN_VERSION 700
|
||||
|
||||
#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 -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
|
||||
// -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_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 _XOPEN_ENH_I18N -1
|
||||
#define _XOPEN_REALTIME -1
|
||||
#define _XOPEN_REALTIME_THREADS -1
|
||||
#define _XOPEN_SHM -1
|
||||
#define _XOPEN_STREAMS -1
|
||||
#define _XOPEN_UNIX -1
|
||||
#define _XOPEN_UUCP -1
|
||||
#define _XOPEN_SHM -1
|
||||
#define _XOPEN_STREAMS -1
|
||||
#define _XOPEN_UNIX 200809L
|
||||
#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>
|
||||
|
@ -104,31 +124,370 @@ __BEGIN_DECLS
|
|||
#define __need_useconds_t
|
||||
#include <sys/types.h>
|
||||
|
||||
// FIXME: _CS prefixed definitions
|
||||
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
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
_PC_2_SYMLINKS,
|
||||
_PC_2_SYMLINKS = 1,
|
||||
#define _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
|
||||
|
|
|
@ -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 c, FILE* stream);
|
||||
wint_t fputwc(wchar_t wc, 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, ...);
|
||||
|
|
|
@ -1,56 +1,22 @@
|
|||
#include <poll.h>
|
||||
#include <sys/select.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int poll(struct pollfd fds[], nfds_t nfds, int timeout)
|
||||
{
|
||||
fd_set rfds, wfds, efds;
|
||||
FD_ZERO(&rfds);
|
||||
FD_ZERO(&wfds);
|
||||
FD_ZERO(&efds);
|
||||
|
||||
for (nfds_t i = 0; i < nfds; i++)
|
||||
fds[i].revents = 0;
|
||||
|
||||
constexpr short rmask = POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI | POLLHUP;
|
||||
constexpr short wmask = POLLOUT | POLLWRNORM | POLLWRBAND;
|
||||
constexpr short emask = POLLERR;
|
||||
|
||||
int max_fd = 0;
|
||||
for (nfds_t i = 0; i < nfds; i++)
|
||||
{
|
||||
if (fds[i].fd < 0)
|
||||
continue;
|
||||
|
||||
if (fds[i].events & rmask)
|
||||
FD_SET(fds[i].fd, &rfds);
|
||||
if (fds[i].events & wmask)
|
||||
FD_SET(fds[i].fd, &wfds);
|
||||
if (fds[i].events & emask)
|
||||
FD_SET(fds[i].fd, &efds);
|
||||
|
||||
if (fds[i].fd > max_fd)
|
||||
max_fd = fds[i].fd;
|
||||
}
|
||||
|
||||
timeval tv;
|
||||
tv.tv_sec = timeout / 1000;
|
||||
tv.tv_usec = timeout % 1000 * 1000;
|
||||
int nselect = select(max_fd + 1, &rfds, &wfds, &efds, &tv);
|
||||
if (nselect == -1)
|
||||
return -1;
|
||||
|
||||
for (nfds_t i = 0; i < nfds; i++)
|
||||
{
|
||||
if (fds[i].fd < 0)
|
||||
continue;
|
||||
|
||||
if (FD_ISSET(fds[i].fd, &rfds))
|
||||
fds[i].revents |= fds[i].events & rmask;
|
||||
if (FD_ISSET(fds[i].fd, &wfds))
|
||||
fds[i].revents |= fds[i].events & wmask;
|
||||
if (FD_ISSET(fds[i].fd, &efds))
|
||||
fds[i].revents |= fds[i].events & emask;
|
||||
}
|
||||
|
||||
return nselect;
|
||||
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);
|
||||
}
|
||||
|
||||
int ppoll(struct pollfd fds[], nfds_t nfds, const struct timespec* timeout, const sigset_t* sigmask)
|
||||
{
|
||||
pthread_testcancel();
|
||||
return syscall(SYS_PPOLL, fds, nfds, timeout, sigmask);
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <BAN/PlacementNew.h>
|
||||
|
||||
#include <kernel/Arch.h>
|
||||
#include <kernel/Thread.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
|
@ -46,13 +47,14 @@ 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();
|
||||
}
|
||||
|
||||
static uthread* get_uthread()
|
||||
uthread* _get_uthread()
|
||||
{
|
||||
uthread* result;
|
||||
#if ARCH(x86_64)
|
||||
|
@ -75,22 +77,13 @@ 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)
|
||||
{
|
||||
ASSERT(s_cleanup_stack);
|
||||
uthread* uthread = _get_uthread();
|
||||
ASSERT(uthread->cleanup_stack);
|
||||
|
||||
auto* cleanup = s_cleanup_stack;
|
||||
s_cleanup_stack = cleanup->next;
|
||||
auto* cleanup = uthread->cleanup_stack;
|
||||
uthread->cleanup_stack = cleanup->next;
|
||||
|
||||
if (execute)
|
||||
cleanup->routine(cleanup->arg);
|
||||
|
@ -100,16 +93,17 @@ 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 = s_cleanup_stack;
|
||||
cleanup->next = uthread->cleanup_stack;
|
||||
|
||||
s_cleanup_stack = cleanup;
|
||||
uthread->cleanup_stack = cleanup;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if not __disable_thread_local_storage
|
||||
static thread_local struct {
|
||||
|
@ -175,38 +169,148 @@ int pthread_attr_destroy(pthread_attr_t* attr)
|
|||
|
||||
int pthread_attr_init(pthread_attr_t* attr)
|
||||
{
|
||||
*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");
|
||||
*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()),
|
||||
};
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_attr_getdetachstate(const pthread_attr_t* attr, int* detachstate)
|
||||
{
|
||||
(void)attr;
|
||||
*detachstate = PTHREAD_CREATE_JOINABLE;
|
||||
*detachstate = attr->detachstate;
|
||||
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;
|
||||
}
|
||||
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)
|
||||
|
@ -223,14 +327,23 @@ 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;
|
||||
uthread->master_tls_addr = nullptr;
|
||||
uthread->master_tls_size = 0;
|
||||
|
||||
*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->dtv[0] = 0;
|
||||
|
||||
info->uthread = uthread;
|
||||
|
@ -249,9 +362,17 @@ 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;
|
||||
uthread->master_tls_addr = self->master_tls_addr;
|
||||
uthread->master_tls_size = 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,
|
||||
};
|
||||
|
||||
const uintptr_t self_addr = reinterpret_cast<uintptr_t>(self);
|
||||
const uintptr_t uthread_addr = reinterpret_cast<uintptr_t>(uthread);
|
||||
|
@ -288,9 +409,11 @@ int pthread_detach(pthread_t thread)
|
|||
|
||||
void pthread_exit(void* value_ptr)
|
||||
{
|
||||
#if not __disable_thread_local_storage
|
||||
while (s_cleanup_stack)
|
||||
uthread* uthread = _get_uthread();
|
||||
while (uthread->cleanup_stack)
|
||||
pthread_cleanup_pop(1);
|
||||
|
||||
#if not __disable_thread_local_storage
|
||||
for (size_t iteration = 0; iteration < PTHREAD_DESTRUCTOR_ITERATIONS; iteration++)
|
||||
{
|
||||
bool called = false;
|
||||
|
@ -309,7 +432,8 @@ void pthread_exit(void* value_ptr)
|
|||
break;
|
||||
}
|
||||
#endif
|
||||
free_uthread(get_uthread());
|
||||
|
||||
free_uthread(uthread);
|
||||
syscall(SYS_PTHREAD_EXIT, value_ptr);
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
@ -321,19 +445,13 @@ 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)
|
||||
{
|
||||
#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
|
||||
return _get_uthread()->id;
|
||||
}
|
||||
|
||||
int pthread_once(pthread_once_t* once_control, void (*init_routine)(void))
|
||||
|
@ -352,6 +470,168 @@ 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;
|
||||
|
@ -732,7 +1012,7 @@ int pthread_condattr_getpshared(const pthread_condattr_t* __restrict attr, int*
|
|||
return 0;
|
||||
}
|
||||
|
||||
int pthread_condattr_setpshared(pthread_barrierattr_t* attr, int pshared)
|
||||
int pthread_condattr_setpshared(pthread_condattr_t* attr, int pshared)
|
||||
{
|
||||
switch (pshared)
|
||||
{
|
||||
|
@ -788,11 +1068,14 @@ 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
|
||||
{
|
||||
|
@ -925,7 +1208,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)
|
||||
|
|
|
@ -38,9 +38,18 @@ 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)
|
||||
{
|
||||
return syscall(SYS_SIGPROCMASK, how, set, oset);
|
||||
if (syscall(SYS_SIGPROCMASK, how, set, oset) == -1)
|
||||
return errno;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int raise(int sig)
|
||||
|
@ -138,7 +147,12 @@ int sigpending(sigset_t* set)
|
|||
|
||||
int sigprocmask(int how, const sigset_t* __restrict set, sigset_t* __restrict oset)
|
||||
{
|
||||
return pthread_sigmask(how, set, oset);
|
||||
if (int error = pthread_sigmask(how, set, oset))
|
||||
{
|
||||
errno = error;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sigrelse(int sig)
|
||||
|
|
|
@ -190,6 +190,8 @@ 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;
|
||||
}
|
||||
}
|
||||
|
@ -364,6 +366,19 @@ 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];
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#include <pthread.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
|
@ -25,6 +26,7 @@ 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);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
#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,
|
||||
|
@ -17,6 +19,7 @@ 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)
|
||||
|
|
|
@ -1,14 +1,17 @@
|
|||
#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);
|
||||
}
|
||||
|
||||
|
@ -19,6 +22,7 @@ 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);
|
||||
}
|
||||
|
||||
|
@ -29,11 +33,13 @@ 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,
|
||||
|
@ -47,11 +53,13 @@ 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,
|
||||
|
|
|
@ -53,3 +53,13 @@ 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);
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#include <fcntl.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
@ -26,3 +27,20 @@ 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);
|
||||
}
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
#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++)
|
||||
{
|
||||
|
@ -25,6 +28,8 @@ 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++)
|
||||
{
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
#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);
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include <BAN/Debug.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
|
@ -64,9 +65,19 @@ int cfsetospeed(struct termios* termios, speed_t speed)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int tcdrain(int);
|
||||
int tcdrain(int fd)
|
||||
{
|
||||
pthread_testcancel();
|
||||
|
||||
int tcflow(int, int);
|
||||
dwarnln("TODO: tcdrain({})", fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tcflow(int fd, int action)
|
||||
{
|
||||
dwarnln("TODO: tcflow({}, {})", fd, action);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int tcflush(int fd, int queue_selector)
|
||||
{
|
||||
|
@ -81,7 +92,11 @@ int tcgetattr(int fildes, struct termios* termios)
|
|||
|
||||
pid_t tcgetsid(int);
|
||||
|
||||
int tcsendbreak(int, int);
|
||||
int tcsendbreak(int fd, int duration)
|
||||
{
|
||||
dwarnln("FIXME: tcsendbreak({}, {})", fd, duration);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int tcsetattr(int fildes, int optional_actions, const struct termios* termios)
|
||||
{
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <langinfo.h>
|
||||
#include <pthread.h>
|
||||
#include <string.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <time.h>
|
||||
|
@ -20,6 +21,7 @@ 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);
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,16 @@ extern "C" void _init_libc(char** environ, init_funcs_t init_funcs, init_funcs_t
|
|||
if (::environ == nullptr)
|
||||
::environ = environ;
|
||||
|
||||
if (syscall(SYS_GET_TLS) == 0)
|
||||
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
|
||||
{
|
||||
alignas(uthread) static uint8_t storage[sizeof(uthread) + sizeof(uintptr_t)];
|
||||
|
||||
|
@ -43,6 +52,12 @@ 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;
|
||||
|
||||
|
@ -99,16 +114,19 @@ 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);
|
||||
}
|
||||
|
||||
|
@ -124,11 +142,13 @@ 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);
|
||||
}
|
||||
|
||||
|
@ -137,13 +157,24 @@ 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_TRUNCATE, fildes, length);
|
||||
return syscall(SYS_FTRUNCATE, fildes, length);
|
||||
}
|
||||
|
||||
int fsync(int fildes)
|
||||
{
|
||||
pthread_testcancel();
|
||||
return syscall(SYS_FSYNC, fildes);
|
||||
}
|
||||
|
||||
|
@ -402,7 +433,12 @@ int execvp(const char* pathname, char* const argv[])
|
|||
|
||||
pid_t fork(void)
|
||||
{
|
||||
return syscall(SYS_FORK);
|
||||
_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;
|
||||
}
|
||||
|
||||
int pipe(int fildes[2])
|
||||
|
@ -412,6 +448,7 @@ 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;
|
||||
|
@ -480,14 +517,28 @@ 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 syscall(SYS_UNLINK, path);
|
||||
return unlinkat(AT_FDCWD, path, 0);
|
||||
}
|
||||
|
||||
int unlinkat(int fd, const char* path, int flag)
|
||||
{
|
||||
return syscall(SYS_UNLINKAT, fd, path, flag);
|
||||
}
|
||||
|
||||
int rmdir(const char* path)
|
||||
{
|
||||
return syscall(SYS_UNLINK, path);
|
||||
return unlinkat(AT_FDCWD, path, AT_REMOVEDIR);
|
||||
}
|
||||
|
||||
char* optarg = nullptr;
|
||||
|
@ -771,3 +822,199 @@ 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;
|
||||
}
|
||||
|
|
|
@ -1,11 +1,20 @@
|
|||
#include <utime.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#include <utime.h>
|
||||
|
||||
int utime(const char* filename, const struct utimbuf* times)
|
||||
{
|
||||
fprintf(stddbg, "TODO: utime(\"%s\", %p)\n", filename, times);
|
||||
|
||||
struct stat st;
|
||||
return stat(filename, &st);
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
#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;
|
||||
}
|
|
@ -1,10 +1,112 @@
|
|||
#include <BAN/Assert.h>
|
||||
#include <BAN/UTF8.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <locale.h>
|
||||
#include <wchar.h>
|
||||
|
||||
size_t mbrtowc(wchar_t* __restrict, const char* __restrict, size_t, mbstate_t* __restrict)
|
||||
wint_t btowc(int c)
|
||||
{
|
||||
ASSERT_NOT_REACHED();
|
||||
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;
|
||||
}
|
||||
|
||||
int wcscmp(const wchar_t* ws1, const wchar_t* ws2)
|
||||
|
@ -182,3 +284,93 @@ 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;
|
||||
}
|
||||
|
|
|
@ -928,7 +928,6 @@ 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;
|
||||
|
|
Loading…
Reference in New Issue