Compare commits
56 Commits
987cc3c237
...
eb9fe8ffc6
Author | SHA1 | Date |
---|---|---|
|
eb9fe8ffc6 | |
|
6ccc727dd0 | |
|
40d942ca32 | |
|
44bfb57953 | |
|
342682d5d5 | |
|
b586917930 | |
|
45ad6082bc | |
|
f27823babe | |
|
95cfac471a | |
|
f7c1084c3e | |
|
cf96bb6cc3 | |
|
f1369c8fd6 | |
|
eb7922ab88 | |
|
dfdfb7cdaf | |
|
1cc0fb9c01 | |
|
a51b589bc9 | |
|
5940e912b3 | |
|
658a001d91 | |
|
57c9f5a8a8 | |
|
fa7b58057c | |
|
0e0f5295cf | |
|
284c9e5f61 | |
|
927fbda1e8 | |
|
d25a5034db | |
|
f197d39aaf | |
|
4a95343936 | |
|
4e705a91af | |
|
82b351469b | |
|
ea91bdcce7 | |
|
256c9daefd | |
|
af0a46e79c | |
|
4519c48284 | |
|
8ea32c7650 | |
|
5972d40ced | |
|
f35a6b3922 | |
|
21009c37b4 | |
|
11a2d15003 | |
|
d8a695a88d | |
|
f82390424b | |
|
08ed405a5b | |
|
8c598a6902 | |
|
8e9c40caa4 | |
|
8c29036fbf | |
|
b46337d376 | |
|
56d701492b | |
|
07e4e764a0 | |
|
66fe2f2e50 | |
|
fda0ced72e | |
|
654e8bb7f6 | |
|
80ffde5e1e | |
|
52309e0754 | |
|
31e411f8f1 | |
|
de45b760b5 | |
|
ff29e9c4d6 | |
|
cc04bd0f06 | |
|
e72e1e4e43 |
|
@ -14,6 +14,23 @@
|
||||||
# multiboot2 header
|
# multiboot2 header
|
||||||
.section .multiboot, "aw"
|
.section .multiboot, "aw"
|
||||||
.align 8
|
.align 8
|
||||||
|
multiboot_start:
|
||||||
|
.long 0x1BADB002
|
||||||
|
.long (1 << 2) # page align modules
|
||||||
|
.long -(0x1BADB002 + (1 << 2))
|
||||||
|
|
||||||
|
.long 0
|
||||||
|
.long 0
|
||||||
|
.long 0
|
||||||
|
.long 0
|
||||||
|
.long 0
|
||||||
|
|
||||||
|
.long 0
|
||||||
|
.long FB_WIDTH
|
||||||
|
.long FB_HEIGHT
|
||||||
|
.long FB_BPP
|
||||||
|
multiboot_end:
|
||||||
|
.align 8
|
||||||
multiboot2_start:
|
multiboot2_start:
|
||||||
.long 0xE85250D6
|
.long 0xE85250D6
|
||||||
.long 0
|
.long 0
|
||||||
|
|
|
@ -14,6 +14,23 @@
|
||||||
# multiboot2 header
|
# multiboot2 header
|
||||||
.section .multiboot, "aw"
|
.section .multiboot, "aw"
|
||||||
.align 8
|
.align 8
|
||||||
|
multiboot_start:
|
||||||
|
.long 0x1BADB002
|
||||||
|
.long (1 << 2) # page align modules
|
||||||
|
.long -(0x1BADB002 + (1 << 2))
|
||||||
|
|
||||||
|
.long 0
|
||||||
|
.long 0
|
||||||
|
.long 0
|
||||||
|
.long 0
|
||||||
|
.long 0
|
||||||
|
|
||||||
|
.long 0
|
||||||
|
.long FB_WIDTH
|
||||||
|
.long FB_HEIGHT
|
||||||
|
.long FB_BPP
|
||||||
|
multiboot_end:
|
||||||
|
.align 8
|
||||||
multiboot2_start:
|
multiboot2_start:
|
||||||
.long 0xE85250D6
|
.long 0xE85250D6
|
||||||
.long 0
|
.long 0
|
||||||
|
|
|
@ -16,7 +16,11 @@ namespace Kernel
|
||||||
virtual bool is_partition() const { return false; }
|
virtual bool is_partition() const { return false; }
|
||||||
virtual bool is_storage_device() const { return false; }
|
virtual bool is_storage_device() const { return false; }
|
||||||
|
|
||||||
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> mmap_region(PageTable&, off_t offset, size_t len, AddressRange, MemoryRegion::Type, PageTable::flags_t) { (void)offset; (void)len; return BAN::Error::from_errno(EINVAL); }
|
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> mmap_region(PageTable&, off_t offset, size_t len, AddressRange, MemoryRegion::Type, PageTable::flags_t, int status_flags)
|
||||||
|
{
|
||||||
|
(void)offset; (void)len; (void)status_flags;
|
||||||
|
return BAN::Error::from_errno(ENOTSUP);
|
||||||
|
}
|
||||||
|
|
||||||
virtual dev_t rdev() const override = 0;
|
virtual dev_t rdev() const override = 0;
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ namespace Kernel
|
||||||
void sync_pixels_linear(uint32_t first_pixel, uint32_t pixel_count);
|
void sync_pixels_linear(uint32_t first_pixel, uint32_t pixel_count);
|
||||||
void sync_pixels_rectangle(uint32_t top_right_x, uint32_t top_right_y, uint32_t width, uint32_t height);
|
void sync_pixels_rectangle(uint32_t top_right_x, uint32_t top_right_y, uint32_t width, uint32_t height);
|
||||||
|
|
||||||
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> mmap_region(PageTable&, off_t offset, size_t len, AddressRange, MemoryRegion::Type, PageTable::flags_t) override;
|
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> mmap_region(PageTable&, off_t offset, size_t len, AddressRange, MemoryRegion::Type, PageTable::flags_t, int status_flags) override;
|
||||||
|
|
||||||
virtual dev_t rdev() const override { return m_rdev; }
|
virtual dev_t rdev() const override { return m_rdev; }
|
||||||
virtual BAN::StringView name() const override { return m_name.sv(); }
|
virtual BAN::StringView name() const override { return m_name.sv(); }
|
||||||
|
|
|
@ -22,7 +22,7 @@ namespace Kernel
|
||||||
|
|
||||||
class FileBackedRegion;
|
class FileBackedRegion;
|
||||||
class FileSystem;
|
class FileSystem;
|
||||||
class SharedFileData;
|
struct SharedFileData;
|
||||||
|
|
||||||
class Inode : public BAN::RefCounted<Inode>
|
class Inode : public BAN::RefCounted<Inode>
|
||||||
{
|
{
|
||||||
|
|
|
@ -27,18 +27,18 @@ namespace Kernel
|
||||||
BAN_NON_MOVABLE(FileBackedRegion);
|
BAN_NON_MOVABLE(FileBackedRegion);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static BAN::ErrorOr<BAN::UniqPtr<FileBackedRegion>> create(BAN::RefPtr<Inode>, PageTable&, off_t offset, size_t size, AddressRange address_range, Type, PageTable::flags_t);
|
static BAN::ErrorOr<BAN::UniqPtr<FileBackedRegion>> create(BAN::RefPtr<Inode>, PageTable&, off_t offset, size_t size, AddressRange address_range, Type, PageTable::flags_t, int status_flags);
|
||||||
~FileBackedRegion();
|
~FileBackedRegion();
|
||||||
|
|
||||||
virtual BAN::ErrorOr<void> msync(vaddr_t, size_t, int) override;
|
BAN::ErrorOr<void> msync(vaddr_t, size_t, int) override;
|
||||||
|
|
||||||
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) override;
|
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual BAN::ErrorOr<bool> allocate_page_containing_impl(vaddr_t vaddr, bool wants_write) override;
|
BAN::ErrorOr<bool> allocate_page_containing_impl(vaddr_t vaddr, bool wants_write) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FileBackedRegion(BAN::RefPtr<Inode>, PageTable&, off_t offset, ssize_t size, Type flags, PageTable::flags_t page_flags);
|
FileBackedRegion(BAN::RefPtr<Inode>, PageTable&, off_t offset, ssize_t size, Type type, PageTable::flags_t flags, int status_flags);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BAN::RefPtr<Inode> m_inode;
|
BAN::RefPtr<Inode> m_inode;
|
||||||
|
|
|
@ -11,22 +11,22 @@ namespace Kernel
|
||||||
BAN_NON_MOVABLE(MemoryBackedRegion);
|
BAN_NON_MOVABLE(MemoryBackedRegion);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static BAN::ErrorOr<BAN::UniqPtr<MemoryBackedRegion>> create(PageTable&, size_t size, AddressRange, Type, PageTable::flags_t);
|
static BAN::ErrorOr<BAN::UniqPtr<MemoryBackedRegion>> create(PageTable&, size_t size, AddressRange, Type, PageTable::flags_t, int status_flags);
|
||||||
~MemoryBackedRegion();
|
~MemoryBackedRegion();
|
||||||
|
|
||||||
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) override;
|
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) override;
|
||||||
|
|
||||||
virtual BAN::ErrorOr<void> msync(vaddr_t, size_t, int) override { return {}; }
|
BAN::ErrorOr<void> msync(vaddr_t, size_t, int) override { return {}; }
|
||||||
|
|
||||||
// Copy data from buffer into this region
|
// Copy data from buffer into this region
|
||||||
// This can fail if no memory is mapped and no free memory was available
|
// This can fail if no memory is mapped and no free memory was available
|
||||||
BAN::ErrorOr<void> copy_data_to_region(size_t offset_into_region, const uint8_t* buffer, size_t buffer_size);
|
BAN::ErrorOr<void> copy_data_to_region(size_t offset_into_region, const uint8_t* buffer, size_t buffer_size);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual BAN::ErrorOr<bool> allocate_page_containing_impl(vaddr_t vaddr, bool wants_write) override;
|
BAN::ErrorOr<bool> allocate_page_containing_impl(vaddr_t vaddr, bool wants_write) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MemoryBackedRegion(PageTable&, size_t size, Type, PageTable::flags_t);
|
MemoryBackedRegion(PageTable&, size_t size, Type, PageTable::flags_t, int status_flags);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,10 @@ namespace Kernel
|
||||||
size_t size() const { return m_size; }
|
size_t size() const { return m_size; }
|
||||||
vaddr_t vaddr() const { return m_vaddr; }
|
vaddr_t vaddr() const { return m_vaddr; }
|
||||||
|
|
||||||
|
int status_flags() const { return m_status_flags; }
|
||||||
|
Type type() const { return m_type; }
|
||||||
|
PageTable::flags_t flags() const { return m_flags; }
|
||||||
|
|
||||||
size_t virtual_page_count() const { return BAN::Math::div_round_up<size_t>(m_size, PAGE_SIZE); }
|
size_t virtual_page_count() const { return BAN::Math::div_round_up<size_t>(m_size, PAGE_SIZE); }
|
||||||
size_t physical_page_count() const { return m_physical_page_count; }
|
size_t physical_page_count() const { return m_physical_page_count; }
|
||||||
|
|
||||||
|
@ -46,6 +50,7 @@ namespace Kernel
|
||||||
void unpin();
|
void unpin();
|
||||||
void wait_not_pinned();
|
void wait_not_pinned();
|
||||||
|
|
||||||
|
BAN::ErrorOr<void> mprotect(PageTable::flags_t);
|
||||||
virtual BAN::ErrorOr<void> msync(vaddr_t, size_t, int) = 0;
|
virtual BAN::ErrorOr<void> msync(vaddr_t, size_t, int) = 0;
|
||||||
|
|
||||||
// Returns error if no memory was available
|
// Returns error if no memory was available
|
||||||
|
@ -56,7 +61,7 @@ namespace Kernel
|
||||||
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) = 0;
|
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
MemoryRegion(PageTable&, size_t size, Type type, PageTable::flags_t flags);
|
MemoryRegion(PageTable&, size_t size, Type type, PageTable::flags_t flags, int status_flags);
|
||||||
BAN::ErrorOr<void> initialize(AddressRange);
|
BAN::ErrorOr<void> initialize(AddressRange);
|
||||||
|
|
||||||
virtual BAN::ErrorOr<bool> allocate_page_containing_impl(vaddr_t address, bool wants_write) = 0;
|
virtual BAN::ErrorOr<bool> allocate_page_containing_impl(vaddr_t address, bool wants_write) = 0;
|
||||||
|
@ -65,7 +70,8 @@ namespace Kernel
|
||||||
PageTable& m_page_table;
|
PageTable& m_page_table;
|
||||||
const size_t m_size;
|
const size_t m_size;
|
||||||
const Type m_type;
|
const Type m_type;
|
||||||
const PageTable::flags_t m_flags;
|
PageTable::flags_t m_flags;
|
||||||
|
const int m_status_flags;
|
||||||
vaddr_t m_vaddr { 0 };
|
vaddr_t m_vaddr { 0 };
|
||||||
size_t m_physical_page_count { 0 };
|
size_t m_physical_page_count { 0 };
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
#include <kernel/Lock/SpinLock.h>
|
#include <kernel/Lock/SpinLock.h>
|
||||||
#include <kernel/Memory/MemoryRegion.h>
|
#include <kernel/Memory/MemoryRegion.h>
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -55,15 +57,16 @@ namespace Kernel
|
||||||
public:
|
public:
|
||||||
static BAN::ErrorOr<BAN::UniqPtr<SharedMemoryObject>> create(BAN::RefPtr<SharedMemoryObjectManager::Object>, PageTable&, AddressRange);
|
static BAN::ErrorOr<BAN::UniqPtr<SharedMemoryObject>> create(BAN::RefPtr<SharedMemoryObjectManager::Object>, PageTable&, AddressRange);
|
||||||
|
|
||||||
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) override;
|
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) override;
|
||||||
virtual BAN::ErrorOr<void> msync(vaddr_t, size_t, int) override { return {}; }
|
|
||||||
|
BAN::ErrorOr<void> msync(vaddr_t, size_t, int) override { return {}; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual BAN::ErrorOr<bool> allocate_page_containing_impl(vaddr_t vaddr, bool wants_write) override;
|
BAN::ErrorOr<bool> allocate_page_containing_impl(vaddr_t vaddr, bool wants_write) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SharedMemoryObject(BAN::RefPtr<SharedMemoryObjectManager::Object> object, PageTable& page_table)
|
SharedMemoryObject(BAN::RefPtr<SharedMemoryObjectManager::Object> object, PageTable& page_table)
|
||||||
: MemoryRegion(page_table, object->size, MemoryRegion::Type::SHARED, object->flags)
|
: MemoryRegion(page_table, object->size, MemoryRegion::Type::SHARED, object->flags, O_EXEC | O_RDWR)
|
||||||
, m_object(object)
|
, m_object(object)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ namespace Kernel
|
||||||
|
|
||||||
bool contains(vaddr_t address) const { return vaddr() <= address && address < vaddr() + size(); }
|
bool contains(vaddr_t address) const { return vaddr() <= address && address < vaddr() + size(); }
|
||||||
|
|
||||||
BAN::ErrorOr<void> allocate_page_for_demand_paging(vaddr_t address);
|
BAN::ErrorOr<bool> allocate_page_for_demand_paging(vaddr_t address);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VirtualRange(PageTable&, bool preallocated, bool has_guard_pages, vaddr_t, size_t, PageTable::flags_t);
|
VirtualRange(PageTable&, bool preallocated, bool has_guard_pages, vaddr_t, size_t, PageTable::flags_t);
|
||||||
|
|
|
@ -161,6 +161,8 @@ namespace Kernel
|
||||||
|
|
||||||
BAN::ErrorOr<long> sys_sync(bool should_block);
|
BAN::ErrorOr<long> sys_sync(bool should_block);
|
||||||
|
|
||||||
|
BAN::ErrorOr<long> sys_get_nprocessor();
|
||||||
|
|
||||||
static BAN::ErrorOr<long> clean_poweroff(int command);
|
static BAN::ErrorOr<long> clean_poweroff(int command);
|
||||||
BAN::ErrorOr<long> sys_poweroff(int command);
|
BAN::ErrorOr<long> sys_poweroff(int command);
|
||||||
|
|
||||||
|
@ -168,13 +170,14 @@ namespace Kernel
|
||||||
|
|
||||||
BAN::ErrorOr<long> sys_mmap(const sys_mmap_t*);
|
BAN::ErrorOr<long> sys_mmap(const sys_mmap_t*);
|
||||||
BAN::ErrorOr<long> sys_munmap(void* addr, size_t len);
|
BAN::ErrorOr<long> sys_munmap(void* addr, size_t len);
|
||||||
|
BAN::ErrorOr<long> sys_mprotect(void* addr, size_t len, int prot);
|
||||||
BAN::ErrorOr<long> sys_msync(void* addr, size_t len, int flags);
|
BAN::ErrorOr<long> sys_msync(void* addr, size_t len, int flags);
|
||||||
|
|
||||||
BAN::ErrorOr<long> sys_smo_create(size_t len, int prot);
|
BAN::ErrorOr<long> sys_smo_create(size_t len, int prot);
|
||||||
BAN::ErrorOr<long> sys_smo_delete(SharedMemoryObjectManager::Key);
|
BAN::ErrorOr<long> sys_smo_delete(SharedMemoryObjectManager::Key);
|
||||||
BAN::ErrorOr<long> sys_smo_map(SharedMemoryObjectManager::Key);
|
BAN::ErrorOr<long> sys_smo_map(SharedMemoryObjectManager::Key);
|
||||||
|
|
||||||
BAN::ErrorOr<long> sys_ttyname(int fildes, char* storage);
|
BAN::ErrorOr<long> sys_ttyname(int fildes, char* name, size_t namesize);
|
||||||
BAN::ErrorOr<long> sys_isatty(int fildes);
|
BAN::ErrorOr<long> sys_isatty(int fildes);
|
||||||
BAN::ErrorOr<long> sys_posix_openpt(int flags);
|
BAN::ErrorOr<long> sys_posix_openpt(int flags);
|
||||||
BAN::ErrorOr<long> sys_ptsname(int fildes, char* buffer, size_t buffer_len);
|
BAN::ErrorOr<long> sys_ptsname(int fildes, char* buffer, size_t buffer_len);
|
||||||
|
@ -187,6 +190,7 @@ namespace Kernel
|
||||||
BAN::ErrorOr<long> sys_sigpending(sigset_t* set);
|
BAN::ErrorOr<long> sys_sigpending(sigset_t* set);
|
||||||
BAN::ErrorOr<long> sys_sigprocmask(int how, const sigset_t* set, sigset_t* oset);
|
BAN::ErrorOr<long> sys_sigprocmask(int how, const sigset_t* set, sigset_t* oset);
|
||||||
|
|
||||||
|
BAN::ErrorOr<long> sys_futex(int op, const uint32_t* addr, uint32_t val, const timespec* abstime);
|
||||||
BAN::ErrorOr<long> sys_yield();
|
BAN::ErrorOr<long> sys_yield();
|
||||||
BAN::ErrorOr<long> sys_set_tls(void*);
|
BAN::ErrorOr<long> sys_set_tls(void*);
|
||||||
BAN::ErrorOr<long> sys_get_tls();
|
BAN::ErrorOr<long> sys_get_tls();
|
||||||
|
@ -218,7 +222,7 @@ namespace Kernel
|
||||||
// Returns error if page could not be allocated
|
// Returns error if page could not be allocated
|
||||||
// Returns true if the page was allocated successfully
|
// Returns true if the page was allocated successfully
|
||||||
// Return false if access was page violation (segfault)
|
// Return false if access was page violation (segfault)
|
||||||
BAN::ErrorOr<bool> allocate_page_for_demand_paging(vaddr_t addr, bool wants_write);
|
BAN::ErrorOr<bool> allocate_page_for_demand_paging(vaddr_t addr, bool wants_write, bool wants_exec);
|
||||||
|
|
||||||
// FIXME: remove this API
|
// FIXME: remove this API
|
||||||
BAN::ErrorOr<BAN::String> absolute_path_of(BAN::StringView) const;
|
BAN::ErrorOr<BAN::String> absolute_path_of(BAN::StringView) const;
|
||||||
|
@ -335,6 +339,14 @@ namespace Kernel
|
||||||
BAN::UniqPtr<PageTable> m_page_table;
|
BAN::UniqPtr<PageTable> m_page_table;
|
||||||
BAN::RefPtr<TTY> m_controlling_terminal;
|
BAN::RefPtr<TTY> m_controlling_terminal;
|
||||||
|
|
||||||
|
struct futex_t
|
||||||
|
{
|
||||||
|
ThreadBlocker blocker;
|
||||||
|
uint32_t waiters { 0 };
|
||||||
|
uint32_t to_wakeup { 0 };
|
||||||
|
};
|
||||||
|
BAN::HashMap<paddr_t, BAN::UniqPtr<futex_t>> m_futexes;
|
||||||
|
|
||||||
friend class Thread;
|
friend class Thread;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include <kernel/BootInfo.h>
|
#include <kernel/BootInfo.h>
|
||||||
#include <kernel/BananBootloader.h>
|
#include <kernel/BananBootloader.h>
|
||||||
|
#include <kernel/multiboot.h>
|
||||||
#include <kernel/multiboot2.h>
|
#include <kernel/multiboot2.h>
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
|
@ -20,6 +21,70 @@ namespace Kernel
|
||||||
return MemoryMapEntry::Type::Reserved;
|
return MemoryMapEntry::Type::Reserved;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void parse_boot_info_multiboot(uint32_t info)
|
||||||
|
{
|
||||||
|
const auto& multiboot_info = *reinterpret_cast<const multiboot_info_t*>(info);
|
||||||
|
|
||||||
|
if (multiboot_info.flags & MULTIBOOT_FLAGS_CMDLINE)
|
||||||
|
{
|
||||||
|
MUST(g_boot_info.command_line.append(reinterpret_cast<const char*>(multiboot_info.cmdline)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (multiboot_info.flags & MULTIBOOT_FLAGS_MODULES)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < multiboot_info.mods_count; i++)
|
||||||
|
{
|
||||||
|
const auto& module = reinterpret_cast<const multiboot_module_t*>(multiboot_info.mods_addr)[i];
|
||||||
|
MUST(g_boot_info.modules.emplace_back(module.mod_start, module.mod_end - module.mod_start));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (multiboot_info.flags & MULTIBOOT_FLAGS_MMAP)
|
||||||
|
{
|
||||||
|
uintptr_t address = multiboot_info.mmap_addr;
|
||||||
|
while (address < multiboot_info.mmap_addr + multiboot_info.mmap_length)
|
||||||
|
{
|
||||||
|
const auto& mmap_entry = *reinterpret_cast<const multiboot_mmap_t*>(address);
|
||||||
|
dprintln("entry {16H} {16H} {8H}",
|
||||||
|
(uint64_t)mmap_entry.base_addr,
|
||||||
|
(uint64_t)mmap_entry.length,
|
||||||
|
(uint64_t)mmap_entry.type
|
||||||
|
);
|
||||||
|
MUST(g_boot_info.memory_map_entries.push_back({
|
||||||
|
.address = mmap_entry.base_addr,
|
||||||
|
.length = mmap_entry.length,
|
||||||
|
.type = bios_number_to_memory_type(mmap_entry.type),
|
||||||
|
}));
|
||||||
|
address += mmap_entry.size + sizeof(mmap_entry.size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (multiboot_info.flags & MULTIBOOT_FLAGS_FRAMEBUFFER)
|
||||||
|
{
|
||||||
|
g_boot_info.framebuffer.address = multiboot_info.framebuffer_addr;
|
||||||
|
g_boot_info.framebuffer.pitch = multiboot_info.framebuffer_pitch;
|
||||||
|
g_boot_info.framebuffer.width = multiboot_info.framebuffer_width;
|
||||||
|
g_boot_info.framebuffer.height = multiboot_info.framebuffer_height;
|
||||||
|
g_boot_info.framebuffer.bpp = multiboot_info.framebuffer_bpp;
|
||||||
|
if (multiboot_info.framebuffer_type == MULTIBOOT_FRAMEBUFFER_TYPE_RGB)
|
||||||
|
g_boot_info.framebuffer.type = FramebufferInfo::Type::RGB;
|
||||||
|
else if (multiboot_info.framebuffer_type == MULTIBOOT_FRAMEBUFFER_TYPE_TEXT)
|
||||||
|
g_boot_info.framebuffer.type = FramebufferInfo::Type::Text;
|
||||||
|
else
|
||||||
|
g_boot_info.framebuffer.type = FramebufferInfo::Type::Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_boot_info.kernel_paddr = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BAN::StringView get_early_boot_command_line_multiboot(uint32_t info)
|
||||||
|
{
|
||||||
|
const auto& multiboot_info = *reinterpret_cast<const multiboot_info_t*>(info);
|
||||||
|
if (!(multiboot_info.flags & MULTIBOOT_FLAGS_CMDLINE))
|
||||||
|
return ""_sv;
|
||||||
|
return BAN::StringView(reinterpret_cast<const char*>(multiboot_info.cmdline));
|
||||||
|
}
|
||||||
|
|
||||||
static void parse_boot_info_multiboot2(uint32_t info)
|
static void parse_boot_info_multiboot2(uint32_t info)
|
||||||
{
|
{
|
||||||
const auto& multiboot2_info = *reinterpret_cast<const multiboot2_info_t*>(info);
|
const auto& multiboot2_info = *reinterpret_cast<const multiboot2_info_t*>(info);
|
||||||
|
@ -149,17 +214,23 @@ namespace Kernel
|
||||||
|
|
||||||
bool validate_boot_magic(uint32_t magic)
|
bool validate_boot_magic(uint32_t magic)
|
||||||
{
|
{
|
||||||
if (magic == MULTIBOOT2_MAGIC)
|
switch (magic)
|
||||||
return true;
|
{
|
||||||
if (magic == BANAN_BOOTLOADER_MAGIC)
|
case MULTIBOOT_MAGIC:
|
||||||
return true;
|
case MULTIBOOT2_MAGIC:
|
||||||
return false;
|
case BANAN_BOOTLOADER_MAGIC:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void parse_boot_info(uint32_t magic, uint32_t info)
|
void parse_boot_info(uint32_t magic, uint32_t info)
|
||||||
{
|
{
|
||||||
switch (magic)
|
switch (magic)
|
||||||
{
|
{
|
||||||
|
case MULTIBOOT_MAGIC:
|
||||||
|
return parse_boot_info_multiboot(info);
|
||||||
case MULTIBOOT2_MAGIC:
|
case MULTIBOOT2_MAGIC:
|
||||||
return parse_boot_info_multiboot2(info);
|
return parse_boot_info_multiboot2(info);
|
||||||
case BANAN_BOOTLOADER_MAGIC:
|
case BANAN_BOOTLOADER_MAGIC:
|
||||||
|
@ -172,6 +243,8 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
switch (magic)
|
switch (magic)
|
||||||
{
|
{
|
||||||
|
case MULTIBOOT_MAGIC:
|
||||||
|
return get_early_boot_command_line_multiboot(info);
|
||||||
case MULTIBOOT2_MAGIC:
|
case MULTIBOOT2_MAGIC:
|
||||||
return get_early_boot_command_line_multiboot2(info);
|
return get_early_boot_command_line_multiboot2(info);
|
||||||
case BANAN_BOOTLOADER_MAGIC:
|
case BANAN_BOOTLOADER_MAGIC:
|
||||||
|
|
|
@ -241,9 +241,9 @@ namespace Kernel
|
||||||
class FramebufferMemoryRegion : public MemoryRegion
|
class FramebufferMemoryRegion : public MemoryRegion
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static BAN::ErrorOr<BAN::UniqPtr<FramebufferMemoryRegion>> create(PageTable& page_table, size_t size, AddressRange address_range, MemoryRegion::Type region_type, PageTable::flags_t page_flags, BAN::RefPtr<FramebufferDevice> framebuffer)
|
static BAN::ErrorOr<BAN::UniqPtr<FramebufferMemoryRegion>> create(PageTable& page_table, size_t size, AddressRange address_range, MemoryRegion::Type region_type, PageTable::flags_t page_flags, int status_flags, BAN::RefPtr<FramebufferDevice> framebuffer)
|
||||||
{
|
{
|
||||||
auto* region_ptr = new FramebufferMemoryRegion(page_table, size, region_type, page_flags, framebuffer);
|
auto* region_ptr = new FramebufferMemoryRegion(page_table, size, region_type, page_flags, status_flags, framebuffer);
|
||||||
if (region_ptr == nullptr)
|
if (region_ptr == nullptr)
|
||||||
return BAN::Error::from_errno(ENOMEM);
|
return BAN::Error::from_errno(ENOMEM);
|
||||||
auto region = BAN::UniqPtr<FramebufferMemoryRegion>::adopt(region_ptr);
|
auto region = BAN::UniqPtr<FramebufferMemoryRegion>::adopt(region_ptr);
|
||||||
|
@ -258,7 +258,7 @@ namespace Kernel
|
||||||
m_framebuffer->sync_pixels_full();
|
m_framebuffer->sync_pixels_full();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual BAN::ErrorOr<void> msync(vaddr_t vaddr, size_t size, int flags) override
|
BAN::ErrorOr<void> msync(vaddr_t vaddr, size_t size, int flags) override
|
||||||
{
|
{
|
||||||
if (flags != MS_SYNC)
|
if (flags != MS_SYNC)
|
||||||
return BAN::Error::from_errno(ENOTSUP);
|
return BAN::Error::from_errno(ENOTSUP);
|
||||||
|
@ -281,9 +281,9 @@ namespace Kernel
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) override
|
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) override
|
||||||
{
|
{
|
||||||
auto* region_ptr = new FramebufferMemoryRegion(new_page_table, m_size, m_type, m_flags, m_framebuffer);
|
auto* region_ptr = new FramebufferMemoryRegion(new_page_table, m_size, m_type, m_flags, m_status_flags, m_framebuffer);
|
||||||
if (region_ptr == nullptr)
|
if (region_ptr == nullptr)
|
||||||
return BAN::Error::from_errno(ENOMEM);
|
return BAN::Error::from_errno(ENOMEM);
|
||||||
auto region = BAN::UniqPtr<FramebufferMemoryRegion>::adopt(region_ptr);
|
auto region = BAN::UniqPtr<FramebufferMemoryRegion>::adopt(region_ptr);
|
||||||
|
@ -297,7 +297,7 @@ namespace Kernel
|
||||||
// Returns error if no memory was available
|
// Returns error if no memory was available
|
||||||
// Returns true if page was succesfully allocated
|
// Returns true if page was succesfully allocated
|
||||||
// Returns false if page was already allocated
|
// Returns false if page was already allocated
|
||||||
virtual BAN::ErrorOr<bool> allocate_page_containing_impl(vaddr_t vaddr, bool wants_write) override
|
BAN::ErrorOr<bool> allocate_page_containing_impl(vaddr_t vaddr, bool wants_write) override
|
||||||
{
|
{
|
||||||
(void)wants_write;
|
(void)wants_write;
|
||||||
|
|
||||||
|
@ -312,8 +312,8 @@ namespace Kernel
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FramebufferMemoryRegion(PageTable& page_table, size_t size, MemoryRegion::Type region_type, PageTable::flags_t page_flags, BAN::RefPtr<FramebufferDevice> framebuffer)
|
FramebufferMemoryRegion(PageTable& page_table, size_t size, MemoryRegion::Type region_type, PageTable::flags_t page_flags, int status_flags, BAN::RefPtr<FramebufferDevice> framebuffer)
|
||||||
: MemoryRegion(page_table, size, region_type, page_flags)
|
: MemoryRegion(page_table, size, region_type, page_flags, status_flags)
|
||||||
, m_framebuffer(framebuffer)
|
, m_framebuffer(framebuffer)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
@ -370,7 +370,7 @@ namespace Kernel
|
||||||
BAN::RefPtr<FramebufferDevice> m_framebuffer;
|
BAN::RefPtr<FramebufferDevice> m_framebuffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> FramebufferDevice::mmap_region(PageTable& page_table, off_t offset, size_t len, AddressRange address_range, MemoryRegion::Type region_type, PageTable::flags_t page_flags)
|
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> FramebufferDevice::mmap_region(PageTable& page_table, off_t offset, size_t len, AddressRange address_range, MemoryRegion::Type region_type, PageTable::flags_t page_flags, int status_flags)
|
||||||
{
|
{
|
||||||
if (offset != 0)
|
if (offset != 0)
|
||||||
return BAN::Error::from_errno(EINVAL);
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
@ -379,7 +379,7 @@ namespace Kernel
|
||||||
if (region_type != MemoryRegion::Type::SHARED)
|
if (region_type != MemoryRegion::Type::SHARED)
|
||||||
return BAN::Error::from_errno(EINVAL);
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
|
||||||
auto region = TRY(FramebufferMemoryRegion::create(page_table, len, address_range, region_type, page_flags, this));
|
auto region = TRY(FramebufferMemoryRegion::create(page_table, len, address_range, region_type, page_flags, status_flags, this));
|
||||||
return BAN::UniqPtr<MemoryRegion>(BAN::move(region));
|
return BAN::UniqPtr<MemoryRegion>(BAN::move(region));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -212,7 +212,7 @@ namespace Kernel::ELF
|
||||||
file_backed_size,
|
file_backed_size,
|
||||||
{ .start = pheader_base, .end = pheader_base + file_backed_size },
|
{ .start = pheader_base, .end = pheader_base + file_backed_size },
|
||||||
MemoryRegion::Type::PRIVATE,
|
MemoryRegion::Type::PRIVATE,
|
||||||
flags
|
flags, O_EXEC | O_RDWR
|
||||||
));
|
));
|
||||||
TRY(memory_regions.emplace_back(BAN::move(region)));
|
TRY(memory_regions.emplace_back(BAN::move(region)));
|
||||||
}
|
}
|
||||||
|
@ -226,7 +226,7 @@ namespace Kernel::ELF
|
||||||
(pheader_base + program_header.p_memsz) - (aligned_vaddr + file_backed_size),
|
(pheader_base + program_header.p_memsz) - (aligned_vaddr + file_backed_size),
|
||||||
{ .start = aligned_vaddr + file_backed_size, .end = pheader_base + program_header.p_memsz },
|
{ .start = aligned_vaddr + file_backed_size, .end = pheader_base + program_header.p_memsz },
|
||||||
MemoryRegion::Type::PRIVATE,
|
MemoryRegion::Type::PRIVATE,
|
||||||
flags
|
flags, O_EXEC | O_RDWR
|
||||||
));
|
));
|
||||||
|
|
||||||
if (file_backed_size < program_header.p_filesz)
|
if (file_backed_size < program_header.p_filesz)
|
||||||
|
@ -267,7 +267,8 @@ namespace Kernel::ELF
|
||||||
offset + region_size,
|
offset + region_size,
|
||||||
{ .start = last_loaded_address, .end = USERSPACE_END },
|
{ .start = last_loaded_address, .end = USERSPACE_END },
|
||||||
MemoryRegion::Type::PRIVATE,
|
MemoryRegion::Type::PRIVATE,
|
||||||
PageTable::Flags::UserSupervisor | PageTable::Flags::Present
|
PageTable::Flags::UserSupervisor | PageTable::Flags::Present,
|
||||||
|
O_EXEC | O_RDWR
|
||||||
));
|
));
|
||||||
|
|
||||||
for (vaddr_t vaddr = region->vaddr(); vaddr < region->vaddr() + offset + region->size(); vaddr += PAGE_SIZE)
|
for (vaddr_t vaddr = region->vaddr(); vaddr < region->vaddr() + offset + region->size(); vaddr += PAGE_SIZE)
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include <kernel/BootInfo.h>
|
||||||
#include <kernel/FS/ProcFS/FileSystem.h>
|
#include <kernel/FS/ProcFS/FileSystem.h>
|
||||||
#include <kernel/FS/ProcFS/Inode.h>
|
#include <kernel/FS/ProcFS/Inode.h>
|
||||||
|
|
||||||
|
@ -33,6 +34,10 @@ namespace Kernel
|
||||||
*s_instance, 0444, 0, 0
|
*s_instance, 0444, 0, 0
|
||||||
));
|
));
|
||||||
MUST(static_cast<TmpDirectoryInode*>(s_instance->root_inode().ptr())->link_inode(*meminfo_inode, "meminfo"_sv));
|
MUST(static_cast<TmpDirectoryInode*>(s_instance->root_inode().ptr())->link_inode(*meminfo_inode, "meminfo"_sv));
|
||||||
|
|
||||||
|
auto cmdline_inode = MUST(TmpFileInode::create_new(*s_instance, 0444, 0, 0));
|
||||||
|
MUST(cmdline_inode->write(0, { reinterpret_cast<const uint8_t*>(g_boot_info.command_line.data()), g_boot_info.command_line.size() }));
|
||||||
|
MUST(static_cast<TmpDirectoryInode*>(s_instance->root_inode().ptr())->link_inode(*cmdline_inode, "cmdline"_sv));
|
||||||
}
|
}
|
||||||
|
|
||||||
ProcFileSystem& ProcFileSystem::get()
|
ProcFileSystem& ProcFileSystem::get()
|
||||||
|
|
|
@ -109,7 +109,8 @@ namespace Kernel
|
||||||
|
|
||||||
if (file_type == DIRTYPE)
|
if (file_type == DIRTYPE)
|
||||||
{
|
{
|
||||||
TRY(parent_inode->create_directory(file_name_sv, file_mode, file_uid, file_gid));
|
if (auto ret = parent_inode->create_directory(file_name_sv, file_mode, file_uid, file_gid); ret.is_error())
|
||||||
|
dwarnln("failed to create directory '{}': {}", file_name_sv, ret.error());
|
||||||
}
|
}
|
||||||
else if (file_type == LNKTYPE)
|
else if (file_type == LNKTYPE)
|
||||||
{
|
{
|
||||||
|
@ -117,40 +118,46 @@ namespace Kernel
|
||||||
}
|
}
|
||||||
else if (file_type == SYMTYPE)
|
else if (file_type == SYMTYPE)
|
||||||
{
|
{
|
||||||
TRY(parent_inode->create_file(file_name_sv, file_mode, file_uid, file_gid));
|
if (auto ret = parent_inode->create_file(file_name_sv, file_mode, file_uid, file_gid); ret.is_error())
|
||||||
|
dwarnln("failed to create symlink '{}': {}", file_name_sv, ret.error());
|
||||||
char link_target[101] {};
|
else
|
||||||
const paddr_t paddr = module.start + offset;
|
|
||||||
PageTable::with_fast_page(paddr & PAGE_ADDR_MASK, [&] {
|
|
||||||
memcpy(link_target, PageTable::fast_page_as_ptr((paddr % PAGE_SIZE) + 157), 100);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (link_target[0])
|
|
||||||
{
|
{
|
||||||
auto inode = TRY(parent_inode->find_inode(file_name_sv));
|
char link_target[101] {};
|
||||||
TRY(inode->set_link_target(link_target));
|
const paddr_t paddr = module.start + offset;
|
||||||
|
PageTable::with_fast_page(paddr & PAGE_ADDR_MASK, [&] {
|
||||||
|
memcpy(link_target, PageTable::fast_page_as_ptr((paddr % PAGE_SIZE) + 157), 100);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (link_target[0])
|
||||||
|
{
|
||||||
|
auto inode = TRY(parent_inode->find_inode(file_name_sv));
|
||||||
|
TRY(inode->set_link_target(link_target));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TRY(parent_inode->create_file(file_name_sv, file_mode, file_uid, file_gid));
|
if (auto ret = parent_inode->create_file(file_name_sv, file_mode, file_uid, file_gid); ret.is_error())
|
||||||
|
dwarnln("failed to create file '{}': {}", file_name_sv, ret.error());
|
||||||
if (file_size)
|
else
|
||||||
{
|
{
|
||||||
auto inode = TRY(parent_inode->find_inode(file_name_sv));
|
if (file_size)
|
||||||
|
|
||||||
size_t nwritten = 0;
|
|
||||||
while (nwritten < file_size)
|
|
||||||
{
|
{
|
||||||
const paddr_t paddr = module.start + offset + 512 + nwritten;
|
auto inode = TRY(parent_inode->find_inode(file_name_sv));
|
||||||
PageTable::with_fast_page(paddr & PAGE_ADDR_MASK, [&] {
|
|
||||||
memcpy(temp_page, PageTable::fast_page_as_ptr(), PAGE_SIZE);
|
|
||||||
});
|
|
||||||
|
|
||||||
const size_t page_off = paddr % PAGE_SIZE;
|
size_t nwritten = 0;
|
||||||
const size_t to_write = BAN::Math::min(file_size - nwritten, PAGE_SIZE - page_off);
|
while (nwritten < file_size)
|
||||||
TRY(inode->write(nwritten, { temp_page + page_off, to_write }));
|
{
|
||||||
nwritten += to_write;
|
const paddr_t paddr = module.start + offset + 512 + nwritten;
|
||||||
|
PageTable::with_fast_page(paddr & PAGE_ADDR_MASK, [&] {
|
||||||
|
memcpy(temp_page, PageTable::fast_page_as_ptr(), PAGE_SIZE);
|
||||||
|
});
|
||||||
|
|
||||||
|
const size_t page_off = paddr % PAGE_SIZE;
|
||||||
|
const size_t to_write = BAN::Math::min(file_size - nwritten, PAGE_SIZE - page_off);
|
||||||
|
TRY(inode->write(nwritten, { temp_page + page_off, to_write }));
|
||||||
|
nwritten += to_write;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -188,6 +188,26 @@ namespace Kernel
|
||||||
|
|
||||||
if (isr == ISR::PageFault && Thread::current().is_userspace())
|
if (isr == ISR::PageFault && Thread::current().is_userspace())
|
||||||
{
|
{
|
||||||
|
if (pid)
|
||||||
|
{
|
||||||
|
PageFaultError page_fault_error;
|
||||||
|
page_fault_error.raw = error;
|
||||||
|
|
||||||
|
Processor::set_interrupt_state(InterruptState::Enabled);
|
||||||
|
auto result = Process::current().allocate_page_for_demand_paging(regs->cr2, page_fault_error.write, page_fault_error.instruction);
|
||||||
|
Processor::set_interrupt_state(InterruptState::Disabled);
|
||||||
|
|
||||||
|
if (!result.is_error() && result.value())
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
if (result.is_error())
|
||||||
|
{
|
||||||
|
dwarnln("Demand paging: {}", result.error());
|
||||||
|
Thread::current().handle_signal(SIGKILL);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Check if stack is OOB
|
// Check if stack is OOB
|
||||||
if (ARCH(i686) && !GDT::is_user_segment(interrupt_stack->cs))
|
if (ARCH(i686) && !GDT::is_user_segment(interrupt_stack->cs))
|
||||||
; // 32 bit does not push stack pointer when no CPL change happens
|
; // 32 bit does not push stack pointer when no CPL change happens
|
||||||
|
@ -207,26 +227,6 @@ namespace Kernel
|
||||||
Thread::current().handle_signal(SIGKILL);
|
Thread::current().handle_signal(SIGKILL);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pid)
|
|
||||||
{
|
|
||||||
PageFaultError page_fault_error;
|
|
||||||
page_fault_error.raw = error;
|
|
||||||
|
|
||||||
Processor::set_interrupt_state(InterruptState::Enabled);
|
|
||||||
auto result = Process::current().allocate_page_for_demand_paging(regs->cr2, page_fault_error.write);
|
|
||||||
Processor::set_interrupt_state(InterruptState::Disabled);
|
|
||||||
|
|
||||||
if (!result.is_error() && result.value())
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
if (result.is_error())
|
|
||||||
{
|
|
||||||
dwarnln("Demand paging: {}", result.error());
|
|
||||||
Thread::current().handle_signal(SIGKILL);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -338,6 +338,7 @@ namespace Kernel
|
||||||
ASSERT(InterruptController::get().is_in_service(IRQ_IPI - IRQ_VECTOR_BASE));
|
ASSERT(InterruptController::get().is_in_service(IRQ_IPI - IRQ_VECTOR_BASE));
|
||||||
InterruptController::get().eoi(IRQ_IPI - IRQ_VECTOR_BASE);
|
InterruptController::get().eoi(IRQ_IPI - IRQ_VECTOR_BASE);
|
||||||
Processor::handle_ipi();
|
Processor::handle_ipi();
|
||||||
|
Processor::scheduler().reschedule_if_idle();
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void cpp_timer_handler()
|
extern "C" void cpp_timer_handler()
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::UniqPtr<FileBackedRegion>> FileBackedRegion::create(BAN::RefPtr<Inode> inode, PageTable& page_table, off_t offset, size_t size, AddressRange address_range, Type type, PageTable::flags_t flags)
|
BAN::ErrorOr<BAN::UniqPtr<FileBackedRegion>> FileBackedRegion::create(BAN::RefPtr<Inode> inode, PageTable& page_table, off_t offset, size_t size, AddressRange address_range, Type type, PageTable::flags_t flags, int status_flags)
|
||||||
{
|
{
|
||||||
ASSERT(inode->mode().ifreg());
|
ASSERT(inode->mode().ifreg());
|
||||||
|
|
||||||
|
@ -16,14 +16,14 @@ namespace Kernel
|
||||||
if ((size > (size_t)inode->size() || (size_t)offset > (size_t)inode->size() - size))
|
if ((size > (size_t)inode->size() || (size_t)offset > (size_t)inode->size() - size))
|
||||||
return BAN::Error::from_errno(EOVERFLOW);
|
return BAN::Error::from_errno(EOVERFLOW);
|
||||||
|
|
||||||
auto* region_ptr = new FileBackedRegion(inode, page_table, offset, size, type, flags);
|
auto* region_ptr = new FileBackedRegion(inode, page_table, offset, size, type, flags, status_flags);
|
||||||
if (region_ptr == nullptr)
|
if (region_ptr == nullptr)
|
||||||
return BAN::Error::from_errno(ENOMEM);
|
return BAN::Error::from_errno(ENOMEM);
|
||||||
auto region = BAN::UniqPtr<FileBackedRegion>::adopt(region_ptr);
|
auto region = BAN::UniqPtr<FileBackedRegion>::adopt(region_ptr);
|
||||||
|
|
||||||
TRY(region->initialize(address_range));
|
TRY(region->initialize(address_range));
|
||||||
|
|
||||||
if (type == Type::PRIVATE && (flags & PageTable::Flags::ReadWrite))
|
if (type == Type::PRIVATE)
|
||||||
TRY(region->m_dirty_pages.resize(BAN::Math::div_round_up<size_t>(size, PAGE_SIZE)));
|
TRY(region->m_dirty_pages.resize(BAN::Math::div_round_up<size_t>(size, PAGE_SIZE)));
|
||||||
|
|
||||||
LockGuard _(inode->m_mutex);
|
LockGuard _(inode->m_mutex);
|
||||||
|
@ -39,8 +39,8 @@ namespace Kernel
|
||||||
return region;
|
return region;
|
||||||
}
|
}
|
||||||
|
|
||||||
FileBackedRegion::FileBackedRegion(BAN::RefPtr<Inode> inode, PageTable& page_table, off_t offset, ssize_t size, Type type, PageTable::flags_t flags)
|
FileBackedRegion::FileBackedRegion(BAN::RefPtr<Inode> inode, PageTable& page_table, off_t offset, ssize_t size, Type type, PageTable::flags_t flags, int status_flags)
|
||||||
: MemoryRegion(page_table, size, type, flags)
|
: MemoryRegion(page_table, size, type, flags, status_flags)
|
||||||
, m_inode(inode)
|
, m_inode(inode)
|
||||||
, m_offset(offset)
|
, m_offset(offset)
|
||||||
{
|
{
|
||||||
|
@ -200,7 +200,7 @@ namespace Kernel
|
||||||
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> FileBackedRegion::clone(PageTable& page_table)
|
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> FileBackedRegion::clone(PageTable& page_table)
|
||||||
{
|
{
|
||||||
const size_t aligned_size = (m_size + PAGE_SIZE - 1) & PAGE_ADDR_MASK;
|
const size_t aligned_size = (m_size + PAGE_SIZE - 1) & PAGE_ADDR_MASK;
|
||||||
auto result = TRY(FileBackedRegion::create(m_inode, page_table, m_offset, m_size, { .start = m_vaddr, .end = m_vaddr + aligned_size }, m_type, m_flags));
|
auto result = TRY(FileBackedRegion::create(m_inode, page_table, m_offset, m_size, { .start = m_vaddr, .end = m_vaddr + aligned_size }, m_type, m_flags, m_status_flags));
|
||||||
|
|
||||||
// non-dirty pages can go through demand paging
|
// non-dirty pages can go through demand paging
|
||||||
|
|
||||||
|
|
|
@ -4,12 +4,12 @@
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::UniqPtr<MemoryBackedRegion>> MemoryBackedRegion::create(PageTable& page_table, size_t size, AddressRange address_range, Type type, PageTable::flags_t flags)
|
BAN::ErrorOr<BAN::UniqPtr<MemoryBackedRegion>> MemoryBackedRegion::create(PageTable& page_table, size_t size, AddressRange address_range, Type type, PageTable::flags_t flags, int status_flags)
|
||||||
{
|
{
|
||||||
if (type != Type::PRIVATE)
|
if (type != Type::PRIVATE)
|
||||||
return BAN::Error::from_errno(ENOTSUP);
|
return BAN::Error::from_errno(ENOTSUP);
|
||||||
|
|
||||||
auto* region_ptr = new MemoryBackedRegion(page_table, size, type, flags);
|
auto* region_ptr = new MemoryBackedRegion(page_table, size, type, flags, status_flags);
|
||||||
if (region_ptr == nullptr)
|
if (region_ptr == nullptr)
|
||||||
return BAN::Error::from_errno(ENOMEM);
|
return BAN::Error::from_errno(ENOMEM);
|
||||||
auto region = BAN::UniqPtr<MemoryBackedRegion>::adopt(region_ptr);
|
auto region = BAN::UniqPtr<MemoryBackedRegion>::adopt(region_ptr);
|
||||||
|
@ -19,8 +19,8 @@ namespace Kernel
|
||||||
return region;
|
return region;
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryBackedRegion::MemoryBackedRegion(PageTable& page_table, size_t size, Type type, PageTable::flags_t flags)
|
MemoryBackedRegion::MemoryBackedRegion(PageTable& page_table, size_t size, Type type, PageTable::flags_t flags, int status_flags)
|
||||||
: MemoryRegion(page_table, size, type, flags)
|
: MemoryRegion(page_table, size, type, flags, status_flags)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ namespace Kernel
|
||||||
ASSERT(&PageTable::current() == &m_page_table);
|
ASSERT(&PageTable::current() == &m_page_table);
|
||||||
|
|
||||||
const size_t aligned_size = (m_size + PAGE_SIZE - 1) & PAGE_ADDR_MASK;
|
const size_t aligned_size = (m_size + PAGE_SIZE - 1) & PAGE_ADDR_MASK;
|
||||||
auto result = TRY(MemoryBackedRegion::create(new_page_table, m_size, { .start = m_vaddr, .end = m_vaddr + aligned_size }, m_type, m_flags));
|
auto result = TRY(MemoryBackedRegion::create(new_page_table, m_size, { .start = m_vaddr, .end = m_vaddr + aligned_size }, m_type, m_flags, m_status_flags));
|
||||||
|
|
||||||
for (size_t offset = 0; offset < m_size; offset += PAGE_SIZE)
|
for (size_t offset = 0; offset < m_size; offset += PAGE_SIZE)
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,11 +4,12 @@
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
MemoryRegion::MemoryRegion(PageTable& page_table, size_t size, Type type, PageTable::flags_t flags)
|
MemoryRegion::MemoryRegion(PageTable& page_table, size_t size, Type type, PageTable::flags_t flags, int status_flags)
|
||||||
: m_page_table(page_table)
|
: m_page_table(page_table)
|
||||||
, m_size(size)
|
, m_size(size)
|
||||||
, m_type(type)
|
, m_type(type)
|
||||||
, m_flags(flags)
|
, m_flags(flags)
|
||||||
|
, m_status_flags(status_flags)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,6 +50,25 @@ namespace Kernel
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<void> MemoryRegion::mprotect(PageTable::flags_t new_page_flags)
|
||||||
|
{
|
||||||
|
if (m_flags == new_page_flags)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
const size_t page_count = BAN::Math::div_round_up<size_t>(m_size, PAGE_SIZE);
|
||||||
|
for (size_t i = 0; i < page_count; i++)
|
||||||
|
{
|
||||||
|
const vaddr_t vaddr = m_vaddr + i * PAGE_SIZE;
|
||||||
|
const paddr_t paddr = m_page_table.physical_address_of(vaddr);
|
||||||
|
if (paddr == 0)
|
||||||
|
continue;
|
||||||
|
m_page_table.map_page_at(paddr, vaddr, new_page_flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_flags = new_page_flags;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<bool> MemoryRegion::allocate_page_containing(vaddr_t address, bool wants_write)
|
BAN::ErrorOr<bool> MemoryRegion::allocate_page_containing(vaddr_t address, bool wants_write)
|
||||||
{
|
{
|
||||||
ASSERT(contains(address));
|
ASSERT(contains(address));
|
||||||
|
|
|
@ -99,7 +99,7 @@ namespace Kernel
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const size_t page_count = size() / PAGE_SIZE;
|
const size_t page_count = size() / PAGE_SIZE;
|
||||||
for (size_t i = m_has_guard_pages; i < page_count; i++)
|
for (size_t i = 0; i < page_count; i++)
|
||||||
{
|
{
|
||||||
PageTable::with_fast_page(m_paddrs[i], [&] {
|
PageTable::with_fast_page(m_paddrs[i], [&] {
|
||||||
memset(PageTable::fast_page_as_ptr(), 0, PAGE_SIZE);
|
memset(PageTable::fast_page_as_ptr(), 0, PAGE_SIZE);
|
||||||
|
@ -120,7 +120,7 @@ namespace Kernel
|
||||||
auto result = TRY(create_to_vaddr(page_table, vaddr(), size(), m_flags, m_preallocated, m_has_guard_pages));
|
auto result = TRY(create_to_vaddr(page_table, vaddr(), size(), m_flags, m_preallocated, m_has_guard_pages));
|
||||||
|
|
||||||
const size_t page_count = size() / PAGE_SIZE;
|
const size_t page_count = size() / PAGE_SIZE;
|
||||||
for (size_t i = m_has_guard_pages; i < page_count; i++)
|
for (size_t i = 0; i < page_count; i++)
|
||||||
{
|
{
|
||||||
if (m_paddrs[i] == 0)
|
if (m_paddrs[i] == 0)
|
||||||
continue;
|
continue;
|
||||||
|
@ -140,15 +140,17 @@ namespace Kernel
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<void> VirtualRange::allocate_page_for_demand_paging(vaddr_t vaddr)
|
BAN::ErrorOr<bool> VirtualRange::allocate_page_for_demand_paging(vaddr_t vaddr)
|
||||||
{
|
{
|
||||||
ASSERT(!m_preallocated);
|
|
||||||
ASSERT(vaddr % PAGE_SIZE == 0);
|
|
||||||
ASSERT(contains(vaddr));
|
ASSERT(contains(vaddr));
|
||||||
ASSERT(&PageTable::current() == &m_page_table);
|
ASSERT(&PageTable::current() == &m_page_table);
|
||||||
|
|
||||||
|
if (m_preallocated)
|
||||||
|
return false;
|
||||||
|
|
||||||
const size_t index = (vaddr - this->vaddr()) / PAGE_SIZE;
|
const size_t index = (vaddr - this->vaddr()) / PAGE_SIZE;
|
||||||
ASSERT(m_paddrs[index] == 0);
|
if (m_paddrs[index])
|
||||||
|
return false;
|
||||||
|
|
||||||
SpinLockGuard _(m_lock);
|
SpinLockGuard _(m_lock);
|
||||||
|
|
||||||
|
@ -159,7 +161,7 @@ namespace Kernel
|
||||||
m_page_table.map_page_at(m_paddrs[index], vaddr, m_flags);
|
m_page_table.map_page_at(m_paddrs[index], vaddr, m_flags);
|
||||||
memset(reinterpret_cast<void*>(vaddr), 0, PAGE_SIZE);
|
memset(reinterpret_cast<void*>(vaddr), 0, PAGE_SIZE);
|
||||||
|
|
||||||
return {};
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,17 +29,16 @@ namespace Kernel
|
||||||
, m_type(type)
|
, m_type(type)
|
||||||
, m_rdev(get_rdev(type))
|
, m_rdev(get_rdev(type))
|
||||||
{
|
{
|
||||||
ASSERT(minor(m_rdev) < 10);
|
|
||||||
|
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case Type::Ethernet:
|
case Type::Ethernet:
|
||||||
|
ASSERT(minor(m_rdev) < 10);
|
||||||
strcpy(m_name, "ethx");
|
strcpy(m_name, "ethx");
|
||||||
m_name[3] = minor(m_rdev) + '0';
|
m_name[3] = minor(m_rdev) + '0';
|
||||||
break;
|
break;
|
||||||
case Type::Loopback:
|
case Type::Loopback:
|
||||||
strcpy(m_name, "lox");
|
ASSERT(minor(m_rdev) == 0);
|
||||||
m_name[2] = minor(m_rdev) + '0';
|
strcpy(m_name, "lo");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -429,6 +429,8 @@ namespace Kernel
|
||||||
size_t nread;
|
size_t nread;
|
||||||
{
|
{
|
||||||
LockGuard _(inode->m_mutex);
|
LockGuard _(inode->m_mutex);
|
||||||
|
if (!inode->can_read() && inode->has_hungup())
|
||||||
|
return 0;
|
||||||
if (is_nonblock && !inode->can_read())
|
if (is_nonblock && !inode->can_read())
|
||||||
return BAN::Error::from_errno(EAGAIN);
|
return BAN::Error::from_errno(EAGAIN);
|
||||||
nread = TRY(inode->read(offset, buffer));
|
nread = TRY(inode->read(offset, buffer));
|
||||||
|
@ -464,6 +466,11 @@ namespace Kernel
|
||||||
size_t nwrite;
|
size_t nwrite;
|
||||||
{
|
{
|
||||||
LockGuard _(inode->m_mutex);
|
LockGuard _(inode->m_mutex);
|
||||||
|
if (inode->has_error())
|
||||||
|
{
|
||||||
|
Thread::current().add_signal(SIGPIPE);
|
||||||
|
return BAN::Error::from_errno(EPIPE);
|
||||||
|
}
|
||||||
if (is_nonblock && !inode->can_write())
|
if (is_nonblock && !inode->can_write())
|
||||||
return BAN::Error::from_errno(EAGAIN);
|
return BAN::Error::from_errno(EAGAIN);
|
||||||
nwrite = TRY(inode->write(offset, buffer));
|
nwrite = TRY(inode->write(offset, buffer));
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <sys/banan-os.h>
|
#include <sys/banan-os.h>
|
||||||
|
#include <sys/futex.h>
|
||||||
#include <sys/sysmacros.h>
|
#include <sys/sysmacros.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
@ -317,7 +318,8 @@ namespace Kernel
|
||||||
tls_size,
|
tls_size,
|
||||||
{ .start = master_addr, .end = USERSPACE_END },
|
{ .start = master_addr, .end = USERSPACE_END },
|
||||||
MemoryRegion::Type::PRIVATE,
|
MemoryRegion::Type::PRIVATE,
|
||||||
PageTable::Flags::UserSupervisor | PageTable::Flags::ReadWrite | PageTable::Flags::Present
|
PageTable::Flags::UserSupervisor | PageTable::Flags::ReadWrite | PageTable::Flags::Present,
|
||||||
|
O_EXEC | O_RDWR
|
||||||
));
|
));
|
||||||
|
|
||||||
BAN::Vector<uint8_t> temp_buffer;
|
BAN::Vector<uint8_t> temp_buffer;
|
||||||
|
@ -981,24 +983,32 @@ namespace Kernel
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<bool> Process::allocate_page_for_demand_paging(vaddr_t address, bool wants_write)
|
BAN::ErrorOr<bool> Process::allocate_page_for_demand_paging(vaddr_t address, bool wants_write, bool wants_exec)
|
||||||
{
|
{
|
||||||
ASSERT(&Process::current() == this);
|
ASSERT(&Process::current() == this);
|
||||||
|
|
||||||
LockGuard _(m_process_lock);
|
LockGuard _(m_process_lock);
|
||||||
|
|
||||||
if (Thread::current().userspace_stack().contains(address))
|
|
||||||
{
|
{
|
||||||
TRY(Thread::current().userspace_stack().allocate_page_for_demand_paging(address));
|
// NOTE: page can be already allocated by another thread!
|
||||||
return true;
|
|
||||||
|
PageTable::flags_t wanted_flags = PageTable::Flags::UserSupervisor | PageTable::Flags::Present;
|
||||||
|
if (wants_write)
|
||||||
|
wanted_flags |= PageTable::Flags::ReadWrite;
|
||||||
|
if (wants_exec)
|
||||||
|
wanted_flags |= PageTable::Flags::Execute;
|
||||||
|
if ((m_page_table->get_page_flags(address & PAGE_ADDR_MASK) & wanted_flags) == wanted_flags)
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Thread::current().userspace_stack().contains(address))
|
||||||
|
return Thread::current().userspace_stack().allocate_page_for_demand_paging(address);
|
||||||
|
|
||||||
for (auto& region : m_mapped_regions)
|
for (auto& region : m_mapped_regions)
|
||||||
{
|
{
|
||||||
if (!region->contains(address))
|
if (!region->contains(address))
|
||||||
continue;
|
continue;
|
||||||
TRY(region->allocate_page_containing(address, wants_write));
|
return region->allocate_page_containing(address, wants_write);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -2011,6 +2021,11 @@ namespace Kernel
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<long> Process::sys_get_nprocessor()
|
||||||
|
{
|
||||||
|
return Processor::count();
|
||||||
|
}
|
||||||
|
|
||||||
[[noreturn]] static void reset_system()
|
[[noreturn]] static void reset_system()
|
||||||
{
|
{
|
||||||
(void)ACPI::ACPI::get().reset();
|
(void)ACPI::ACPI::get().reset();
|
||||||
|
@ -2132,7 +2147,8 @@ namespace Kernel
|
||||||
page_table(),
|
page_table(),
|
||||||
args.len,
|
args.len,
|
||||||
address_range,
|
address_range,
|
||||||
region_type, page_flags
|
region_type, page_flags,
|
||||||
|
O_EXEC | O_RDWR
|
||||||
));
|
));
|
||||||
|
|
||||||
LockGuard _(m_process_lock);
|
LockGuard _(m_process_lock);
|
||||||
|
@ -2159,7 +2175,8 @@ namespace Kernel
|
||||||
page_table(),
|
page_table(),
|
||||||
args.off, args.len,
|
args.off, args.len,
|
||||||
address_range,
|
address_range,
|
||||||
region_type, page_flags
|
region_type, page_flags,
|
||||||
|
status_flags
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
else if (inode->is_device())
|
else if (inode->is_device())
|
||||||
|
@ -2168,7 +2185,8 @@ namespace Kernel
|
||||||
page_table(),
|
page_table(),
|
||||||
args.off, args.len,
|
args.off, args.len,
|
||||||
address_range,
|
address_range,
|
||||||
region_type, page_flags
|
region_type, page_flags,
|
||||||
|
status_flags
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2214,6 +2232,70 @@ namespace Kernel
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<long> Process::sys_mprotect(void* addr, size_t len, int prot)
|
||||||
|
{
|
||||||
|
if (len == 0)
|
||||||
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
|
||||||
|
const vaddr_t vaddr = reinterpret_cast<vaddr_t>(addr);
|
||||||
|
if (vaddr % PAGE_SIZE != 0)
|
||||||
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
|
||||||
|
if (auto rem = len % PAGE_SIZE)
|
||||||
|
len += PAGE_SIZE - rem;
|
||||||
|
|
||||||
|
PageTable::flags_t flags = 0;
|
||||||
|
if (prot & PROT_READ)
|
||||||
|
flags |= PageTable::Flags::Present;
|
||||||
|
if (prot & PROT_WRITE)
|
||||||
|
flags |= PageTable::Flags::ReadWrite | PageTable::Flags::Present;
|
||||||
|
if (prot & PROT_EXEC)
|
||||||
|
flags |= PageTable::Flags::Execute | PageTable::Flags::Execute;
|
||||||
|
|
||||||
|
if (flags == 0)
|
||||||
|
flags = PageTable::Flags::Reserved;
|
||||||
|
else
|
||||||
|
flags |= PageTable::Flags::UserSupervisor;
|
||||||
|
|
||||||
|
LockGuard _(m_process_lock);
|
||||||
|
|
||||||
|
// FIXME: We should protect partial regions.
|
||||||
|
// This is a hack to only protect if the whole mmap region
|
||||||
|
// is contained within [addr, addr + len]
|
||||||
|
for (size_t i = 0; i < m_mapped_regions.size(); i++)
|
||||||
|
{
|
||||||
|
auto& region = m_mapped_regions[i];
|
||||||
|
|
||||||
|
const vaddr_t region_s = region->vaddr();
|
||||||
|
const vaddr_t region_e = region->vaddr() + region->size();
|
||||||
|
if (vaddr <= region_s && region_e <= vaddr + len)
|
||||||
|
{
|
||||||
|
const bool is_shared = (region->type() == MemoryRegion::Type::SHARED);
|
||||||
|
const bool is_writable = (region->status_flags() & O_WRONLY);
|
||||||
|
const bool want_write = (prot & PROT_WRITE);
|
||||||
|
if (is_shared && want_write && !is_writable)
|
||||||
|
return BAN::Error::from_errno(EACCES);
|
||||||
|
|
||||||
|
// FIXME: if the region is pinned writable, this may
|
||||||
|
// cause some problems :D
|
||||||
|
TRY(region->mprotect(flags));
|
||||||
|
}
|
||||||
|
else if (region->overlaps(vaddr, len))
|
||||||
|
{
|
||||||
|
const bool is_shared = (region->type() == MemoryRegion::Type::SHARED);
|
||||||
|
const bool is_writable = (region->status_flags() & O_WRONLY);
|
||||||
|
const bool want_write = (prot & PROT_WRITE);
|
||||||
|
if (is_shared && want_write && !is_writable)
|
||||||
|
return BAN::Error::from_errno(EACCES);
|
||||||
|
|
||||||
|
dwarnln("TODO: partial region mprotect");
|
||||||
|
TRY(region->mprotect(flags | region->flags()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::sys_msync(void* addr, size_t len, int flags)
|
BAN::ErrorOr<long> Process::sys_msync(void* addr, size_t len, int flags)
|
||||||
{
|
{
|
||||||
if (flags != MS_SYNC && flags != MS_ASYNC && flags != MS_INVALIDATE)
|
if (flags != MS_SYNC && flags != MS_ASYNC && flags != MS_INVALIDATE)
|
||||||
|
@ -2270,17 +2352,17 @@ namespace Kernel
|
||||||
return m_mapped_regions.back()->vaddr();
|
return m_mapped_regions.back()->vaddr();
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::sys_ttyname(int fildes, char* storage)
|
BAN::ErrorOr<long> Process::sys_ttyname(int fildes, char* name, size_t namesize)
|
||||||
{
|
{
|
||||||
LockGuard _(m_process_lock);
|
LockGuard _(m_process_lock);
|
||||||
TRY(validate_pointer_access(storage, TTY_NAME_MAX, true));
|
TRY(validate_pointer_access(name, namesize, true));
|
||||||
auto inode = TRY(m_open_file_descriptors.inode_of(fildes));
|
auto inode = TRY(m_open_file_descriptors.inode_of(fildes));
|
||||||
if (!inode->is_tty())
|
if (!inode->is_tty())
|
||||||
return BAN::Error::from_errno(ENOTTY);
|
return BAN::Error::from_errno(ENOTTY);
|
||||||
auto path = TRY(m_open_file_descriptors.path_of(fildes));
|
auto path = TRY(m_open_file_descriptors.path_of(fildes));
|
||||||
ASSERT(path.size() < TTY_NAME_MAX);
|
if (namesize < path.size() + 1)
|
||||||
strncpy(storage, path.data(), path.size());
|
return BAN::Error::from_errno(ERANGE);
|
||||||
storage[path.size()] = '\0';
|
strcpy(name, path.data());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2491,14 +2573,7 @@ namespace Kernel
|
||||||
*oact = m_signal_handlers[signal];
|
*oact = m_signal_handlers[signal];
|
||||||
|
|
||||||
if (act)
|
if (act)
|
||||||
{
|
|
||||||
if (act->sa_flags & ~(SA_RESTART))
|
|
||||||
{
|
|
||||||
dwarnln("TODO: sigaction({}, {H})", signal, act->sa_flags);
|
|
||||||
return BAN::Error::from_errno(ENOTSUP);
|
|
||||||
}
|
|
||||||
m_signal_handlers[signal] = *act;
|
m_signal_handlers[signal] = *act;
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -2544,6 +2619,96 @@ namespace Kernel
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<long> Process::sys_futex(int op, const uint32_t* addr, uint32_t val, const timespec* abstime)
|
||||||
|
{
|
||||||
|
const vaddr_t vaddr = reinterpret_cast<vaddr_t>(addr);
|
||||||
|
if (vaddr % 4)
|
||||||
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
|
||||||
|
const bool is_private = (op & FUTEX_PRIVATE);
|
||||||
|
const bool is_realtime = (op & FUTEX_REALTIME);
|
||||||
|
op &= ~(FUTEX_PRIVATE | FUTEX_REALTIME);
|
||||||
|
|
||||||
|
if (!is_private)
|
||||||
|
{
|
||||||
|
dwarnln("TODO: shared futex");
|
||||||
|
return BAN::Error::from_errno(ENOTSUP);
|
||||||
|
}
|
||||||
|
|
||||||
|
LockGuard _(m_process_lock);
|
||||||
|
|
||||||
|
auto* buffer_region = TRY(validate_and_pin_pointer_access(addr, sizeof(uint32_t), false));
|
||||||
|
BAN::ScopeGuard pin_guard([&] { if (buffer_region) buffer_region->unpin(); });
|
||||||
|
|
||||||
|
const paddr_t paddr = m_page_table->physical_address_of(vaddr & PAGE_ADDR_MASK) | (vaddr & ~PAGE_ADDR_MASK);
|
||||||
|
ASSERT(paddr != 0);
|
||||||
|
|
||||||
|
switch (op)
|
||||||
|
{
|
||||||
|
case FUTEX_WAIT:
|
||||||
|
{
|
||||||
|
if (BAN::atomic_load(*addr) != val)
|
||||||
|
return BAN::Error::from_errno(EAGAIN);
|
||||||
|
|
||||||
|
const uint64_t wake_time_ns =
|
||||||
|
TRY([abstime, is_realtime, this]() -> BAN::ErrorOr<uint64_t>
|
||||||
|
{
|
||||||
|
if (abstime == nullptr)
|
||||||
|
return BAN::numeric_limits<uint64_t>::max();
|
||||||
|
TRY(validate_pointer_access(abstime, sizeof(*abstime), false));
|
||||||
|
const uint64_t abs_ns = abstime->tv_sec * 1'000'000'000 + abstime->tv_nsec;
|
||||||
|
if (!is_realtime)
|
||||||
|
return abs_ns;
|
||||||
|
const auto realtime = SystemTimer::get().real_time();
|
||||||
|
const uint64_t real_ns = realtime.tv_sec * 1'000'000'000 + realtime.tv_nsec;
|
||||||
|
if (abs_ns <= real_ns)
|
||||||
|
return BAN::Error::from_errno(ETIMEDOUT);
|
||||||
|
return SystemTimer::get().ns_since_boot() + (abs_ns - real_ns);
|
||||||
|
}());
|
||||||
|
|
||||||
|
auto it = m_futexes.find(paddr);
|
||||||
|
if (it == m_futexes.end())
|
||||||
|
it = TRY(m_futexes.emplace(paddr, TRY(BAN::UniqPtr<futex_t>::create())));
|
||||||
|
futex_t* const futex = it->value.ptr();
|
||||||
|
|
||||||
|
futex->waiters++;
|
||||||
|
BAN::ScopeGuard _([futex, paddr, this] {
|
||||||
|
if (--futex->waiters == 0)
|
||||||
|
m_futexes.remove(paddr);
|
||||||
|
});
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
TRY(Thread::current().block_or_eintr_or_waketime_ns(futex->blocker, wake_time_ns, true, &m_process_lock));
|
||||||
|
if (BAN::atomic_load(*addr) == val || futex->to_wakeup == 0)
|
||||||
|
continue;
|
||||||
|
futex->to_wakeup--;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case FUTEX_WAKE:
|
||||||
|
{
|
||||||
|
auto it = m_futexes.find(paddr);
|
||||||
|
if (it == m_futexes.end())
|
||||||
|
return 0;
|
||||||
|
futex_t* const futex = it->value.ptr();
|
||||||
|
|
||||||
|
if (BAN::Math::will_addition_overflow(futex->to_wakeup, val))
|
||||||
|
futex->to_wakeup = BAN::numeric_limits<uint32_t>::max();
|
||||||
|
else
|
||||||
|
futex->to_wakeup += val;
|
||||||
|
|
||||||
|
futex->to_wakeup = BAN::Math::min(futex->to_wakeup, futex->waiters);
|
||||||
|
futex->blocker.unblock();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return BAN::Error::from_errno(ENOSYS);
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::sys_yield()
|
BAN::ErrorOr<long> Process::sys_yield()
|
||||||
{
|
{
|
||||||
Processor::yield();
|
Processor::yield();
|
||||||
|
@ -3055,9 +3220,8 @@ namespace Kernel
|
||||||
BAN::ErrorOr<void> Process::validate_pointer_access_check(const void* ptr, size_t size, bool needs_write)
|
BAN::ErrorOr<void> Process::validate_pointer_access_check(const void* ptr, size_t size, bool needs_write)
|
||||||
{
|
{
|
||||||
ASSERT(&Process::current() == this);
|
ASSERT(&Process::current() == this);
|
||||||
auto& thread = Thread::current();
|
|
||||||
|
|
||||||
vaddr_t vaddr = (vaddr_t)ptr;
|
const vaddr_t vaddr = reinterpret_cast<vaddr_t>(ptr);
|
||||||
|
|
||||||
// NOTE: detect overflow
|
// NOTE: detect overflow
|
||||||
if (vaddr + size < vaddr)
|
if (vaddr + size < vaddr)
|
||||||
|
@ -3067,14 +3231,12 @@ namespace Kernel
|
||||||
if (vaddr + size > USERSPACE_END)
|
if (vaddr + size > USERSPACE_END)
|
||||||
goto unauthorized_access;
|
goto unauthorized_access;
|
||||||
|
|
||||||
if (vaddr == 0)
|
for (const auto* thread : m_threads)
|
||||||
return {};
|
if (vaddr >= thread->userspace_stack_bottom() && vaddr + size <= thread->userspace_stack_top())
|
||||||
|
return {};
|
||||||
if (vaddr >= thread.userspace_stack_bottom() && vaddr + size <= thread.userspace_stack_top())
|
|
||||||
return {};
|
|
||||||
|
|
||||||
// FIXME: should we allow cross mapping access?
|
// FIXME: should we allow cross mapping access?
|
||||||
for (auto& mapped_region : m_mapped_regions)
|
for (const auto& mapped_region : m_mapped_regions)
|
||||||
{
|
{
|
||||||
if (!mapped_region->contains_fully(vaddr, size))
|
if (!mapped_region->contains_fully(vaddr, size))
|
||||||
continue;
|
continue;
|
||||||
|
@ -3107,7 +3269,7 @@ unauthorized_access:
|
||||||
const vaddr_t current = page_start + i * PAGE_SIZE;
|
const vaddr_t current = page_start + i * PAGE_SIZE;
|
||||||
if (page_table().get_page_flags(current) & PageTable::Flags::Present)
|
if (page_table().get_page_flags(current) & PageTable::Flags::Present)
|
||||||
continue;
|
continue;
|
||||||
TRY(Process::allocate_page_for_demand_paging(current, needs_write));
|
TRY(Process::allocate_page_for_demand_paging(current, needs_write, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
|
|
|
@ -119,9 +119,15 @@ namespace Kernel
|
||||||
|
|
||||||
thread->m_is_userspace = true;
|
thread->m_is_userspace = true;
|
||||||
|
|
||||||
|
#if ARCH(x86_64)
|
||||||
|
static constexpr vaddr_t stack_addr_start = 0x0000700000000000;
|
||||||
|
#elif ARCH(i686)
|
||||||
|
static constexpr vaddr_t stack_addr_start = 0xB0000000;
|
||||||
|
#endif
|
||||||
|
|
||||||
thread->m_kernel_stack = TRY(VirtualRange::create_to_vaddr_range(
|
thread->m_kernel_stack = TRY(VirtualRange::create_to_vaddr_range(
|
||||||
page_table,
|
page_table,
|
||||||
0x200000, USERSPACE_END,
|
stack_addr_start, USERSPACE_END,
|
||||||
kernel_stack_size,
|
kernel_stack_size,
|
||||||
PageTable::Flags::ReadWrite | PageTable::Flags::Present,
|
PageTable::Flags::ReadWrite | PageTable::Flags::Present,
|
||||||
true, true
|
true, true
|
||||||
|
@ -129,7 +135,7 @@ namespace Kernel
|
||||||
|
|
||||||
thread->m_userspace_stack = TRY(VirtualRange::create_to_vaddr_range(
|
thread->m_userspace_stack = TRY(VirtualRange::create_to_vaddr_range(
|
||||||
page_table,
|
page_table,
|
||||||
0x200000, USERSPACE_END,
|
stack_addr_start, USERSPACE_END,
|
||||||
userspace_stack_size,
|
userspace_stack_size,
|
||||||
PageTable::Flags::UserSupervisor | PageTable::Flags::ReadWrite | PageTable::Flags::Present,
|
PageTable::Flags::UserSupervisor | PageTable::Flags::ReadWrite | PageTable::Flags::Present,
|
||||||
true, true
|
true, true
|
||||||
|
@ -507,9 +513,16 @@ namespace Kernel
|
||||||
bool has_sa_restart;
|
bool has_sa_restart;
|
||||||
{
|
{
|
||||||
SpinLockGuard _(m_process->m_signal_lock);
|
SpinLockGuard _(m_process->m_signal_lock);
|
||||||
ASSERT(!(m_process->m_signal_handlers[signal].sa_flags & SA_SIGINFO));
|
|
||||||
signal_handler = (vaddr_t)m_process->m_signal_handlers[signal].sa_handler;
|
auto& handler = m_process->m_signal_handlers[signal];
|
||||||
has_sa_restart = !!(m_process->m_signal_handlers[signal].sa_flags & SA_RESTART);
|
|
||||||
|
ASSERT(!(handler.sa_flags & SA_SIGINFO));
|
||||||
|
|
||||||
|
signal_handler = reinterpret_cast<vaddr_t>(handler.sa_handler);
|
||||||
|
if (handler.sa_flags & SA_RESETHAND)
|
||||||
|
handler.sa_handler = SIG_DFL;
|
||||||
|
|
||||||
|
has_sa_restart = !!(handler.sa_flags & SA_RESTART);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_signal_pending_mask &= ~(1ull << signal);
|
m_signal_pending_mask &= ~(1ull << signal);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
diff -ruN SDL-release-2.30.11/CMakeLists.txt SDL-release-2.30.11-banan_os/CMakeLists.txt
|
diff -ruN SDL-release-2.30.11/CMakeLists.txt SDL2-2.30.11-banan_os/CMakeLists.txt
|
||||||
--- SDL-release-2.30.11/CMakeLists.txt 2025-01-01 19:09:38.000000000 +0200
|
--- SDL-release-2.30.11/CMakeLists.txt 2025-01-01 19:09:38.000000000 +0200
|
||||||
+++ SDL-release-2.30.11-banan_os/CMakeLists.txt 2025-06-25 16:53:26.163363407 +0300
|
+++ SDL2-2.30.11-banan_os/CMakeLists.txt 2025-08-03 14:04:09.894244781 +0300
|
||||||
@@ -1452,7 +1452,7 @@
|
@@ -1452,7 +1452,7 @@
|
||||||
CheckPTHREAD()
|
CheckPTHREAD()
|
||||||
CheckLibUnwind()
|
CheckLibUnwind()
|
||||||
|
@ -60,9 +60,9 @@ diff -ruN SDL-release-2.30.11/CMakeLists.txt SDL-release-2.30.11-banan_os/CMakeL
|
||||||
elseif(RISCOS)
|
elseif(RISCOS)
|
||||||
if(SDL_MISC)
|
if(SDL_MISC)
|
||||||
file(GLOB MISC_SOURCES ${SDL2_SOURCE_DIR}/src/misc/riscos/*.c)
|
file(GLOB MISC_SOURCES ${SDL2_SOURCE_DIR}/src/misc/riscos/*.c)
|
||||||
diff -ruN SDL-release-2.30.11/include/SDL_config.h.cmake SDL-release-2.30.11-banan_os/include/SDL_config.h.cmake
|
diff -ruN SDL-release-2.30.11/include/SDL_config.h.cmake SDL2-2.30.11-banan_os/include/SDL_config.h.cmake
|
||||||
--- SDL-release-2.30.11/include/SDL_config.h.cmake 2025-01-01 19:09:38.000000000 +0200
|
--- SDL-release-2.30.11/include/SDL_config.h.cmake 2025-01-01 19:09:38.000000000 +0200
|
||||||
+++ SDL-release-2.30.11-banan_os/include/SDL_config.h.cmake 2025-06-24 19:53:27.963249565 +0300
|
+++ SDL2-2.30.11-banan_os/include/SDL_config.h.cmake 2025-08-03 14:04:09.894803585 +0300
|
||||||
@@ -406,6 +406,7 @@
|
@@ -406,6 +406,7 @@
|
||||||
#cmakedefine SDL_VIDEO_DRIVER_ANDROID @SDL_VIDEO_DRIVER_ANDROID@
|
#cmakedefine SDL_VIDEO_DRIVER_ANDROID @SDL_VIDEO_DRIVER_ANDROID@
|
||||||
#cmakedefine SDL_VIDEO_DRIVER_EMSCRIPTEN @SDL_VIDEO_DRIVER_EMSCRIPTEN@
|
#cmakedefine SDL_VIDEO_DRIVER_EMSCRIPTEN @SDL_VIDEO_DRIVER_EMSCRIPTEN@
|
||||||
|
@ -71,9 +71,9 @@ diff -ruN SDL-release-2.30.11/include/SDL_config.h.cmake SDL-release-2.30.11-ban
|
||||||
#cmakedefine SDL_VIDEO_DRIVER_COCOA @SDL_VIDEO_DRIVER_COCOA@
|
#cmakedefine SDL_VIDEO_DRIVER_COCOA @SDL_VIDEO_DRIVER_COCOA@
|
||||||
#cmakedefine SDL_VIDEO_DRIVER_UIKIT @SDL_VIDEO_DRIVER_UIKIT@
|
#cmakedefine SDL_VIDEO_DRIVER_UIKIT @SDL_VIDEO_DRIVER_UIKIT@
|
||||||
#cmakedefine SDL_VIDEO_DRIVER_DIRECTFB @SDL_VIDEO_DRIVER_DIRECTFB@
|
#cmakedefine SDL_VIDEO_DRIVER_DIRECTFB @SDL_VIDEO_DRIVER_DIRECTFB@
|
||||||
diff -ruN SDL-release-2.30.11/include/SDL_platform.h SDL-release-2.30.11-banan_os/include/SDL_platform.h
|
diff -ruN SDL-release-2.30.11/include/SDL_platform.h SDL2-2.30.11-banan_os/include/SDL_platform.h
|
||||||
--- SDL-release-2.30.11/include/SDL_platform.h 2025-01-01 19:09:38.000000000 +0200
|
--- SDL-release-2.30.11/include/SDL_platform.h 2025-01-01 19:09:38.000000000 +0200
|
||||||
+++ SDL-release-2.30.11-banan_os/include/SDL_platform.h 2025-06-24 17:54:20.094530618 +0300
|
+++ SDL2-2.30.11-banan_os/include/SDL_platform.h 2025-08-03 14:04:09.895022748 +0300
|
||||||
@@ -36,6 +36,10 @@
|
@@ -36,6 +36,10 @@
|
||||||
#undef __HAIKU__
|
#undef __HAIKU__
|
||||||
#define __HAIKU__ 1
|
#define __HAIKU__ 1
|
||||||
|
@ -85,9 +85,9 @@ diff -ruN SDL-release-2.30.11/include/SDL_platform.h SDL-release-2.30.11-banan_o
|
||||||
#if defined(bsdi) || defined(__bsdi) || defined(__bsdi__)
|
#if defined(bsdi) || defined(__bsdi) || defined(__bsdi__)
|
||||||
#undef __BSDI__
|
#undef __BSDI__
|
||||||
#define __BSDI__ 1
|
#define __BSDI__ 1
|
||||||
diff -ruN SDL-release-2.30.11/src/misc/banan_os/SDL_sysurl.cpp SDL-release-2.30.11-banan_os/src/misc/banan_os/SDL_sysurl.cpp
|
diff -ruN SDL-release-2.30.11/src/misc/banan_os/SDL_sysurl.cpp SDL2-2.30.11-banan_os/src/misc/banan_os/SDL_sysurl.cpp
|
||||||
--- SDL-release-2.30.11/src/misc/banan_os/SDL_sysurl.cpp 1970-01-01 02:00:00.000000000 +0200
|
--- SDL-release-2.30.11/src/misc/banan_os/SDL_sysurl.cpp 1970-01-01 02:00:00.000000000 +0200
|
||||||
+++ SDL-release-2.30.11-banan_os/src/misc/banan_os/SDL_sysurl.cpp 2025-06-24 18:51:56.695953622 +0300
|
+++ SDL2-2.30.11-banan_os/src/misc/banan_os/SDL_sysurl.cpp 2025-08-03 14:04:09.895198889 +0300
|
||||||
@@ -0,0 +1,30 @@
|
@@ -0,0 +1,30 @@
|
||||||
+/*
|
+/*
|
||||||
+ Simple DirectMedia Layer
|
+ Simple DirectMedia Layer
|
||||||
|
@ -119,9 +119,9 @@ diff -ruN SDL-release-2.30.11/src/misc/banan_os/SDL_sysurl.cpp SDL-release-2.30.
|
||||||
+
|
+
|
||||||
+/* vi: set ts=4 sw=4 expandtab: */
|
+/* vi: set ts=4 sw=4 expandtab: */
|
||||||
+
|
+
|
||||||
diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_message_box.cpp SDL-release-2.30.11-banan_os/src/video/banan_os/SDL_banan_os_message_box.cpp
|
diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_message_box.cpp SDL2-2.30.11-banan_os/src/video/banan_os/SDL_banan_os_message_box.cpp
|
||||||
--- SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_message_box.cpp 1970-01-01 02:00:00.000000000 +0200
|
--- SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_message_box.cpp 1970-01-01 02:00:00.000000000 +0200
|
||||||
+++ SDL-release-2.30.11-banan_os/src/video/banan_os/SDL_banan_os_message_box.cpp 2025-06-27 16:29:59.012277213 +0300
|
+++ SDL2-2.30.11-banan_os/src/video/banan_os/SDL_banan_os_message_box.cpp 2025-08-03 14:04:09.895299391 +0300
|
||||||
@@ -0,0 +1,60 @@
|
@@ -0,0 +1,60 @@
|
||||||
+/*
|
+/*
|
||||||
+ Simple DirectMedia Layer
|
+ Simple DirectMedia Layer
|
||||||
|
@ -183,9 +183,9 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_message_box.cpp SD
|
||||||
+#endif /* SDL_VIDEO_DRIVER_BANAN_OS */
|
+#endif /* SDL_VIDEO_DRIVER_BANAN_OS */
|
||||||
+
|
+
|
||||||
+/* vi: set ts=4 sw=4 expandtab: */
|
+/* vi: set ts=4 sw=4 expandtab: */
|
||||||
diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_message_box.h SDL-release-2.30.11-banan_os/src/video/banan_os/SDL_banan_os_message_box.h
|
diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_message_box.h SDL2-2.30.11-banan_os/src/video/banan_os/SDL_banan_os_message_box.h
|
||||||
--- SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_message_box.h 1970-01-01 02:00:00.000000000 +0200
|
--- SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_message_box.h 1970-01-01 02:00:00.000000000 +0200
|
||||||
+++ SDL-release-2.30.11-banan_os/src/video/banan_os/SDL_banan_os_message_box.h 2025-06-24 19:49:44.390183027 +0300
|
+++ SDL2-2.30.11-banan_os/src/video/banan_os/SDL_banan_os_message_box.h 2025-08-03 14:04:09.895347931 +0300
|
||||||
@@ -0,0 +1,45 @@
|
@@ -0,0 +1,45 @@
|
||||||
+/*
|
+/*
|
||||||
+ Simple DirectMedia Layer
|
+ Simple DirectMedia Layer
|
||||||
|
@ -232,10 +232,10 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_message_box.h SDL-
|
||||||
+#endif
|
+#endif
|
||||||
+
|
+
|
||||||
+/* vi: set ts=4 sw=4 expandtab: */
|
+/* vi: set ts=4 sw=4 expandtab: */
|
||||||
diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL-release-2.30.11-banan_os/src/video/banan_os/SDL_banan_os_video.cpp
|
diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.30.11-banan_os/src/video/banan_os/SDL_banan_os_video.cpp
|
||||||
--- SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp 1970-01-01 02:00:00.000000000 +0200
|
--- SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp 1970-01-01 02:00:00.000000000 +0200
|
||||||
+++ SDL-release-2.30.11-banan_os/src/video/banan_os/SDL_banan_os_video.cpp 2025-06-28 20:49:41.452498550 +0300
|
+++ SDL2-2.30.11-banan_os/src/video/banan_os/SDL_banan_os_video.cpp 2025-08-04 14:57:50.844360579 +0300
|
||||||
@@ -0,0 +1,770 @@
|
@@ -0,0 +1,719 @@
|
||||||
+/*
|
+/*
|
||||||
+ Simple DirectMedia Layer
|
+ Simple DirectMedia Layer
|
||||||
+ Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
+ Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
@ -291,8 +291,8 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL-rele
|
||||||
+struct banan_os_window
|
+struct banan_os_window
|
||||||
+{
|
+{
|
||||||
+ BAN::UniqPtr<LibGUI::Window> window;
|
+ BAN::UniqPtr<LibGUI::Window> window;
|
||||||
+ LibGUI::Texture framebuffer;
|
+ OSMesaContext gl_context { nullptr };
|
||||||
+ OSMesaContext gl_context;
|
+ SDL_bool relative { SDL_FALSE };
|
||||||
+};
|
+};
|
||||||
+
|
+
|
||||||
+struct banan_os_video_device_data
|
+struct banan_os_video_device_data
|
||||||
|
@ -442,6 +442,8 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL-rele
|
||||||
+{
|
+{
|
||||||
+ DUMP_FUNCTION();
|
+ DUMP_FUNCTION();
|
||||||
+
|
+
|
||||||
|
+ // FIXME: support system cursors :)
|
||||||
|
+
|
||||||
+ auto* cursor = static_cast<SDL_Cursor*>(SDL_calloc(1, sizeof(SDL_Cursor)));
|
+ auto* cursor = static_cast<SDL_Cursor*>(SDL_calloc(1, sizeof(SDL_Cursor)));
|
||||||
+ if (cursor == nullptr) {
|
+ if (cursor == nullptr) {
|
||||||
+ SDL_OutOfMemory();
|
+ SDL_OutOfMemory();
|
||||||
|
@ -473,12 +475,17 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL-rele
|
||||||
+ return 0;
|
+ return 0;
|
||||||
+}
|
+}
|
||||||
+
|
+
|
||||||
+static int BANAN_OS_CaptureMouse(SDL_Window* window)
|
+static int BANAN_OS_SetRelativeMouseMode(SDL_bool enabled)
|
||||||
+{
|
+{
|
||||||
+ DUMP_FUNCTION();
|
+ DUMP_FUNCTION();
|
||||||
+
|
+
|
||||||
|
+ auto* window = SDL_GetMouseFocus();
|
||||||
|
+ if (window == nullptr)
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
+ auto& ban_window = *static_cast<banan_os_window*>(window->driverdata);
|
+ auto& ban_window = *static_cast<banan_os_window*>(window->driverdata);
|
||||||
+ ban_window.window->set_mouse_capture(SDL_GetMouse()->capture_window == window);
|
+ ban_window.window->set_mouse_relative(enabled);
|
||||||
|
+ ban_window.relative = enabled;
|
||||||
+
|
+
|
||||||
+ return 0;
|
+ return 0;
|
||||||
+}
|
+}
|
||||||
|
@ -489,9 +496,11 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL-rele
|
||||||
+
|
+
|
||||||
+ auto* mouse = SDL_GetMouse();
|
+ auto* mouse = SDL_GetMouse();
|
||||||
+ mouse->ShowCursor = BANAN_OS_ShowCursor;
|
+ mouse->ShowCursor = BANAN_OS_ShowCursor;
|
||||||
+ mouse->CaptureMouse = BANAN_OS_CaptureMouse;
|
+ mouse->SetRelativeMouseMode = BANAN_OS_SetRelativeMouseMode;
|
||||||
+ mouse->CreateSystemCursor = BANAN_OS_CreateSystemCursor;
|
+ mouse->CreateSystemCursor = BANAN_OS_CreateSystemCursor;
|
||||||
+ mouse->FreeCursor = BANAN_OS_FreeCursor;
|
+ mouse->FreeCursor = BANAN_OS_FreeCursor;
|
||||||
|
+
|
||||||
|
+ SDL_SetDefaultCursor(BANAN_OS_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW));
|
||||||
+}
|
+}
|
||||||
+
|
+
|
||||||
+static int BANAN_OS_VideoInit(_THIS)
|
+static int BANAN_OS_VideoInit(_THIS)
|
||||||
|
@ -588,16 +597,16 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL-rele
|
||||||
+ );
|
+ );
|
||||||
+
|
+
|
||||||
+ ban_window->window->set_mouse_button_event_callback(
|
+ ban_window->window->set_mouse_button_event_callback(
|
||||||
+ [window](LibGUI::EventPacket::MouseButtonEvent::event_t event) {
|
+ [window, ban_window](LibGUI::EventPacket::MouseButtonEvent::event_t event) {
|
||||||
+ const int state = event.pressed ? SDL_PRESSED : SDL_RELEASED;
|
+ const int state = event.pressed ? SDL_PRESSED : SDL_RELEASED;
|
||||||
+ SDL_SendMouseMotion(window, 0, SDL_FALSE, event.x, event.y);
|
+ SDL_SendMouseMotion(window, 0, ban_window->relative, event.x, event.y);
|
||||||
+ SDL_SendMouseButton(window, 0, state, BANAN_OS_mouse_button_to_sdl(event.button));
|
+ SDL_SendMouseButton(window, 0, state, BANAN_OS_mouse_button_to_sdl(event.button));
|
||||||
+ }
|
+ }
|
||||||
+ );
|
+ );
|
||||||
+
|
+
|
||||||
+ ban_window->window->set_mouse_move_event_callback(
|
+ ban_window->window->set_mouse_move_event_callback(
|
||||||
+ [window](LibGUI::EventPacket::MouseMoveEvent::event_t event) {
|
+ [window, ban_window](LibGUI::EventPacket::MouseMoveEvent::event_t event) {
|
||||||
+ SDL_SendMouseMotion(window, 0, SDL_FALSE, event.x, event.y);
|
+ SDL_SendMouseMotion(window, 0, ban_window->relative, event.x, event.y);
|
||||||
+ }
|
+ }
|
||||||
+ );
|
+ );
|
||||||
+
|
+
|
||||||
|
@ -613,13 +622,13 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL-rele
|
||||||
+ const size_t height = ban_window->window->height();
|
+ const size_t height = ban_window->window->height();
|
||||||
+
|
+
|
||||||
+ if (ban_window->gl_context) {
|
+ if (ban_window->gl_context) {
|
||||||
+ ban_window->framebuffer = MUST(LibGUI::Texture::create(width, height, 0x000000));
|
|
||||||
+ OSMesaMakeCurrent(
|
+ OSMesaMakeCurrent(
|
||||||
+ ban_window->gl_context,
|
+ ban_window->gl_context,
|
||||||
+ ban_window->framebuffer.pixels().data(),
|
+ ban_window->window->texture().pixels().data(),
|
||||||
+ GL_UNSIGNED_BYTE,
|
+ GL_UNSIGNED_BYTE,
|
||||||
+ width, height
|
+ width, height
|
||||||
+ );
|
+ );
|
||||||
|
+ OSMesaPixelStore(OSMESA_Y_UP, 0);
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, width, height);
|
+ SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, width, height);
|
||||||
|
@ -767,11 +776,9 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL-rele
|
||||||
+ return -1;
|
+ return -1;
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ ban_window.framebuffer = framebuffer_or_error.release_value();
|
|
||||||
+
|
|
||||||
+ *format = SDL_PIXELFORMAT_BGR888;
|
+ *format = SDL_PIXELFORMAT_BGR888;
|
||||||
+ *pixels = ban_window.framebuffer.pixels().data();
|
+ *pixels = ban_window.window->texture().pixels().data();
|
||||||
+ *pitch = ban_window.framebuffer.width() * sizeof(uint32_t);
|
+ *pitch = ban_window.window->texture().width() * sizeof(uint32_t);
|
||||||
+
|
+
|
||||||
+ return 0;
|
+ return 0;
|
||||||
+}
|
+}
|
||||||
|
@ -782,25 +789,8 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL-rele
|
||||||
+
|
+
|
||||||
+ auto& ban_window = *static_cast<banan_os_window*>(window->driverdata);
|
+ auto& ban_window = *static_cast<banan_os_window*>(window->driverdata);
|
||||||
+
|
+
|
||||||
+ int min_x = ban_window.window->width();
|
+ for (int i = 0; i < numrects; i++)
|
||||||
+ int min_y = ban_window.window->height();
|
+ ban_window.window->invalidate(rects[i].x, rects[i].y, rects[i].w, rects[i].h);
|
||||||
+ int max_x = 0;
|
|
||||||
+ int max_y = 0;
|
|
||||||
+ for (int i = 0; i < numrects; i++) {
|
|
||||||
+ ban_window.window->texture().copy_texture(ban_window.framebuffer,
|
|
||||||
+ rects[i].x, rects[i].y,
|
|
||||||
+ rects[i].x, rects[i].y,
|
|
||||||
+ rects[i].w, rects[i].h
|
|
||||||
+ );
|
|
||||||
+
|
|
||||||
+ min_x = BAN::Math::min(min_x, rects[i].x);
|
|
||||||
+ min_y = BAN::Math::min(min_y, rects[i].y);
|
|
||||||
+ max_x = BAN::Math::max(max_x, rects[i].x + rects[i].w);
|
|
||||||
+ max_y = BAN::Math::max(max_y, rects[i].y + rects[i].h);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (min_x < max_x && min_y < max_y)
|
|
||||||
+ ban_window.window->invalidate(min_x, min_y, max_x - min_x, max_y - min_y);
|
|
||||||
+
|
+
|
||||||
+ return 0;
|
+ return 0;
|
||||||
+}
|
+}
|
||||||
|
@ -808,32 +798,6 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL-rele
|
||||||
+static void BANAN_OS_DestroyWindowFramebuffer(_THIS, SDL_Window* window)
|
+static void BANAN_OS_DestroyWindowFramebuffer(_THIS, SDL_Window* window)
|
||||||
+{
|
+{
|
||||||
+ DUMP_FUNCTION();
|
+ DUMP_FUNCTION();
|
||||||
+
|
|
||||||
+ auto& ban_window = *static_cast<banan_os_window*>(window->driverdata);
|
|
||||||
+ ban_window.framebuffer = {};
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int BANAN_OS_WaitEventTimeout(_THIS, int timeout)
|
|
||||||
+{
|
|
||||||
+ DUMP_FUNCTION();
|
|
||||||
+
|
|
||||||
+ auto& ban_video_device_data = *static_cast<banan_os_video_device_data*>(_this->driverdata);
|
|
||||||
+
|
|
||||||
+ fd_set fds;
|
|
||||||
+ FD_ZERO(&fds);
|
|
||||||
+
|
|
||||||
+ int max_fd = 0;
|
|
||||||
+ for (auto* window : ban_video_device_data.windows)
|
|
||||||
+ {
|
|
||||||
+ max_fd = BAN::Math::max(max_fd, window->window->server_fd());
|
|
||||||
+ FD_SET(window->window->server_fd(), &fds);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ timeval tv {
|
|
||||||
+ .tv_sec = static_cast<time_t>(timeout / 1000),
|
|
||||||
+ .tv_usec = static_cast<suseconds_t>((timeout % 1000) * 1000),
|
|
||||||
+ };
|
|
||||||
+ return select(max_fd + 1, &fds, nullptr, nullptr, &tv);
|
|
||||||
+}
|
+}
|
||||||
+
|
+
|
||||||
+static void BANAN_OS_PumpEvents(_THIS)
|
+static void BANAN_OS_PumpEvents(_THIS)
|
||||||
|
@ -871,25 +835,19 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL-rele
|
||||||
+
|
+
|
||||||
+ auto& ban_window = *static_cast<banan_os_window*>(window->driverdata);
|
+ auto& ban_window = *static_cast<banan_os_window*>(window->driverdata);
|
||||||
+
|
+
|
||||||
+ auto framebuffer_or_error = LibGUI::Texture::create(ban_window.window->width(), ban_window.window->width(), 0x000000);
|
|
||||||
+ if (framebuffer_or_error.is_error()) {
|
|
||||||
+ dwarnln("LibGUI::Texture::create: {}", framebuffer_or_error.error());
|
|
||||||
+ return nullptr;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ auto gl_context = OSMesaCreateContext(OSMESA_BGRA, NULL);
|
+ auto gl_context = OSMesaCreateContext(OSMESA_BGRA, NULL);
|
||||||
+ if (gl_context == nullptr) {
|
+ if (gl_context == nullptr) {
|
||||||
+ dwarnln("OSMesaCreateContext");
|
+ dwarnln("OSMesaCreateContext");
|
||||||
+ return nullptr;
|
+ return nullptr;
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ auto fb = framebuffer_or_error.release_value();
|
+ auto& fb = ban_window.window->texture();
|
||||||
+ if (!OSMesaMakeCurrent(gl_context, fb.pixels().data(), GL_UNSIGNED_BYTE, fb.width(), fb.height())) {
|
+ if (!OSMesaMakeCurrent(gl_context, fb.pixels().data(), GL_UNSIGNED_BYTE, fb.width(), fb.height())) {
|
||||||
+ OSMesaDestroyContext(gl_context);
|
+ OSMesaDestroyContext(gl_context);
|
||||||
+ return nullptr;
|
+ return nullptr;
|
||||||
+ }
|
+ }
|
||||||
|
+ OSMesaPixelStore(OSMESA_Y_UP, 0);
|
||||||
+
|
+
|
||||||
+ ban_window.framebuffer = BAN::move(fb);
|
|
||||||
+ ban_window.gl_context = gl_context;
|
+ ban_window.gl_context = gl_context;
|
||||||
+
|
+
|
||||||
+ return gl_context;
|
+ return gl_context;
|
||||||
|
@ -914,9 +872,10 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL-rele
|
||||||
+
|
+
|
||||||
+ auto gl_context = static_cast<OSMesaContext>(context);
|
+ auto gl_context = static_cast<OSMesaContext>(context);
|
||||||
+
|
+
|
||||||
+ auto& fb = ban_window.framebuffer;
|
+ auto& fb = ban_window.window->texture();
|
||||||
+ if (!OSMesaMakeCurrent(gl_context, fb.pixels().data(), GL_UNSIGNED_BYTE, fb.width(), fb.height()))
|
+ if (!OSMesaMakeCurrent(gl_context, fb.pixels().data(), GL_UNSIGNED_BYTE, fb.width(), fb.height()))
|
||||||
+ return -1;
|
+ return -1;
|
||||||
|
+ OSMesaPixelStore(OSMESA_Y_UP, 0);
|
||||||
+
|
+
|
||||||
+ return 0;
|
+ return 0;
|
||||||
+}
|
+}
|
||||||
|
@ -931,15 +890,6 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL-rele
|
||||||
+ glFinish();
|
+ glFinish();
|
||||||
+
|
+
|
||||||
+ auto& ban_window = *static_cast<banan_os_window*>(window->driverdata);
|
+ auto& ban_window = *static_cast<banan_os_window*>(window->driverdata);
|
||||||
+
|
|
||||||
+ auto* src = ban_window.framebuffer.pixels().data();
|
|
||||||
+ auto* dst = ban_window.window->texture().pixels().data();
|
|
||||||
+
|
|
||||||
+ const size_t width = ban_window.window->width();
|
|
||||||
+ const size_t height = ban_window.window->height();
|
|
||||||
+ for (size_t y = 0; y < height; y++)
|
|
||||||
+ memcpy(&dst[(height - y - 1) * width], &src[y * width], width * 4);
|
|
||||||
+
|
|
||||||
+ ban_window.window->invalidate();
|
+ ban_window.window->invalidate();
|
||||||
+
|
+
|
||||||
+ return 0;
|
+ return 0;
|
||||||
|
@ -982,7 +932,6 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL-rele
|
||||||
+ device->UpdateWindowFramebuffer = BANAN_OS_UpdateWindowFramebuffer;
|
+ device->UpdateWindowFramebuffer = BANAN_OS_UpdateWindowFramebuffer;
|
||||||
+ device->DestroyWindowFramebuffer = BANAN_OS_DestroyWindowFramebuffer;
|
+ device->DestroyWindowFramebuffer = BANAN_OS_DestroyWindowFramebuffer;
|
||||||
+
|
+
|
||||||
+ device->WaitEventTimeout = BANAN_OS_WaitEventTimeout;
|
|
||||||
+ device->PumpEvents = BANAN_OS_PumpEvents;
|
+ device->PumpEvents = BANAN_OS_PumpEvents;
|
||||||
+
|
+
|
||||||
+ device->GL_LoadLibrary = BANAN_OS_GL_LoadLibrary;
|
+ device->GL_LoadLibrary = BANAN_OS_GL_LoadLibrary;
|
||||||
|
@ -1006,9 +955,9 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL-rele
|
||||||
+#endif /* SDL_VIDEO_DRIVER_BANAN_OS */
|
+#endif /* SDL_VIDEO_DRIVER_BANAN_OS */
|
||||||
+
|
+
|
||||||
+/* vi: set ts=4 sw=4 expandtab: */
|
+/* vi: set ts=4 sw=4 expandtab: */
|
||||||
diff -ruN SDL-release-2.30.11/src/video/SDL_sysvideo.h SDL-release-2.30.11-banan_os/src/video/SDL_sysvideo.h
|
diff -ruN SDL-release-2.30.11/src/video/SDL_sysvideo.h SDL2-2.30.11-banan_os/src/video/SDL_sysvideo.h
|
||||||
--- SDL-release-2.30.11/src/video/SDL_sysvideo.h 2025-01-01 19:09:38.000000000 +0200
|
--- SDL-release-2.30.11/src/video/SDL_sysvideo.h 2025-01-01 19:09:38.000000000 +0200
|
||||||
+++ SDL-release-2.30.11-banan_os/src/video/SDL_sysvideo.h 2025-06-24 18:55:08.546768590 +0300
|
+++ SDL2-2.30.11-banan_os/src/video/SDL_sysvideo.h 2025-08-03 14:04:09.895655165 +0300
|
||||||
@@ -462,6 +462,7 @@
|
@@ -462,6 +462,7 @@
|
||||||
extern VideoBootStrap WINDOWS_bootstrap;
|
extern VideoBootStrap WINDOWS_bootstrap;
|
||||||
extern VideoBootStrap WINRT_bootstrap;
|
extern VideoBootStrap WINRT_bootstrap;
|
||||||
|
@ -1017,9 +966,9 @@ diff -ruN SDL-release-2.30.11/src/video/SDL_sysvideo.h SDL-release-2.30.11-banan
|
||||||
extern VideoBootStrap PND_bootstrap;
|
extern VideoBootStrap PND_bootstrap;
|
||||||
extern VideoBootStrap UIKIT_bootstrap;
|
extern VideoBootStrap UIKIT_bootstrap;
|
||||||
extern VideoBootStrap Android_bootstrap;
|
extern VideoBootStrap Android_bootstrap;
|
||||||
diff -ruN SDL-release-2.30.11/src/video/SDL_video.c SDL-release-2.30.11-banan_os/src/video/SDL_video.c
|
diff -ruN SDL-release-2.30.11/src/video/SDL_video.c SDL2-2.30.11-banan_os/src/video/SDL_video.c
|
||||||
--- SDL-release-2.30.11/src/video/SDL_video.c 2025-01-01 19:09:38.000000000 +0200
|
--- SDL-release-2.30.11/src/video/SDL_video.c 2025-01-01 19:09:38.000000000 +0200
|
||||||
+++ SDL-release-2.30.11-banan_os/src/video/SDL_video.c 2025-06-24 19:37:36.342677687 +0300
|
+++ SDL2-2.30.11-banan_os/src/video/SDL_video.c 2025-08-03 14:04:09.896007237 +0300
|
||||||
@@ -94,6 +94,9 @@
|
@@ -94,6 +94,9 @@
|
||||||
#ifdef SDL_VIDEO_DRIVER_HAIKU
|
#ifdef SDL_VIDEO_DRIVER_HAIKU
|
||||||
&HAIKU_bootstrap,
|
&HAIKU_bootstrap,
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
#!/bin/bash ../install.sh
|
||||||
|
|
||||||
|
NAME='cmake'
|
||||||
|
VERSION='3.26.6' # NOTE: same version as used by our toolchain
|
||||||
|
DOWNLOAD_URL="https://github.com/Kitware/CMake/releases/download/v$VERSION/cmake-$VERSION.tar.gz#070b9a2422e666d2c1437e2dab239a236e8a63622d0a8d0ffe9e389613d2b76a"
|
||||||
|
DEPENDENCIES=('openssl' 'libuv' 'make' 'bash')
|
||||||
|
|
||||||
|
configure() {
|
||||||
|
$BANAN_CMAKE \
|
||||||
|
--toolchain=$BANAN_TOOLCHAIN_DIR/Toolchain.txt \
|
||||||
|
-B build -GNinja --fresh \
|
||||||
|
-DCMAKE_INSTALL_PREFIX=/usr \
|
||||||
|
-DCMAKE_USE_OPENSSL=ON \
|
||||||
|
-DCMAKE_USE_SYSTEM_LIBUV=ON \
|
||||||
|
-DOPENSSL_ROOT_DIR=/usr \
|
||||||
|
-DBUILD_TESTING=OFF \
|
||||||
|
. || exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
build() {
|
||||||
|
$BANAN_CMAKE --build build || exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
install() {
|
||||||
|
$BANAN_CMAKE --install build || exit 1
|
||||||
|
cp $BANAN_TOOLCHAIN_DIR/cmake-platform/* $BANAN_SYSROOT/usr/share/cmake-3.26/Modules/Platform/
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
diff -ruN cmake-3.26.6/Source/kwsys/ProcessUNIX.c cmake-3.26.6-x86_64/Source/kwsys/ProcessUNIX.c
|
||||||
|
--- cmake-3.26.6/Source/kwsys/ProcessUNIX.c 2023-11-27 20:48:12.000000000 +0200
|
||||||
|
+++ cmake-3.26.6-x86_64/Source/kwsys/ProcessUNIX.c 2025-07-30 21:49:08.783313124 +0300
|
||||||
|
@@ -115,7 +115,7 @@
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Some platforms do not have siginfo on their signal handlers. */
|
||||||
|
-#if defined(SA_SIGINFO) && !defined(__BEOS__)
|
||||||
|
+#if defined(SA_SIGINFO) && !defined(__BEOS__) && !defined(__banan_os__)
|
||||||
|
# define KWSYSPE_USE_SIGINFO 1
|
||||||
|
#endif
|
||||||
|
|
|
@ -42,8 +42,9 @@ fi
|
||||||
export MESON_CROSS_FILE="$BANAN_PORT_DIR/$BANAN_ARCH-banan_os-meson.txt"
|
export MESON_CROSS_FILE="$BANAN_PORT_DIR/$BANAN_ARCH-banan_os-meson.txt"
|
||||||
if [ ! -f "$MESON_CROSS_FILE" ] || [ "$MESON_CROSS_FILE" -ot "$BANAN_TOOLCHAIN_DIR/meson-cross-file.in" ]; then
|
if [ ! -f "$MESON_CROSS_FILE" ] || [ "$MESON_CROSS_FILE" -ot "$BANAN_TOOLCHAIN_DIR/meson-cross-file.in" ]; then
|
||||||
cp "$BANAN_TOOLCHAIN_DIR/meson-cross-file.in" "$MESON_CROSS_FILE"
|
cp "$BANAN_TOOLCHAIN_DIR/meson-cross-file.in" "$MESON_CROSS_FILE"
|
||||||
sed -i "s/ARCH/$BANAN_ARCH/" "$MESON_CROSS_FILE"
|
sed -i "s|ARCH|$BANAN_ARCH|" "$MESON_CROSS_FILE"
|
||||||
sed -i "s/SYSROOT/$BANAN_SYSROOT/" "$MESON_CROSS_FILE"
|
sed -i "s|CMAKE|$BANAN_CMAKE|" "$MESON_CROSS_FILE"
|
||||||
|
sed -i "s|SYSROOT|$BANAN_SYSROOT|" "$MESON_CROSS_FILE"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
MAKE_BUILD_TARGETS=('all')
|
MAKE_BUILD_TARGETS=('all')
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
#!/bin/bash ../install.sh
|
||||||
|
|
||||||
|
NAME='libuv'
|
||||||
|
VERSION='1.51.0'
|
||||||
|
DOWNLOAD_URL="https://dist.libuv.org/dist/v$VERSION/libuv-v$VERSION.tar.gz#5f0557b90b1106de71951a3c3931de5e0430d78da1d9a10287ebc7a3f78ef8eb"
|
||||||
|
TAR_CONTENT="libuv-v$VERSION"
|
||||||
|
|
||||||
|
configure() {
|
||||||
|
$BANAN_CMAKE \
|
||||||
|
--toolchain="$BANAN_TOOLCHAIN_DIR/Toolchain.txt" \
|
||||||
|
-B build -GNinja --fresh \
|
||||||
|
-DCMAKE_INSTALL_PREFIX=/usr \
|
||||||
|
-DBUILD_TESTING=OFF \
|
||||||
|
. || exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
build() {
|
||||||
|
$BANAN_CMAKE --build build || exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
install() {
|
||||||
|
$BANAN_CMAKE --install build || exit 1
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
diff -ruN libuv-v1.51.0/src/unix/tty.c libuv-1.51.0-x86_64/src/unix/tty.c
|
||||||
|
--- libuv-v1.51.0/src/unix/tty.c 2025-04-25 12:50:27.000000000 +0300
|
||||||
|
+++ libuv-1.51.0-x86_64/src/unix/tty.c 2025-07-23 17:12:21.857957334 +0300
|
||||||
|
@@ -30,7 +30,7 @@
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
|
-#if defined(__MVS__) && !defined(IMAXBEL)
|
||||||
|
+#if (defined(__MVS__) || defined(__banan_os__)) && !defined(IMAXBEL)
|
||||||
|
#define IMAXBEL 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@@ -244,7 +244,7 @@
|
||||||
|
static void uv__tty_make_raw(struct termios* tio) {
|
||||||
|
assert(tio != NULL);
|
||||||
|
|
||||||
|
-#if defined __sun || defined __MVS__
|
||||||
|
+#if defined __sun || defined __MVS__ || defined(__banan_os__)
|
||||||
|
/*
|
||||||
|
* This implementation of cfmakeraw for Solaris and derivatives is taken from
|
||||||
|
* http://www.perkin.org.uk/posts/solaris-portability-cfmakeraw.html.
|
|
@ -0,0 +1,12 @@
|
||||||
|
diff -ruN libuv-v1.51.0/src/unix/core.c libuv-1.51.0-x86_64/src/unix/core.c
|
||||||
|
--- libuv-v1.51.0/src/unix/core.c 2025-04-25 12:50:27.000000000 +0300
|
||||||
|
+++ libuv-1.51.0-x86_64/src/unix/core.c 2025-07-23 17:11:06.844349261 +0300
|
||||||
|
@@ -1036,7 +1036,7 @@
|
||||||
|
rusage->ru_stime.tv_sec = usage.ru_stime.tv_sec;
|
||||||
|
rusage->ru_stime.tv_usec = usage.ru_stime.tv_usec;
|
||||||
|
|
||||||
|
-#if !defined(__MVS__) && !defined(__HAIKU__)
|
||||||
|
+#if !defined(__MVS__) && !defined(__HAIKU__) && !defined(__banan_os__)
|
||||||
|
rusage->ru_maxrss = usage.ru_maxrss;
|
||||||
|
rusage->ru_ixrss = usage.ru_ixrss;
|
||||||
|
rusage->ru_idrss = usage.ru_idrss;
|
|
@ -0,0 +1,33 @@
|
||||||
|
diff -ruN libuv-v1.51.0/src/unix/fs.c libuv-1.51.0-x86_64/src/unix/fs.c
|
||||||
|
--- libuv-v1.51.0/src/unix/fs.c 2025-04-25 12:50:27.000000000 +0300
|
||||||
|
+++ libuv-1.51.0-x86_64/src/unix/fs.c 2025-07-23 17:14:28.118310214 +0300
|
||||||
|
@@ -77,7 +77,8 @@
|
||||||
|
defined(__MVS__) || \
|
||||||
|
defined(__NetBSD__) || \
|
||||||
|
defined(__HAIKU__) || \
|
||||||
|
- defined(__QNX__)
|
||||||
|
+ defined(__QNX__) || \
|
||||||
|
+ defined(__banan_os__)
|
||||||
|
# include <sys/statvfs.h>
|
||||||
|
#else
|
||||||
|
# include <sys/statfs.h>
|
||||||
|
@@ -683,7 +684,8 @@
|
||||||
|
defined(__MVS__) || \
|
||||||
|
defined(__NetBSD__) || \
|
||||||
|
defined(__HAIKU__) || \
|
||||||
|
- defined(__QNX__)
|
||||||
|
+ defined(__QNX__) || \
|
||||||
|
+ defined(__banan_os__)
|
||||||
|
struct statvfs buf;
|
||||||
|
|
||||||
|
if (0 != statvfs(req->path, &buf))
|
||||||
|
@@ -705,7 +707,8 @@
|
||||||
|
defined(__OpenBSD__) || \
|
||||||
|
defined(__NetBSD__) || \
|
||||||
|
defined(__HAIKU__) || \
|
||||||
|
- defined(__QNX__)
|
||||||
|
+ defined(__QNX__) || \
|
||||||
|
+ defined(__banan_os__)
|
||||||
|
stat_fs->f_type = 0; /* f_type is not supported. */
|
||||||
|
#else
|
||||||
|
stat_fs->f_type = buf.f_type;
|
|
@ -0,0 +1,13 @@
|
||||||
|
diff -ruN libuv-v1.51.0/src/unix/process.c libuv-1.51.0-x86_64/src/unix/process.c
|
||||||
|
--- libuv-v1.51.0/src/unix/process.c 2025-04-25 12:50:27.000000000 +0300
|
||||||
|
+++ libuv-1.51.0-x86_64/src/unix/process.c 2025-07-23 17:16:04.548824726 +0300
|
||||||
|
@@ -390,7 +390,9 @@
|
||||||
|
* aren't root, so don't bother checking the return value, this
|
||||||
|
* is just done as an optimistic privilege dropping function.
|
||||||
|
*/
|
||||||
|
+ #if !defined(__banan_os__)
|
||||||
|
SAVE_ERRNO(setgroups(0, NULL));
|
||||||
|
+ #endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((options->flags & UV_PROCESS_SETGID) && setgid(options->gid))
|
|
@ -0,0 +1,22 @@
|
||||||
|
diff -ruN libuv-v1.51.0/src/unix/thread.c libuv-1.51.0-x86_64/src/unix/thread.c
|
||||||
|
--- libuv-v1.51.0/src/unix/thread.c 2025-04-25 12:50:27.000000000 +0300
|
||||||
|
+++ libuv-1.51.0-x86_64/src/unix/thread.c 2025-07-23 17:16:19.619749435 +0300
|
||||||
|
@@ -897,7 +897,7 @@
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
-#if defined(_AIX) || defined(__MVS__) || defined(__PASE__)
|
||||||
|
+#if defined(_AIX) || defined(__MVS__) || defined(__PASE__) || defined(__banan_os__)
|
||||||
|
int uv__thread_setname(const char* name) {
|
||||||
|
return UV_ENOSYS;
|
||||||
|
}
|
||||||
|
@@ -938,7 +938,8 @@
|
||||||
|
#if (defined(__ANDROID_API__) && __ANDROID_API__ < 26) || \
|
||||||
|
defined(_AIX) || \
|
||||||
|
defined(__MVS__) || \
|
||||||
|
- defined(__PASE__)
|
||||||
|
+ defined(__PASE__) || \
|
||||||
|
+ defined(__banan_os__)
|
||||||
|
int uv__thread_getname(uv_thread_t* tid, char* name, size_t size) {
|
||||||
|
return UV_ENOSYS;
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
diff -ruN libuv-v1.51.0/src/unix/udp.c libuv-1.51.0-x86_64/src/unix/udp.c
|
||||||
|
--- libuv-v1.51.0/src/unix/udp.c 2025-04-25 12:50:27.000000000 +0300
|
||||||
|
+++ libuv-1.51.0-x86_64/src/unix/udp.c 2025-07-23 17:15:38.986952773 +0300
|
||||||
|
@@ -767,7 +767,8 @@
|
||||||
|
!defined(__ANDROID__) && \
|
||||||
|
!defined(__DragonFly__) && \
|
||||||
|
!defined(__QNX__) && \
|
||||||
|
- !defined(__GNU__)
|
||||||
|
+ !defined(__GNU__) && \
|
||||||
|
+ !defined(__banan_os__)
|
||||||
|
static int uv__udp_set_source_membership4(uv_udp_t* handle,
|
||||||
|
const struct sockaddr_in* multicast_addr,
|
||||||
|
const char* interface_addr,
|
||||||
|
@@ -958,7 +959,8 @@
|
||||||
|
!defined(__ANDROID__) && \
|
||||||
|
!defined(__DragonFly__) && \
|
||||||
|
!defined(__QNX__) && \
|
||||||
|
- !defined(__GNU__)
|
||||||
|
+ !defined(__GNU__) && \
|
||||||
|
+ !defined(__banan_os__)
|
||||||
|
int err;
|
||||||
|
union uv__sockaddr mcast_addr;
|
||||||
|
union uv__sockaddr src_addr;
|
|
@ -0,0 +1,32 @@
|
||||||
|
diff -ruN libuv-v1.51.0/include/uv/unix.h libuv-1.51.0-x86_64/include/uv/unix.h
|
||||||
|
--- libuv-v1.51.0/include/uv/unix.h 2025-04-25 12:50:27.000000000 +0300
|
||||||
|
+++ libuv-1.51.0-x86_64/include/uv/unix.h 2025-07-28 14:06:18.220856588 +0300
|
||||||
|
@@ -66,7 +66,8 @@
|
||||||
|
defined(__MSYS__) || \
|
||||||
|
defined(__HAIKU__) || \
|
||||||
|
defined(__QNX__) || \
|
||||||
|
- defined(__GNU__)
|
||||||
|
+ defined(__GNU__) || \
|
||||||
|
+ defined(__banan_os__)
|
||||||
|
# include "uv/posix.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
diff -ruN libuv-v1.51.0/CMakeLists.txt libuv-1.51.0-x86_64/CMakeLists.txt
|
||||||
|
--- libuv-v1.51.0/CMakeLists.txt 2025-04-25 12:50:27.000000000 +0300
|
||||||
|
+++ libuv-1.51.0-x86_64/CMakeLists.txt 2025-07-28 13:57:21.518563402 +0300
|
||||||
|
@@ -283,6 +283,15 @@
|
||||||
|
list(APPEND uv_sources src/unix/proctitle.c)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
+if(CMAKE_SYSTEM_NAME STREQUAL "banan-os")
|
||||||
|
+ list(APPEND uv_sources
|
||||||
|
+ src/unix/no-fsevents.c
|
||||||
|
+ src/unix/no-proctitle.c
|
||||||
|
+ src/unix/posix-hrtime.c
|
||||||
|
+ src/unix/posix-poll.c
|
||||||
|
+ )
|
||||||
|
+endif()
|
||||||
|
+
|
||||||
|
if(CMAKE_SYSTEM_NAME MATCHES "DragonFly|FreeBSD")
|
||||||
|
list(APPEND uv_sources src/unix/freebsd.c)
|
||||||
|
endif()
|
|
@ -0,0 +1,34 @@
|
||||||
|
#!/bin/bash ../install.sh
|
||||||
|
|
||||||
|
NAME='llvm'
|
||||||
|
VERSION='20.1.8'
|
||||||
|
DOWNLOAD_URL="https://github.com/llvm/llvm-project/releases/download/llvmorg-$VERSION/llvm-project-$VERSION.src.tar.xz#6898f963c8e938981e6c4a302e83ec5beb4630147c7311183cf61069af16333d"
|
||||||
|
TAR_CONTENT="llvm-project-$VERSION.src"
|
||||||
|
DEPENDENCIES=('zlib' 'zstd')
|
||||||
|
|
||||||
|
configure() {
|
||||||
|
unset CC CXX LD
|
||||||
|
|
||||||
|
$BANAN_CMAKE -B build -S llvm -G Ninja \
|
||||||
|
--toolchain="$BANAN_TOOLCHAIN_DIR/Toolchain.txt" \
|
||||||
|
-DCMAKE_BUILD_TYPE=Release \
|
||||||
|
-DCMAKE_INSTALL_PREFIX=/usr \
|
||||||
|
-DLLVM_ENABLE_PROJECTS= \
|
||||||
|
-DLLVM_ENABLE_RTTI=ON \
|
||||||
|
-DLLVM_TARGETS_TO_BUILD=X86 \
|
||||||
|
-DLLVM_INCLUDE_BENCHMARKS=OFF \
|
||||||
|
-DLLVM_INCLUDE_TESTS=OFF \
|
||||||
|
-DLLVM_HOST_TRIPLE=x86_64-pc-banan_os \
|
||||||
|
-DLLVM_PARALLEL_LINK_JOBS=1 \
|
||||||
|
|| exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
build() {
|
||||||
|
$BANAN_CMAKE --build build || exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
install() {
|
||||||
|
# This port only contains llvm libraries used optionally by
|
||||||
|
# mesa port. There is no need to install and fill the disk :D
|
||||||
|
:
|
||||||
|
}
|
|
@ -0,0 +1,107 @@
|
||||||
|
diff -ruN llvm-project-20.1.8.src/llvm/include/llvm/ADT/bit.h llvm-project-20.1.8.src-banan_os/llvm/include/llvm/ADT/bit.h
|
||||||
|
--- llvm-project-20.1.8.src/llvm/include/llvm/ADT/bit.h 2025-07-09 02:06:32.000000000 +0300
|
||||||
|
+++ llvm-project-20.1.8.src-banan_os/llvm/include/llvm/ADT/bit.h 2025-08-03 17:05:07.723852159 +0300
|
||||||
|
@@ -29,7 +29,7 @@
|
||||||
|
|
||||||
|
#if defined(__linux__) || defined(__GNU__) || defined(__HAIKU__) || \
|
||||||
|
defined(__Fuchsia__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__) || \
|
||||||
|
- defined(__OpenBSD__) || defined(__DragonFly__)
|
||||||
|
+ defined(__OpenBSD__) || defined(__DragonFly__) || defined(__banan_os__)
|
||||||
|
#include <endian.h>
|
||||||
|
#elif defined(_AIX)
|
||||||
|
#include <sys/machine.h>
|
||||||
|
diff -ruN llvm-project-20.1.8.src/llvm/include/llvm/Support/ExitCodes.h llvm-project-20.1.8.src-banan_os/llvm/include/llvm/Support/ExitCodes.h
|
||||||
|
--- llvm-project-20.1.8.src/llvm/include/llvm/Support/ExitCodes.h 2025-07-09 02:06:32.000000000 +0300
|
||||||
|
+++ llvm-project-20.1.8.src-banan_os/llvm/include/llvm/Support/ExitCodes.h 2025-08-03 17:05:35.659696821 +0300
|
||||||
|
@@ -20,6 +20,8 @@
|
||||||
|
|
||||||
|
#if HAVE_SYSEXITS_H
|
||||||
|
#include <sysexits.h>
|
||||||
|
+#elif defined(__banan_os__)
|
||||||
|
+#define EX_IOERR 69
|
||||||
|
#elif __MVS__ || defined(_WIN32)
|
||||||
|
// <sysexits.h> does not exist on z/OS and Windows. The only value used in LLVM
|
||||||
|
// is EX_IOERR, which is used to signal a special error condition (broken pipe).
|
||||||
|
diff -ruN llvm-project-20.1.8.src/llvm/lib/Support/Unix/Path.inc llvm-project-20.1.8.src-banan_os/llvm/lib/Support/Unix/Path.inc
|
||||||
|
--- llvm-project-20.1.8.src/llvm/lib/Support/Unix/Path.inc 2025-07-09 02:06:32.000000000 +0300
|
||||||
|
+++ llvm-project-20.1.8.src-banan_os/llvm/lib/Support/Unix/Path.inc 2025-08-03 17:06:42.941322766 +0300
|
||||||
|
@@ -107,7 +107,7 @@
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__NetBSD__) || defined(__DragonFly__) || defined(__GNU__) || \
|
||||||
|
- defined(__MVS__)
|
||||||
|
+ defined(__MVS__) || defined(__banan_os__)
|
||||||
|
#define STATVFS_F_FLAG(vfs) (vfs).f_flag
|
||||||
|
#else
|
||||||
|
#define STATVFS_F_FLAG(vfs) (vfs).f_flags
|
||||||
|
@@ -317,6 +317,9 @@
|
||||||
|
return std::string(real_path);
|
||||||
|
break; // Found entry, but realpath failed.
|
||||||
|
}
|
||||||
|
+#elif defined(__banan_os__)
|
||||||
|
+ fprintf(stddbg, "TODO: getMainExecutable\n");
|
||||||
|
+ return "";
|
||||||
|
#elif defined(HAVE_DLOPEN)
|
||||||
|
// Use dladdr to get executable path if available.
|
||||||
|
Dl_info DLInfo;
|
||||||
|
@@ -506,6 +509,9 @@
|
||||||
|
#elif defined(__HAIKU__)
|
||||||
|
// Haiku doesn't expose this information.
|
||||||
|
return false;
|
||||||
|
+#elif defined(__banan_os__)
|
||||||
|
+ // banan-os doesn't currently support remote filesystem mounts.
|
||||||
|
+ return true;
|
||||||
|
#elif defined(__sun)
|
||||||
|
// statvfs::f_basetype contains a null-terminated FSType name of the mounted
|
||||||
|
// target
|
||||||
|
diff -ruN llvm-project-20.1.8.src/llvm/lib/Support/Unix/Program.inc llvm-project-20.1.8.src-banan_os/llvm/lib/Support/Unix/Program.inc
|
||||||
|
--- llvm-project-20.1.8.src/llvm/lib/Support/Unix/Program.inc 2025-07-09 02:06:32.000000000 +0300
|
||||||
|
+++ llvm-project-20.1.8.src-banan_os/llvm/lib/Support/Unix/Program.inc 2025-08-03 17:04:50.500947936 +0300
|
||||||
|
@@ -342,7 +342,7 @@
|
||||||
|
namespace llvm {
|
||||||
|
namespace sys {
|
||||||
|
|
||||||
|
-#if defined(_AIX)
|
||||||
|
+#if defined(_AIX) || defined(__banan_os__)
|
||||||
|
static pid_t(wait4)(pid_t pid, int *status, int options, struct rusage *usage);
|
||||||
|
#elif !defined(__Fuchsia__)
|
||||||
|
using ::wait4;
|
||||||
|
@@ -383,6 +383,17 @@
|
||||||
|
// would cause the call here to fail with ECHILD).
|
||||||
|
return ::wait4(pid, status, options & ~WNOHANG, usage);
|
||||||
|
}
|
||||||
|
+#elif defined(__banan_os__)
|
||||||
|
+
|
||||||
|
+#ifndef _ALL_SOURCE
|
||||||
|
+extern "C" pid_t(wait4)(pid_t pid, int *status, int options,
|
||||||
|
+ struct rusage *usage);
|
||||||
|
+#endif
|
||||||
|
+pid_t(llvm::sys::wait4)(pid_t pid, int *status, int options,
|
||||||
|
+ struct rusage *usage) {
|
||||||
|
+ memset(usage, 0, sizeof(struct rusage));
|
||||||
|
+ return waitpid(pid, status, options);
|
||||||
|
+}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ProcessInfo llvm::sys::Wait(const ProcessInfo &PI,
|
||||||
|
@@ -468,7 +479,7 @@
|
||||||
|
std::chrono::microseconds UserT = toDuration(Info.ru_utime);
|
||||||
|
std::chrono::microseconds KernelT = toDuration(Info.ru_stime);
|
||||||
|
uint64_t PeakMemory = 0;
|
||||||
|
-#if !defined(__HAIKU__) && !defined(__MVS__)
|
||||||
|
+#if !defined(__HAIKU__) && !defined(__MVS__) && !defined(__banan_os__)
|
||||||
|
PeakMemory = static_cast<uint64_t>(Info.ru_maxrss);
|
||||||
|
#endif
|
||||||
|
*ProcStat = ProcessStatistics{UserT + KernelT, UserT, PeakMemory};
|
||||||
|
diff -ruN llvm-project-20.1.8.src/llvm/lib/Support/Unix/Signals.inc llvm-project-20.1.8.src-banan_os/llvm/lib/Support/Unix/Signals.inc
|
||||||
|
--- llvm-project-20.1.8.src/llvm/lib/Support/Unix/Signals.inc 2025-07-09 02:06:32.000000000 +0300
|
||||||
|
+++ llvm-project-20.1.8.src-banan_os/llvm/lib/Support/Unix/Signals.inc 2025-08-03 17:03:20.739447219 +0300
|
||||||
|
@@ -817,7 +817,7 @@
|
||||||
|
OS << "Stack dump without symbol names (ensure you have llvm-symbolizer in "
|
||||||
|
"your PATH or set the environment var `LLVM_SYMBOLIZER_PATH` to point "
|
||||||
|
"to it):\n";
|
||||||
|
-#if HAVE_DLOPEN && !defined(_AIX)
|
||||||
|
+#if HAVE_DLOPEN && !defined(_AIX) && !defined(__banan_os__)
|
||||||
|
int width = 0;
|
||||||
|
for (int i = 0; i < depth; ++i) {
|
||||||
|
Dl_info dlinfo;
|
|
@ -7,7 +7,6 @@ DEPENDENCIES=('zlib' 'zstd' 'expat')
|
||||||
CONFIGURE_OPTIONS=(
|
CONFIGURE_OPTIONS=(
|
||||||
'-Dprefix=/usr'
|
'-Dprefix=/usr'
|
||||||
'-Dosmesa=true'
|
'-Dosmesa=true'
|
||||||
'-Dgallium-drivers=softpipe'
|
|
||||||
'-Dvulkan-drivers=[]'
|
'-Dvulkan-drivers=[]'
|
||||||
'-Dplatforms=[]'
|
'-Dplatforms=[]'
|
||||||
'-Dglx=disabled'
|
'-Dglx=disabled'
|
||||||
|
@ -15,7 +14,50 @@ CONFIGURE_OPTIONS=(
|
||||||
)
|
)
|
||||||
|
|
||||||
configure() {
|
configure() {
|
||||||
meson setup --reconfigure --cross-file "$MESON_CROSS_FILE" "${CONFIGURE_OPTIONS[@]}" build || exit 1
|
llvm_version='20.1.9'
|
||||||
|
llvm_root="../../llvm/llvm-$llvm_version-$BANAN_ARCH"
|
||||||
|
|
||||||
|
gallium_driver=softpipe
|
||||||
|
|
||||||
|
if [ -d "$llvm_root" ]; then
|
||||||
|
llvm_lib=$(realpath "$llvm_root/build/lib")
|
||||||
|
|
||||||
|
mkdir -p subprojects/llvm
|
||||||
|
|
||||||
|
wrap_file='subprojects/llvm/meson.build'
|
||||||
|
echo "project('llvm', ['cpp'])" >$wrap_file
|
||||||
|
echo "" >>$wrap_file
|
||||||
|
echo "cpp = meson.get_compiler('cpp')" >>$wrap_file
|
||||||
|
echo "" >>$wrap_file
|
||||||
|
echo "_deps = []" >>$wrap_file
|
||||||
|
echo "_search = '$llvm_lib'" >>$wrap_file
|
||||||
|
echo "foreach d : [" >>$wrap_file
|
||||||
|
for path in $llvm_lib/libLLVM*.a; do
|
||||||
|
name=$(basename $path)
|
||||||
|
echo " '${name:3:-2}'," >>$wrap_file
|
||||||
|
done
|
||||||
|
echo " ]" >>$wrap_file
|
||||||
|
echo " _deps += cpp.find_library(d, dirs : _search)" >>$wrap_file
|
||||||
|
echo "endforeach" >>$wrap_file
|
||||||
|
echo "" >>$wrap_file
|
||||||
|
echo "dep_llvm = declare_dependency(" >>$wrap_file
|
||||||
|
echo " include_directories : include_directories(" >>$wrap_file
|
||||||
|
echo " '$(realpath $llvm_root/llvm/include)'," >>$wrap_file
|
||||||
|
echo " '$(realpath $llvm_root/build/include)'," >>$wrap_file
|
||||||
|
echo " )," >>$wrap_file
|
||||||
|
echo " dependencies : _deps," >>$wrap_file
|
||||||
|
echo " version : '$llvm_version'," >>$wrap_file
|
||||||
|
echo ")" >>$wrap_file
|
||||||
|
|
||||||
|
gallium_driver=llvmpipe
|
||||||
|
fi
|
||||||
|
|
||||||
|
meson setup \
|
||||||
|
--reconfigure \
|
||||||
|
--cross-file "$MESON_CROSS_FILE" \
|
||||||
|
"${CONFIGURE_OPTIONS[@]}" \
|
||||||
|
"-Dgallium-drivers=$gallium_driver" \
|
||||||
|
build || exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
build() {
|
build() {
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
diff -ru mesa-25.0.7-banan_os/src/gallium/drivers/llvmpipe/lp_texture.c mesa-25.0.7-x86_64/src/gallium/drivers/llvmpipe/lp_texture.c
|
||||||
|
--- mesa-25.0.7-banan_os/src/gallium/drivers/llvmpipe/lp_texture.c 2025-05-28 18:20:23.000000000 +0300
|
||||||
|
+++ mesa-25.0.7-x86_64/src/gallium/drivers/llvmpipe/lp_texture.c 2025-08-03 19:16:20.254971098 +0300
|
||||||
|
@@ -59,7 +59,7 @@
|
||||||
|
#include "frontend/sw_winsys.h"
|
||||||
|
#include "git_sha1.h"
|
||||||
|
|
||||||
|
-#ifndef _WIN32
|
||||||
|
+#if !defined(_WIN32) && !defined(__banan_os__)
|
||||||
|
#include "drm-uapi/drm_fourcc.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@@ -1713,7 +1713,7 @@
|
||||||
|
case PIPE_RESOURCE_PARAM_LAYER_STRIDE:
|
||||||
|
*value = lpr->img_stride[level];
|
||||||
|
return true;
|
||||||
|
-#ifndef _WIN32
|
||||||
|
+#if !defined(_WIN32) && !defined(__banan_os__)
|
||||||
|
case PIPE_RESOURCE_PARAM_MODIFIER:
|
||||||
|
*value = lpr->dmabuf ? DRM_FORMAT_MOD_LINEAR : DRM_FORMAT_MOD_INVALID;
|
||||||
|
return true;
|
|
@ -13,8 +13,7 @@ CONFIGURE_OPTIONS=(
|
||||||
'--with-shared'
|
'--with-shared'
|
||||||
'--without-ada'
|
'--without-ada'
|
||||||
'--without-manpages'
|
'--without-manpages'
|
||||||
'--without-dlsym'
|
CFLAGS='-std=c17'
|
||||||
'--without-cxx-binding'
|
|
||||||
)
|
)
|
||||||
|
|
||||||
post_install() {
|
post_install() {
|
||||||
|
|
|
@ -20,7 +20,7 @@ configure() {
|
||||||
done
|
done
|
||||||
popd
|
popd
|
||||||
|
|
||||||
./waf configure -T release --disable-gl || exit 1
|
./waf configure -T release || exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
build() {
|
build() {
|
||||||
|
@ -29,6 +29,7 @@ build() {
|
||||||
|
|
||||||
install() {
|
install() {
|
||||||
./waf install --destdir=$BANAN_SYSROOT/home/user/halflife || exit 1
|
./waf install --destdir=$BANAN_SYSROOT/home/user/halflife || exit 1
|
||||||
|
patchelf --add-needed libxash.so $BANAN_SYSROOT/home/user/halflife/xash3d
|
||||||
|
|
||||||
cat > $BANAN_SYSROOT/home/user/halflife/start.sh << EOF
|
cat > $BANAN_SYSROOT/home/user/halflife/start.sh << EOF
|
||||||
#!/bin/Shell
|
#!/bin/Shell
|
||||||
|
|
|
@ -1,17 +1,20 @@
|
||||||
#!/bin/bash ../install.sh
|
#!/bin/bash ../install.sh
|
||||||
|
|
||||||
NAME='zstd'
|
NAME='zstd'
|
||||||
VERSION='1.5.6'
|
VERSION='1.5.7'
|
||||||
DOWNLOAD_URL="https://github.com/facebook/zstd/releases/download/v$VERSION/zstd-$VERSION.tar.gz#8c29e06cf42aacc1eafc4077ae2ec6c6fcb96a626157e0593d5e82a34fd403c1"
|
DOWNLOAD_URL="https://github.com/facebook/zstd/releases/download/v$VERSION/zstd-$VERSION.tar.gz#eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3"
|
||||||
|
|
||||||
configure() {
|
configure() {
|
||||||
:
|
$BANAN_CMAKE -B _build -S build/cmake -G Ninja \
|
||||||
|
--toolchain $BANAN_TOOLCHAIN_DIR/Toolchain.txt \
|
||||||
|
-DCMAKE_INSTALL_PREFIX=/usr \
|
||||||
|
|| exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
build() {
|
build() {
|
||||||
make -C lib -j$(nproc) lib-nomt || exit 1
|
$BANAN_CMAKE --build _build ||exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
install() {
|
install() {
|
||||||
make -C lib install "DESTDIR=$BANAN_SYSROOT" PREFIX=/usr || exit 1
|
$BANAN_CMAKE --install _build ||exit 1
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,13 +4,11 @@ set -e
|
||||||
export BANAN_SCRIPT_DIR=$(dirname $(realpath $0))
|
export BANAN_SCRIPT_DIR=$(dirname $(realpath $0))
|
||||||
source $BANAN_SCRIPT_DIR/config.sh
|
source $BANAN_SCRIPT_DIR/config.sh
|
||||||
|
|
||||||
FAKEROOT_FILE="$BANAN_BUILD_DIR/fakeroot-context"
|
|
||||||
|
|
||||||
run_fakeroot() {
|
run_fakeroot() {
|
||||||
if [ ! -f $FAKEROOT_FILE ]; then
|
if [ ! -f $BANAN_FAKEROOT ]; then
|
||||||
touch $FAKEROOT_FILE
|
touch $BANAN_FAKEROOT
|
||||||
fi
|
fi
|
||||||
fakeroot -i $FAKEROOT_FILE -s $FAKEROOT_FILE -- /bin/bash -c '$@' bash $@
|
fakeroot -i $BANAN_FAKEROOT -s $BANAN_FAKEROOT -- /bin/bash -c '$@' bash $@
|
||||||
}
|
}
|
||||||
|
|
||||||
make_build_dir () {
|
make_build_dir () {
|
||||||
|
@ -47,11 +45,6 @@ build_toolchain () {
|
||||||
create_image () {
|
create_image () {
|
||||||
build_target all
|
build_target all
|
||||||
build_target install
|
build_target install
|
||||||
|
|
||||||
pushd $BANAN_SYSROOT >/dev/null
|
|
||||||
run_fakeroot tar cf ${BANAN_SYSROOT_TAR} *
|
|
||||||
popd >/dev/null
|
|
||||||
|
|
||||||
$BANAN_SCRIPT_DIR/image.sh "$1"
|
$BANAN_SCRIPT_DIR/image.sh "$1"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,8 @@ export BANAN_BUILD_DIR="$BANAN_ROOT_DIR/build"
|
||||||
export BANAN_PORT_DIR="$BANAN_ROOT_DIR/ports"
|
export BANAN_PORT_DIR="$BANAN_ROOT_DIR/ports"
|
||||||
|
|
||||||
export BANAN_SYSROOT="$BANAN_BUILD_DIR/sysroot"
|
export BANAN_SYSROOT="$BANAN_BUILD_DIR/sysroot"
|
||||||
export BANAN_SYSROOT_TAR="$BANAN_SYSROOT.tar"
|
|
||||||
|
export BANAN_FAKEROOT="$BANAN_BUILD_DIR/fakeroot-context"
|
||||||
|
|
||||||
export BANAN_DISK_IMAGE_PATH="$BANAN_BUILD_DIR/banan-os.img"
|
export BANAN_DISK_IMAGE_PATH="$BANAN_BUILD_DIR/banan-os.img"
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,13 @@ if [ -z $BANAN_DISK_IMAGE_PATH ]; then
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z $BANAN_SYSROOT_TAR ]; then
|
if [ -z $BANAN_SYSROOT ]; then
|
||||||
echo "You must set the BANAN_SYSROOT_TAR environment variable" >&2
|
echo "You must set the BANAN_SYSROOT environment variable" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z $BANAN_FAKEROOT ]; then
|
||||||
|
echo "You must set the BANAN_FAKEROOT environment variable" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -34,13 +39,33 @@ fi
|
||||||
|
|
||||||
if sudo mount $ROOT_PARTITION $MOUNT_DIR; then
|
if sudo mount $ROOT_PARTITION $MOUNT_DIR; then
|
||||||
if (($BANAN_INITRD)); then
|
if (($BANAN_INITRD)); then
|
||||||
|
fakeroot -i $BANAN_FAKEROOT tar -C $BANAN_SYSROOT -cf $BANAN_SYSROOT.initrd .
|
||||||
|
|
||||||
sudo mkdir -p $MOUNT_DIR/boot
|
sudo mkdir -p $MOUNT_DIR/boot
|
||||||
sudo cp $BANAN_BUILD_DIR/kernel/banan-os.kernel $MOUNT_DIR/boot/banan-os.kernel
|
sudo cp $BANAN_BUILD_DIR/kernel/banan-os.kernel $MOUNT_DIR/boot/banan-os.kernel
|
||||||
sudo cp $BANAN_SYSROOT_TAR $MOUNT_DIR/boot/banan-os.initrd
|
sudo mv $BANAN_SYSROOT.initrd $MOUNT_DIR/boot/banan-os.initrd
|
||||||
else
|
else
|
||||||
cd $MOUNT_DIR
|
sudo rsync -rulHpt $BANAN_SYSROOT/ $MOUNT_DIR
|
||||||
sudo tar xf $BANAN_SYSROOT_TAR
|
|
||||||
cd
|
fakeroot -i $BANAN_FAKEROOT find $BANAN_SYSROOT -printf './%P|%U|%G\n' >$BANAN_BUILD_DIR/sysroot-perms.txt
|
||||||
|
sudo bash -c "
|
||||||
|
if enable stat &>/dev/null; then
|
||||||
|
while IFS='|' read -r path uid gid; do
|
||||||
|
full=\"$MOUNT_DIR/\$path\"
|
||||||
|
stat \"\$full\"
|
||||||
|
if [[ \${STAT[uid]} != \$uid ]] || [[ \${STAT[gid]} != \$gid ]]; then
|
||||||
|
chown -h \"\$uid:\$gid\" \"\$full\"
|
||||||
|
fi
|
||||||
|
done <$BANAN_BUILD_DIR/sysroot-perms.txt
|
||||||
|
else
|
||||||
|
while IFS='|' read -r path uid gid; do
|
||||||
|
full=\"$MOUNT_DIR/\$path\"
|
||||||
|
if [[ \$(stat -c '%u %g' \"\$full\") != \"\$uid \$gid\" ]]; then
|
||||||
|
chown -h \"\$uid:\$gid\" \"\$full\"
|
||||||
|
fi
|
||||||
|
done <$BANAN_BUILD_DIR/sysroot-perms.txt
|
||||||
|
fi
|
||||||
|
"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
sudo umount $MOUNT_DIR
|
sudo umount $MOUNT_DIR
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
*/
|
local/
|
||||||
|
|
|
@ -8,15 +8,10 @@ if (NOT DEFINED ENV{BANAN_SYSROOT})
|
||||||
endif ()
|
endif ()
|
||||||
set(BANAN_SYSROOT $ENV{BANAN_SYSROOT})
|
set(BANAN_SYSROOT $ENV{BANAN_SYSROOT})
|
||||||
|
|
||||||
if (NOT DEFINED ENV{BANAN_SYSROOT_TAR})
|
if (NOT DEFINED ENV{BANAN_TOOLCHAIN_PREFIX})
|
||||||
message(FATAL_ERROR "environment variable BANAN_SYSROOT_TAR not defined")
|
message(FATAL_ERROR "environment variable BANAN_TOOLCHAIN_PREFIX not defined")
|
||||||
endif ()
|
endif ()
|
||||||
set(BANAN_SYSROOT_TAR $ENV{BANAN_SYSROOT_TAR})
|
set(TOOLCHAIN_PREFIX $ENV{BANAN_TOOLCHAIN_PREFIX})
|
||||||
|
|
||||||
if (NOT DEFINED ENV{BANAN_ROOT_DIR})
|
|
||||||
message(FATAL_ERROR "environment variable BANAN_ROOT_DIR not defined")
|
|
||||||
endif ()
|
|
||||||
set(TOOLCHAIN_PREFIX $ENV{BANAN_ROOT_DIR}/toolchain/local)
|
|
||||||
|
|
||||||
set(CMAKE_SYSTEM_NAME banan-os)
|
set(CMAKE_SYSTEM_NAME banan-os)
|
||||||
set(CMAKE_SYSTEM_PROCESSOR ${BANAN_ARCH})
|
set(CMAKE_SYSTEM_PROCESSOR ${BANAN_ARCH})
|
||||||
|
|
|
@ -193,6 +193,8 @@ build_cmake() {
|
||||||
|
|
||||||
cp -r ./bin/* $BANAN_TOOLCHAIN_PREFIX/bin/
|
cp -r ./bin/* $BANAN_TOOLCHAIN_PREFIX/bin/
|
||||||
cp -r ./share/* $BANAN_TOOLCHAIN_PREFIX/share/
|
cp -r ./share/* $BANAN_TOOLCHAIN_PREFIX/share/
|
||||||
|
|
||||||
|
cp $BANAN_TOOLCHAIN_DIR/cmake-platform/* $BANAN_TOOLCHAIN_PREFIX/share/cmake-3.26/Modules/Platform/
|
||||||
}
|
}
|
||||||
|
|
||||||
BUILD_BINUTILS=1
|
BUILD_BINUTILS=1
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
include(Platform/banan-os-GNU)
|
||||||
|
__banan_os_compiler_gnu(ASM)
|
|
@ -0,0 +1,2 @@
|
||||||
|
include(Platform/banan-os-GNU)
|
||||||
|
__banan_os_compiler_gnu(C)
|
|
@ -0,0 +1,2 @@
|
||||||
|
include(Platform/banan-os-GNU)
|
||||||
|
__banan_os_compiler_gnu(CXX)
|
|
@ -0,0 +1,20 @@
|
||||||
|
# This module is shared by multiple languages; use include blocker.
|
||||||
|
include_guard()
|
||||||
|
|
||||||
|
macro(__banan_os_compiler_gnu lang)
|
||||||
|
set(CMAKE_SHARED_LIBRARY_RUNTIME_${lang}_FLAG "-Wl,-rpath,")
|
||||||
|
set(CMAKE_SHARED_LIBRARY_RUNTIME_${lang}_FLAG_SEP ":")
|
||||||
|
set(CMAKE_SHARED_LIBRARY_RPATH_LINK_${lang}_FLAG "-Wl,-rpath-link,")
|
||||||
|
set(CMAKE_SHARED_LIBRARY_SONAME_${lang}_FLAG "-Wl,-soname,")
|
||||||
|
set(CMAKE_EXE_EXPORTS_${lang}_FLAG "-Wl,--export-dynamic")
|
||||||
|
|
||||||
|
# Initialize link type selection flags. These flags are used when
|
||||||
|
# building a shared library, shared module, or executable that links
|
||||||
|
# to other libraries to select whether to use the static or shared
|
||||||
|
# versions of the libraries.
|
||||||
|
foreach(type SHARED_LIBRARY SHARED_MODULE EXE)
|
||||||
|
set(CMAKE_${type}_LINK_STATIC_${lang}_FLAGS "-Wl,-Bstatic")
|
||||||
|
set(CMAKE_${type}_LINK_DYNAMIC_${lang}_FLAGS "-Wl,-Bdynamic")
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
endmacro()
|
|
@ -0,0 +1,2 @@
|
||||||
|
set(BANAN_OS 1)
|
||||||
|
set(UNIX 1)
|
|
@ -0,0 +1,9 @@
|
||||||
|
set(CMAKE_DL_LIBS "")
|
||||||
|
set(CMAKE_SHARED_LIBRARY_RPATH_ORIGIN_TOKEN "\$ORIGIN")
|
||||||
|
set(CMAKE_SHARED_LIBRARY_SUFFIX ".so")
|
||||||
|
|
||||||
|
# Shared libraries with no builtin soname may not be linked safely by
|
||||||
|
# specifying the file path.
|
||||||
|
set(CMAKE_PLATFORM_USES_PATH_WHEN_NO_SONAME 1)
|
||||||
|
|
||||||
|
include(Platform/UnixPaths)
|
|
@ -11,7 +11,8 @@ ar = 'ARCH-pc-banan_os-ar'
|
||||||
ld = 'ARCH-pc-banan_os-ld'
|
ld = 'ARCH-pc-banan_os-ld'
|
||||||
objcopy = 'ARCH-pc-banan_os-objcopy'
|
objcopy = 'ARCH-pc-banan_os-objcopy'
|
||||||
strip = 'ARCH-pc-banan_os-strip'
|
strip = 'ARCH-pc-banan_os-strip'
|
||||||
pkgconfig = 'pkg-config'
|
pkg-config = 'pkg-config'
|
||||||
|
cmake = 'CMAKE'
|
||||||
|
|
||||||
[properties]
|
[properties]
|
||||||
sys_root='SYSROOT'
|
sys_root='SYSROOT'
|
||||||
|
|
|
@ -20,6 +20,7 @@ set(LIBC_SOURCES
|
||||||
malloc.cpp
|
malloc.cpp
|
||||||
math.cpp
|
math.cpp
|
||||||
netdb.cpp
|
netdb.cpp
|
||||||
|
netinet/in.cpp
|
||||||
poll.cpp
|
poll.cpp
|
||||||
printf_impl.cpp
|
printf_impl.cpp
|
||||||
pthread.cpp
|
pthread.cpp
|
||||||
|
@ -35,6 +36,7 @@ set(LIBC_SOURCES
|
||||||
sys/banan-os.cpp
|
sys/banan-os.cpp
|
||||||
sys/epoll.cpp
|
sys/epoll.cpp
|
||||||
sys/file.cpp
|
sys/file.cpp
|
||||||
|
sys/futex.cpp
|
||||||
sys/ioctl.cpp
|
sys/ioctl.cpp
|
||||||
sys/mman.cpp
|
sys/mman.cpp
|
||||||
sys/resource.cpp
|
sys/resource.cpp
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
@ -109,3 +110,54 @@ void rewinddir(DIR* dirp)
|
||||||
dirp->entry_index = 0;
|
dirp->entry_index = 0;
|
||||||
lseek(dirp->fd, 0, SEEK_SET);
|
lseek(dirp->fd, 0, SEEK_SET);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int alphasort(const struct dirent** d1, const struct dirent** d2)
|
||||||
|
{
|
||||||
|
return strcoll((*d1)->d_name, (*d2)->d_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
int scandir(const char* dir, struct dirent*** namelist, int (*sel)(const struct dirent*), int (*compar)(const struct dirent**, const struct dirent**))
|
||||||
|
{
|
||||||
|
DIR* dirp = opendir(dir);
|
||||||
|
if (dirp == nullptr)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
size_t count = 0;
|
||||||
|
dirent** list = nullptr;
|
||||||
|
|
||||||
|
dirent* dent;
|
||||||
|
while ((dent = readdir(dirp)))
|
||||||
|
{
|
||||||
|
if (sel && sel(dent) == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
void* new_list = realloc(list, (count + 1) * sizeof(dirent*));
|
||||||
|
if (new_list == nullptr)
|
||||||
|
goto scandir_error;
|
||||||
|
|
||||||
|
list = static_cast<dirent**>(new_list);
|
||||||
|
list[count] = static_cast<dirent*>(malloc(sizeof(dirent)));
|
||||||
|
if (list[count] == nullptr)
|
||||||
|
goto scandir_error;
|
||||||
|
|
||||||
|
memcpy(list[count], dent, sizeof(dirent));
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(dirp);
|
||||||
|
|
||||||
|
qsort(list, count, sizeof(dirent*), reinterpret_cast<int(*)(const void*, const void*)>(compar));
|
||||||
|
|
||||||
|
*namelist = list;
|
||||||
|
return count;
|
||||||
|
|
||||||
|
scandir_error:
|
||||||
|
closedir(dirp);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < count; i++)
|
||||||
|
free(list[i]);
|
||||||
|
free(list);
|
||||||
|
|
||||||
|
*namelist = nullptr;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
extern uthread* _get_uthread();
|
|
||||||
|
|
||||||
int* __errno_location()
|
int* __errno_location()
|
||||||
{
|
{
|
||||||
return &_get_uthread()->errno_;
|
return &_get_uthread()->errno_;
|
||||||
|
|
|
@ -1,162 +1,213 @@
|
||||||
#include <BAN/StringView.h>
|
|
||||||
#include <BAN/Vector.h>
|
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
|
||||||
#include <grp.h>
|
#include <grp.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/mman.h>
|
#include <string.h>
|
||||||
#include <sys/types.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
static struct stat s_group_st;
|
static FILE* s_grent_fp = nullptr;
|
||||||
static char* s_group_mmap = nullptr;
|
static group s_grent_struct;
|
||||||
static int s_group_fd = -1;
|
|
||||||
|
|
||||||
static struct group s_group;
|
static char* s_grent_buffer = nullptr;
|
||||||
|
static size_t s_grent_buffer_size = 0;
|
||||||
|
|
||||||
id_t parse_id(BAN::StringView string)
|
void endgrent(void)
|
||||||
{
|
{
|
||||||
id_t id = 0;
|
if (s_grent_fp)
|
||||||
for (char c : string)
|
fclose(s_grent_fp);
|
||||||
{
|
s_grent_fp = nullptr;
|
||||||
if (!isdigit(c))
|
|
||||||
return -1;
|
if (s_grent_buffer)
|
||||||
id = (id * 10) + (c - '0');
|
free(s_grent_buffer);
|
||||||
}
|
s_grent_buffer = nullptr;
|
||||||
return id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool open_group_file()
|
void setgrent(void)
|
||||||
{
|
{
|
||||||
if (s_group_fd == -1)
|
if (!s_grent_fp)
|
||||||
s_group_fd = open("/etc/group", O_RDONLY);
|
return;
|
||||||
if (s_group_fd == -1)
|
fseek(s_grent_fp, 0, SEEK_SET);
|
||||||
return false;
|
|
||||||
|
|
||||||
if (fstat(s_group_fd, &s_group_st) == -1)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (s_group_mmap == nullptr || s_group_mmap == MAP_FAILED)
|
|
||||||
s_group_mmap = (char*)mmap(nullptr, s_group_st.st_size, PROT_READ, MAP_PRIVATE, s_group_fd, 0);
|
|
||||||
if (s_group_mmap == MAP_FAILED)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
s_group.gr_name = nullptr;
|
|
||||||
s_group.gr_mem = nullptr;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct group* fill_group(const BAN::Vector<BAN::StringView>& parts)
|
static int getgrent_impl(FILE* fp, struct group* grp, char* buffer, size_t bufsize, struct group** result)
|
||||||
{
|
{
|
||||||
if (parts.size() != 4)
|
for (;;)
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
if (s_group.gr_name)
|
|
||||||
{
|
{
|
||||||
free(s_group.gr_name);
|
if (fgets(buffer, bufsize, fp) == nullptr)
|
||||||
s_group.gr_name = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s_group.gr_mem)
|
|
||||||
{
|
|
||||||
for (size_t i = 0; s_group.gr_mem && s_group.gr_mem[i]; i++)
|
|
||||||
free(s_group.gr_mem[i]);
|
|
||||||
free(s_group.gr_mem);
|
|
||||||
s_group.gr_mem = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto groups_or_error = parts[3].split(',');
|
|
||||||
if (groups_or_error.is_error())
|
|
||||||
return nullptr;
|
|
||||||
auto groups = groups_or_error.release_value();
|
|
||||||
|
|
||||||
s_group.gr_gid = parse_id(parts[2]);
|
|
||||||
if (s_group.gr_gid == -1)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
s_group.gr_name = (char*)malloc(parts[0].size() + 1);
|
|
||||||
if (s_group.gr_name == nullptr)
|
|
||||||
return nullptr;
|
|
||||||
memcpy(s_group.gr_name, parts[0].data(), parts[0].size());
|
|
||||||
s_group.gr_name[parts[0].size()] = '\0';
|
|
||||||
|
|
||||||
s_group.gr_mem = (char**)malloc((groups.size() + 1) * sizeof(char*));
|
|
||||||
if (s_group.gr_mem == nullptr)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < groups.size(); i++)
|
|
||||||
{
|
|
||||||
s_group.gr_mem[i] = (char*)malloc(groups[i].size() + 1);
|
|
||||||
if (s_group.gr_mem[i] == nullptr)
|
|
||||||
{
|
{
|
||||||
for (size_t j = 0; j < i; j++)
|
if (ferror(fp))
|
||||||
free(s_group.gr_mem[j]);
|
return errno;
|
||||||
free(s_group.gr_mem);
|
*result = nullptr;
|
||||||
s_group.gr_mem = nullptr;
|
return 0;
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
memcpy(s_group.gr_mem[i], groups[i].data(), groups[i].size());
|
|
||||||
s_group.gr_mem[i][groups[i].size()] = '\0';
|
|
||||||
}
|
|
||||||
s_group.gr_mem[groups.size()] = nullptr;
|
|
||||||
|
|
||||||
return &s_group;
|
const size_t line_len = strlen(buffer);
|
||||||
|
if (line_len == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (buffer[line_len - 1] == '\n')
|
||||||
|
buffer[line_len - 1] = '\0';
|
||||||
|
else if (!feof(fp))
|
||||||
|
return (errno = ERANGE);
|
||||||
|
|
||||||
|
#define GET_STRING() ({ \
|
||||||
|
ptr = strchr(ptr, ':'); \
|
||||||
|
if (ptr == nullptr) \
|
||||||
|
continue; \
|
||||||
|
*ptr++ = '\0'; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define GET_INT() ({ \
|
||||||
|
if (!isdigit(*ptr)) \
|
||||||
|
continue; \
|
||||||
|
long val = 0; \
|
||||||
|
while (isdigit(*ptr)) \
|
||||||
|
val = (val * 10) + (*ptr++ - '0'); \
|
||||||
|
if (*ptr != ':') \
|
||||||
|
continue; \
|
||||||
|
*ptr++ = '\0'; \
|
||||||
|
val; \
|
||||||
|
})
|
||||||
|
|
||||||
|
char* ptr = buffer;
|
||||||
|
|
||||||
|
grp->gr_name = ptr;
|
||||||
|
GET_STRING();
|
||||||
|
|
||||||
|
grp->gr_passwd = ptr;
|
||||||
|
GET_STRING();
|
||||||
|
|
||||||
|
grp->gr_gid = GET_INT();
|
||||||
|
|
||||||
|
size_t offset = line_len + 1;
|
||||||
|
if (auto rem = offset % alignof(char*))
|
||||||
|
offset += alignof(char*) - rem;
|
||||||
|
grp->gr_mem = reinterpret_cast<char**>(buffer + offset);
|
||||||
|
|
||||||
|
const size_t mem_max = (bufsize - offset) / sizeof(char*);
|
||||||
|
size_t mem_idx = 0;
|
||||||
|
|
||||||
|
while (*ptr && mem_idx + 1 <= mem_max)
|
||||||
|
{
|
||||||
|
grp->gr_mem[mem_idx++] = ptr;
|
||||||
|
|
||||||
|
ptr = strchrnul(ptr, ',');
|
||||||
|
if (*ptr == ',')
|
||||||
|
*ptr++ = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mem_idx + 1 > mem_max)
|
||||||
|
return (errno = ERANGE);
|
||||||
|
|
||||||
|
grp->gr_mem[mem_idx] = nullptr;
|
||||||
|
*result = grp;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct group* getgrnam(const char* name)
|
struct group* getgrent(void)
|
||||||
{
|
{
|
||||||
if (s_group_mmap == nullptr || s_group_mmap == MAP_FAILED)
|
if (s_grent_fp == nullptr)
|
||||||
if (!open_group_file())
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
off_t start = 0;
|
|
||||||
off_t end = 0;
|
|
||||||
while (start < s_group_st.st_size)
|
|
||||||
{
|
{
|
||||||
while (end < s_group_st.st_size && s_group_mmap[end] != '\n')
|
s_grent_fp = fopen("/etc/group", "r");
|
||||||
end++;
|
if (s_grent_fp == nullptr)
|
||||||
|
|
||||||
BAN::StringView line(s_group_mmap + start, end - start);
|
|
||||||
start = ++end;
|
|
||||||
|
|
||||||
auto parts_or_error = line.split(':', true);
|
|
||||||
if (parts_or_error.is_error())
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
auto parts = parts_or_error.release_value();
|
|
||||||
if (parts.size() == 4 && parts[0] == name)
|
|
||||||
return fill_group(parts);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
if (s_grent_buffer == nullptr)
|
||||||
|
{
|
||||||
|
long size = sysconf(_SC_GETGR_R_SIZE_MAX);
|
||||||
|
if (size == -1)
|
||||||
|
size = 512;
|
||||||
|
|
||||||
|
s_grent_buffer = static_cast<char*>(malloc(size));
|
||||||
|
if (s_grent_buffer == nullptr)
|
||||||
|
return nullptr;
|
||||||
|
s_grent_buffer_size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
const off_t old_offset = ftello(s_grent_fp);
|
||||||
|
|
||||||
|
group* result;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
const int error = getgrent_impl(s_grent_fp, &s_grent_struct, s_grent_buffer, s_grent_buffer_size, &result);
|
||||||
|
if (error == 0)
|
||||||
|
break;
|
||||||
|
fseeko(s_grent_fp, old_offset, SEEK_SET);
|
||||||
|
if (error != ERANGE)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
const size_t new_size = s_grent_buffer_size * 2;
|
||||||
|
char* new_buffer = static_cast<char*>(realloc(s_grent_buffer, new_size));
|
||||||
|
if (new_buffer == nullptr)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
s_grent_buffer = new_buffer;
|
||||||
|
s_grent_buffer_size = new_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct group* getgrgid(gid_t gid)
|
struct group* getgrgid(gid_t gid)
|
||||||
{
|
{
|
||||||
if (s_group_mmap == nullptr || s_group_mmap == MAP_FAILED)
|
group* grp;
|
||||||
if (!open_group_file())
|
setgrent();
|
||||||
return nullptr;
|
while ((grp = getgrent()))
|
||||||
|
if (grp->gr_gid == gid)
|
||||||
off_t start = 0;
|
return grp;
|
||||||
off_t end = 0;
|
|
||||||
while (start < s_group_st.st_size)
|
|
||||||
{
|
|
||||||
while (end < s_group_st.st_size && s_group_mmap[end] != '\n')
|
|
||||||
end++;
|
|
||||||
|
|
||||||
BAN::StringView line(s_group_mmap + start, end - start);
|
|
||||||
start = ++end;
|
|
||||||
|
|
||||||
auto parts_or_error = line.split(':', true);
|
|
||||||
if (parts_or_error.is_error())
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
auto parts = parts_or_error.release_value();
|
|
||||||
if (parts.size() == 4 && parse_id(parts[2]) == gid)
|
|
||||||
return fill_group(parts);
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct group* getgrnam(const char* name)
|
||||||
|
{
|
||||||
|
group* grp;
|
||||||
|
setgrent();
|
||||||
|
while ((grp = getgrent()))
|
||||||
|
if (strcmp(grp->gr_name, name) == 0)
|
||||||
|
return grp;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getgrgid_r(gid_t gid, struct group* grp, char* buffer, size_t bufsize, struct group** result)
|
||||||
|
{
|
||||||
|
FILE* fp = fopen("/etc/group", "r");
|
||||||
|
if (fp == nullptr)
|
||||||
|
return errno;
|
||||||
|
|
||||||
|
int ret = 0;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if ((ret = getgrent_impl(fp, grp, buffer, bufsize, result)))
|
||||||
|
break;
|
||||||
|
if (*result == nullptr)
|
||||||
|
break;
|
||||||
|
if (grp->gr_gid == gid)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getgrnam_r(const char* name, struct group* grp, char* buffer, size_t bufsize, struct group** result)
|
||||||
|
{
|
||||||
|
FILE* fp = fopen("/etc/group", "r");
|
||||||
|
if (fp == nullptr)
|
||||||
|
return errno;
|
||||||
|
|
||||||
|
int ret = 0;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if ((ret = getgrent_impl(fp, grp, buffer, bufsize, result)))
|
||||||
|
break;
|
||||||
|
if (*result == nullptr)
|
||||||
|
break;
|
||||||
|
if (strcmp(grp->gr_name, name) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#include <stddef.h>
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
struct atexit_func_entry_t
|
struct atexit_func_entry_t
|
||||||
{
|
{
|
||||||
|
@ -8,19 +10,52 @@ struct atexit_func_entry_t
|
||||||
void* dso_handle;
|
void* dso_handle;
|
||||||
};
|
};
|
||||||
|
|
||||||
static atexit_func_entry_t s_atexit_funcs[ATEXIT_MAX];
|
static atexit_func_entry_t s_atexit_funcs_storage[ATEXIT_MAX];
|
||||||
|
static atexit_func_entry_t* s_atexit_funcs = s_atexit_funcs_storage;
|
||||||
|
static size_t s_atexit_funcs_capacity = ATEXIT_MAX;
|
||||||
static size_t s_atexit_func_count = 0;
|
static size_t s_atexit_func_count = 0;
|
||||||
|
static pthread_mutex_t s_atexit_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
|
||||||
extern "C" int __cxa_atexit(void(*func)(void*), void* arg, void* dso_handle)
|
extern "C" int __cxa_atexit(void(*func)(void*), void* arg, void* dso_handle)
|
||||||
{
|
{
|
||||||
if (s_atexit_func_count >= ATEXIT_MAX)
|
pthread_mutex_lock(&s_atexit_mutex);
|
||||||
return -1;
|
|
||||||
|
if (s_atexit_func_count >= s_atexit_funcs_capacity)
|
||||||
|
{
|
||||||
|
const size_t new_capacity = s_atexit_funcs_capacity * 2;
|
||||||
|
|
||||||
|
void* new_funcs = nullptr;
|
||||||
|
|
||||||
|
if (s_atexit_funcs == s_atexit_funcs_storage)
|
||||||
|
{
|
||||||
|
new_funcs = malloc(new_capacity * sizeof(atexit_func_entry_t));
|
||||||
|
if (new_funcs == nullptr)
|
||||||
|
goto __cxa_atexit_error;
|
||||||
|
memcpy(new_funcs, s_atexit_funcs, s_atexit_func_count * sizeof(atexit_func_entry_t));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
new_funcs = realloc(s_atexit_funcs, new_capacity * sizeof(atexit_func_entry_t));
|
||||||
|
if (new_funcs == nullptr)
|
||||||
|
goto __cxa_atexit_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
s_atexit_funcs = reinterpret_cast<atexit_func_entry_t*>(new_funcs);
|
||||||
|
s_atexit_funcs_capacity = new_capacity;
|
||||||
|
}
|
||||||
|
|
||||||
s_atexit_funcs[s_atexit_func_count++] = {
|
s_atexit_funcs[s_atexit_func_count++] = {
|
||||||
.func = func,
|
.func = func,
|
||||||
.arg = arg,
|
.arg = arg,
|
||||||
.dso_handle = dso_handle,
|
.dso_handle = dso_handle,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&s_atexit_mutex);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
__cxa_atexit_error:
|
||||||
|
pthread_mutex_unlock(&s_atexit_mutex);
|
||||||
|
return -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern "C" void __cxa_finalize(void* dso_handle)
|
extern "C" void __cxa_finalize(void* dso_handle)
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
__BEGIN_DECLS
|
__BEGIN_DECLS
|
||||||
|
|
||||||
#include <inttypes.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#define INET_ADDRSTRLEN 16
|
#define INET_ADDRSTRLEN 16
|
||||||
#define INET6_ADDRSTRLEN 46
|
#define INET6_ADDRSTRLEN 46
|
||||||
|
|
|
@ -10,6 +10,8 @@ __BEGIN_DECLS
|
||||||
#include <bits/types/pthread_attr_t.h>
|
#include <bits/types/pthread_attr_t.h>
|
||||||
#include <bits/types/pthread_t.h>
|
#include <bits/types/pthread_t.h>
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
typedef int pthread_once_t;
|
typedef int pthread_once_t;
|
||||||
|
|
||||||
typedef unsigned pthread_key_t;
|
typedef unsigned pthread_key_t;
|
||||||
|
@ -28,17 +30,6 @@ typedef struct
|
||||||
unsigned lock_depth;
|
unsigned lock_depth;
|
||||||
} pthread_mutex_t;
|
} 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
|
typedef struct
|
||||||
{
|
{
|
||||||
int clock;
|
int clock;
|
||||||
|
@ -47,7 +38,7 @@ typedef struct
|
||||||
struct _pthread_cond_block
|
struct _pthread_cond_block
|
||||||
{
|
{
|
||||||
struct _pthread_cond_block* next;
|
struct _pthread_cond_block* next;
|
||||||
int signaled;
|
uint32_t futex;
|
||||||
};
|
};
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
@ -56,6 +47,20 @@ typedef struct
|
||||||
struct _pthread_cond_block* block_list;
|
struct _pthread_cond_block* block_list;
|
||||||
} pthread_cond_t;
|
} pthread_cond_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int shared;
|
||||||
|
} pthread_barrierattr_t;
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
pthread_barrierattr_t attr;
|
||||||
|
pthread_mutex_t lock;
|
||||||
|
pthread_cond_t cond;
|
||||||
|
unsigned target;
|
||||||
|
unsigned waiting;
|
||||||
|
unsigned generation;
|
||||||
|
} pthread_barrier_t;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
int shared;
|
int shared;
|
||||||
|
|
|
@ -13,15 +13,16 @@ __BEGIN_DECLS
|
||||||
|
|
||||||
struct group
|
struct group
|
||||||
{
|
{
|
||||||
char* gr_name; /* The name of the group. */
|
char* gr_name; /* The name of the group. */
|
||||||
gid_t gr_gid; /* Numerical group ID. */
|
char* gr_passwd;/* The password of the group */
|
||||||
char** gr_mem; /* Pointer to a null-terminated array of character pointers to member names. */
|
gid_t gr_gid; /* Numerical group ID. */
|
||||||
|
char** gr_mem; /* Pointer to a null-terminated array of character pointers to member names. */
|
||||||
};
|
};
|
||||||
|
|
||||||
void endgrent(void);
|
void endgrent(void);
|
||||||
struct group* getgrent(void);
|
struct group* getgrent(void);
|
||||||
struct group* getgrgid(gid_t gid);
|
struct group* getgrgid(gid_t gid);
|
||||||
int getgrgit_r(gid_t gid, struct group* grp, char* buffer, size_t bufsize, struct group** result);
|
int getgrgid_r(gid_t gid, struct group* grp, char* buffer, size_t bufsize, struct group** result);
|
||||||
struct group* getgrnam(const char* name);
|
struct group* getgrnam(const char* name);
|
||||||
int getgrnam_r(const char* name, struct group* grp, char* buffer, size_t bufsize, struct group** result);
|
int getgrnam_r(const char* name, struct group* grp, char* buffer, size_t bufsize, struct group** result);
|
||||||
void setgrent(void);
|
void setgrent(void);
|
||||||
|
|
|
@ -79,7 +79,7 @@ __BEGIN_DECLS
|
||||||
#define LOGIN_NAME_MAX 256
|
#define LOGIN_NAME_MAX 256
|
||||||
#define MQ_OPEN_MAX _POSIX_MQ_OPEN_MAX
|
#define MQ_OPEN_MAX _POSIX_MQ_OPEN_MAX
|
||||||
#define MQ_PRIO_MAX _POSIX_MQ_PRIO_MAX
|
#define MQ_PRIO_MAX _POSIX_MQ_PRIO_MAX
|
||||||
#define OPEN_MAX 64
|
#define OPEN_MAX 128
|
||||||
#define PAGESIZE PAGE_SIZE
|
#define PAGESIZE PAGE_SIZE
|
||||||
#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS
|
#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS
|
||||||
#define PTHREAD_KEYS_MAX _POSIX_THREAD_KEYS_MAX
|
#define PTHREAD_KEYS_MAX _POSIX_THREAD_KEYS_MAX
|
||||||
|
|
|
@ -9,7 +9,6 @@ __BEGIN_DECLS
|
||||||
|
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <inttypes.h>
|
|
||||||
|
|
||||||
#define IPPORT_RESERVED 1024
|
#define IPPORT_RESERVED 1024
|
||||||
|
|
||||||
|
|
|
@ -87,6 +87,20 @@ struct uthread
|
||||||
#define _PTHREAD_ATFORK_CHILD 2
|
#define _PTHREAD_ATFORK_CHILD 2
|
||||||
void _pthread_call_atfork(int state);
|
void _pthread_call_atfork(int state);
|
||||||
|
|
||||||
|
#if defined(__x86_64__)
|
||||||
|
#define _get_uthread() ({ \
|
||||||
|
struct uthread* __tmp; \
|
||||||
|
asm volatile("movq %%fs:0, %0" : "=r"(__tmp)); \
|
||||||
|
__tmp; \
|
||||||
|
})
|
||||||
|
#elif defined(__i686__)
|
||||||
|
#define _get_uthread() ({ \
|
||||||
|
struct uthread* __tmp; \
|
||||||
|
asm volatile("movl %%gs:0, %0" : "=r"(__tmp)); \
|
||||||
|
__tmp; \
|
||||||
|
})
|
||||||
|
#endif
|
||||||
|
|
||||||
int pthread_atfork(void (*prepare)(void), void (*parent)(void), void(*child)(void));
|
int pthread_atfork(void (*prepare)(void), void (*parent)(void), void(*child)(void));
|
||||||
int pthread_attr_destroy(pthread_attr_t* attr);
|
int pthread_attr_destroy(pthread_attr_t* attr);
|
||||||
int pthread_attr_getdetachstate(const pthread_attr_t* attr, int* detachstate);
|
int pthread_attr_getdetachstate(const pthread_attr_t* attr, int* detachstate);
|
||||||
|
|
|
@ -134,8 +134,9 @@ struct sigevent
|
||||||
#define SA_NODEFER 0x040
|
#define SA_NODEFER 0x040
|
||||||
#define SS_ONSTACK 0x080
|
#define SS_ONSTACK 0x080
|
||||||
#define SS_DISABLE 0x100
|
#define SS_DISABLE 0x100
|
||||||
#define MINSIGSTKSZ 0x200
|
|
||||||
#define SIGSTKSZ 0x400
|
#define MINSIGSTKSZ 4096
|
||||||
|
#define SIGSTKSZ 4096
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
|
|
@ -44,6 +44,7 @@ void _Exit(int status) __attribute__((__noreturn__));
|
||||||
long a64l(const char* s);
|
long a64l(const char* s);
|
||||||
void abort(void) __attribute__((__noreturn__));
|
void abort(void) __attribute__((__noreturn__));
|
||||||
int abs(int i);
|
int abs(int i);
|
||||||
|
void* aligned_alloc(size_t alignment, size_t size);
|
||||||
int atexit(void (*func)(void));
|
int atexit(void (*func)(void));
|
||||||
double atof(const char* str);
|
double atof(const char* str);
|
||||||
int atoi(const char* str);
|
int atoi(const char* str);
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
#ifndef _SYS_FUTEX_H
|
||||||
|
#define _SYS_FUTEX_H 1
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
|
||||||
|
__BEGIN_DECLS
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#define FUTEX_WAIT 0
|
||||||
|
#define FUTEX_WAKE 1
|
||||||
|
#define FUTEX_PRIVATE 0x10
|
||||||
|
#define FUTEX_REALTIME 0x20
|
||||||
|
|
||||||
|
#define FUTEX_WAIT_PRIVATE (FUTEX_WAIT | FUTEX_PRIVATE)
|
||||||
|
#define FUTEX_WAKE_PRIVATE (FUTEX_WAKE | FUTEX_PRIVATE)
|
||||||
|
|
||||||
|
// op is one of FUTEX_WAIT or FUTEX_WAKE optionally or'ed with FUTEX_PRIVATE and/or FUTEX_REALTIME
|
||||||
|
//
|
||||||
|
// FUTEX_WAIT
|
||||||
|
// put current thread to sleep until *addr != value or until timeout occurs
|
||||||
|
// timeout is specified as a absolute time or NULL for indefinite wait
|
||||||
|
//
|
||||||
|
// FUTEX_WAKE
|
||||||
|
// signals waiting futexes to recheck *addr. at most value threads are woken up
|
||||||
|
//
|
||||||
|
// FUTEX_PRIVATE
|
||||||
|
// limit futex wait/wake events to the current process
|
||||||
|
//
|
||||||
|
// FUTEX_REALTIME
|
||||||
|
// abstime corresponds to CLOCK_REALTIME instead of the default CLOCK_MONOTONIC
|
||||||
|
//
|
||||||
|
// ERRORS
|
||||||
|
// ETIMEDOUT timeout occured
|
||||||
|
// EINVAL addr is not aligned on 4 byte boundary
|
||||||
|
// ENOSYS op contains unrecognized value
|
||||||
|
// EINTR function was interrupted
|
||||||
|
// ENOMEM not enough memory to allocate futex object
|
||||||
|
// EAGAIN *addr != value before thread was put to sleep
|
||||||
|
int futex(int op, const uint32_t* addr, uint32_t value, const struct timespec* abstime);
|
||||||
|
|
||||||
|
__END_DECLS
|
||||||
|
|
||||||
|
#endif
|
|
@ -16,6 +16,7 @@ __BEGIN_DECLS
|
||||||
#define MAP_PRIVATE 0x02
|
#define MAP_PRIVATE 0x02
|
||||||
#define MAP_SHARED 0x04
|
#define MAP_SHARED 0x04
|
||||||
#define MAP_ANONYMOUS 0x08
|
#define MAP_ANONYMOUS 0x08
|
||||||
|
#define MAP_ANON MAP_ANONYMOUS
|
||||||
|
|
||||||
#define MS_ASYNC 0x01
|
#define MS_ASYNC 0x01
|
||||||
#define MS_INVALIDATE 0x02
|
#define MS_INVALIDATE 0x02
|
||||||
|
|
|
@ -25,7 +25,7 @@ __BEGIN_DECLS
|
||||||
struct sockaddr
|
struct sockaddr
|
||||||
{
|
{
|
||||||
sa_family_t sa_family; /* Address family. */
|
sa_family_t sa_family; /* Address family. */
|
||||||
char sa_data[]; /* Socket address (variable-length data). */
|
char sa_data[0]; /* Socket address (variable-length data). */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sockaddr_storage
|
struct sockaddr_storage
|
||||||
|
|
|
@ -52,6 +52,7 @@ __BEGIN_DECLS
|
||||||
O(SYS_SYNC, sync) \
|
O(SYS_SYNC, sync) \
|
||||||
O(SYS_MMAP, mmap) \
|
O(SYS_MMAP, mmap) \
|
||||||
O(SYS_MUNMAP, munmap) \
|
O(SYS_MUNMAP, munmap) \
|
||||||
|
O(SYS_MPROTECT, mprotect) \
|
||||||
O(SYS_TTY_CTRL, tty_ctrl) \
|
O(SYS_TTY_CTRL, tty_ctrl) \
|
||||||
O(SYS_POWEROFF, poweroff) \
|
O(SYS_POWEROFF, poweroff) \
|
||||||
O(SYS_FCHMODAT, fchmodat) \
|
O(SYS_FCHMODAT, fchmodat) \
|
||||||
|
@ -108,6 +109,8 @@ __BEGIN_DECLS
|
||||||
O(SYS_EPOLL_CTL, epoll_ctl) \
|
O(SYS_EPOLL_CTL, epoll_ctl) \
|
||||||
O(SYS_EPOLL_PWAIT2, epoll_pwait2) \
|
O(SYS_EPOLL_PWAIT2, epoll_pwait2) \
|
||||||
O(SYS_FLOCK, flock) \
|
O(SYS_FLOCK, flock) \
|
||||||
|
O(SYS_GET_NPROCESSOR, get_nprocessor) \
|
||||||
|
O(SYS_FUTEX, futex) \
|
||||||
|
|
||||||
enum Syscall
|
enum Syscall
|
||||||
{
|
{
|
||||||
|
|
|
@ -342,6 +342,10 @@ enum
|
||||||
#define _SC_MQ_PRIO_MAX _SC_MQ_PRIO_MAX
|
#define _SC_MQ_PRIO_MAX _SC_MQ_PRIO_MAX
|
||||||
_SC_NGROUPS_MAX,
|
_SC_NGROUPS_MAX,
|
||||||
#define _SC_NGROUPS_MAX _SC_NGROUPS_MAX
|
#define _SC_NGROUPS_MAX _SC_NGROUPS_MAX
|
||||||
|
_SC_NPROCESSORS_CONF,
|
||||||
|
#define _SC_NPROCESSORS_CONF _SC_NPROCESSORS_CONF
|
||||||
|
_SC_NPROCESSORS_ONLN,
|
||||||
|
#define _SC_NPROCESSORS_ONLN _SC_NPROCESSORS_ONLN
|
||||||
_SC_OPEN_MAX,
|
_SC_OPEN_MAX,
|
||||||
#define _SC_OPEN_MAX _SC_OPEN_MAX
|
#define _SC_OPEN_MAX _SC_OPEN_MAX
|
||||||
_SC_PAGE_SIZE,
|
_SC_PAGE_SIZE,
|
||||||
|
|
|
@ -338,14 +338,14 @@ void* calloc(size_t nmemb, size_t size)
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
int posix_memalign(void** memptr, size_t alignment, size_t size)
|
void* aligned_alloc(size_t alignment, size_t size)
|
||||||
{
|
{
|
||||||
dprintln_if(DEBUG_MALLOC, "posix_memalign({}, {})", alignment, size);
|
dprintln_if(DEBUG_MALLOC, "aligned_alloc({}, {})", alignment, size);
|
||||||
|
|
||||||
if (alignment < sizeof(void*) || alignment % sizeof(void*) || !BAN::Math::is_power_of_two(alignment / sizeof(void*)))
|
if (alignment < sizeof(void*) || alignment % sizeof(void*) || !BAN::Math::is_power_of_two(alignment / sizeof(void*)))
|
||||||
{
|
{
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return -1;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (alignment < s_malloc_default_align)
|
if (alignment < s_malloc_default_align)
|
||||||
|
@ -353,7 +353,7 @@ int posix_memalign(void** memptr, size_t alignment, size_t size)
|
||||||
|
|
||||||
void* unaligned = malloc(size + alignment + sizeof(malloc_node_t));
|
void* unaligned = malloc(size + alignment + sizeof(malloc_node_t));
|
||||||
if (unaligned == nullptr)
|
if (unaligned == nullptr)
|
||||||
return -1;
|
return nullptr;
|
||||||
|
|
||||||
pthread_mutex_lock(&s_malloc_mutex);
|
pthread_mutex_lock(&s_malloc_mutex);
|
||||||
|
|
||||||
|
@ -395,6 +395,11 @@ int posix_memalign(void** memptr, size_t alignment, size_t size)
|
||||||
pthread_mutex_unlock(&s_malloc_mutex);
|
pthread_mutex_unlock(&s_malloc_mutex);
|
||||||
|
|
||||||
assert(((uintptr_t)node->data & (alignment - 1)) == 0);
|
assert(((uintptr_t)node->data & (alignment - 1)) == 0);
|
||||||
*memptr = node->data;
|
return node->data;
|
||||||
return 0;
|
}
|
||||||
|
|
||||||
|
int posix_memalign(void** memptr, size_t alignment, size_t size)
|
||||||
|
{
|
||||||
|
dprintln_if(DEBUG_MALLOC, "posix_memalign({}, {})", alignment, size);
|
||||||
|
return (*memptr = aligned_alloc(alignment, size)) ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
#include <netinet/in.h>
|
||||||
|
|
||||||
|
const struct in6_addr in6addr_any = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||||
|
const struct in6_addr in6addr_loopback = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
|
|
@ -10,6 +10,7 @@
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <sys/futex.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
@ -54,17 +55,6 @@ extern "C" void _pthread_trampoline_cpp(void* arg)
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
uthread* _get_uthread()
|
|
||||||
{
|
|
||||||
uthread* result;
|
|
||||||
#if ARCH(x86_64)
|
|
||||||
asm volatile("movq %%fs:0, %0" : "=r"(result));
|
|
||||||
#elif ARCH(i686)
|
|
||||||
asm volatile("movl %%gs:0, %0" : "=r"(result));
|
|
||||||
#endif
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void free_uthread(uthread* uthread)
|
static void free_uthread(uthread* uthread)
|
||||||
{
|
{
|
||||||
if (uthread->dtv[0] == 0)
|
if (uthread->dtv[0] == 0)
|
||||||
|
@ -105,58 +95,95 @@ void pthread_cleanup_push(void (*routine)(void*), void* arg)
|
||||||
uthread->cleanup_stack = cleanup;
|
uthread->cleanup_stack = cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
static thread_local struct {
|
static thread_local struct
|
||||||
void* value;
|
|
||||||
void (*destructor)(void*);
|
|
||||||
} s_pthread_keys[PTHREAD_KEYS_MAX] {};
|
|
||||||
static thread_local uint8_t s_pthread_keys_allocated[(PTHREAD_KEYS_MAX + 7) / 8];
|
|
||||||
|
|
||||||
static inline bool is_pthread_key_allocated(pthread_key_t key)
|
|
||||||
{
|
{
|
||||||
if (key >= PTHREAD_KEYS_MAX)
|
void* value;
|
||||||
return false;
|
pthread_key_t key;
|
||||||
return s_pthread_keys_allocated[key / 8] & (1 << (key % 8));
|
} s_pthread_key_values[PTHREAD_KEYS_MAX] {};
|
||||||
}
|
|
||||||
|
static pthread_key_t s_pthread_key_current = 1;
|
||||||
|
static pthread_key_t s_pthread_key_map[PTHREAD_KEYS_MAX] {};
|
||||||
|
static void (*s_pthread_key_destructors[PTHREAD_KEYS_MAX])(void*) {};
|
||||||
|
static pthread_spinlock_t s_pthread_key_lock = PTHREAD_SPIN_INITIALIZER;
|
||||||
|
|
||||||
int pthread_key_create(pthread_key_t* key, void (*destructor)(void*))
|
int pthread_key_create(pthread_key_t* key, void (*destructor)(void*))
|
||||||
{
|
{
|
||||||
for (pthread_key_t i = 0; i < PTHREAD_KEYS_MAX; i++)
|
int ret = EAGAIN;
|
||||||
{
|
|
||||||
if (is_pthread_key_allocated(i))
|
|
||||||
continue;
|
|
||||||
s_pthread_keys[i].value = nullptr;
|
|
||||||
s_pthread_keys[i].destructor = destructor;
|
|
||||||
s_pthread_keys_allocated[i / 8] |= 1 << (i % 8);
|
|
||||||
*key = i;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return EAGAIN;
|
pthread_spin_lock(&s_pthread_key_lock);
|
||||||
|
for (size_t i = 0; i < PTHREAD_KEYS_MAX; i++)
|
||||||
|
{
|
||||||
|
if (s_pthread_key_map[i])
|
||||||
|
continue;
|
||||||
|
s_pthread_key_destructors[i] = destructor;
|
||||||
|
s_pthread_key_map[i] = *key = s_pthread_key_current++;
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pthread_spin_unlock(&s_pthread_key_lock);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pthread_key_delete(pthread_key_t key)
|
int pthread_key_delete(pthread_key_t key)
|
||||||
{
|
{
|
||||||
if (!is_pthread_key_allocated(key))
|
int ret = EINVAL;
|
||||||
return EINVAL;
|
|
||||||
s_pthread_keys[key].value = nullptr;
|
pthread_spin_lock(&s_pthread_key_lock);
|
||||||
s_pthread_keys[key].destructor = nullptr;
|
for (size_t i = 0; i < PTHREAD_KEYS_MAX; i++)
|
||||||
s_pthread_keys_allocated[key / 8] &= ~(1 << (key % 8));
|
{
|
||||||
return 0;
|
if (s_pthread_key_map[i] != key)
|
||||||
|
continue;
|
||||||
|
s_pthread_key_destructors[i] = nullptr;
|
||||||
|
s_pthread_key_map[i] = 0;
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pthread_spin_unlock(&s_pthread_key_lock);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* pthread_getspecific(pthread_key_t key)
|
void* pthread_getspecific(pthread_key_t key)
|
||||||
{
|
{
|
||||||
if (!is_pthread_key_allocated(key))
|
void* ret = nullptr;
|
||||||
return nullptr;
|
|
||||||
return s_pthread_keys[key].value;
|
pthread_spin_lock(&s_pthread_key_lock);
|
||||||
|
for (size_t i = 0; i < PTHREAD_KEYS_MAX; i++)
|
||||||
|
{
|
||||||
|
if (s_pthread_key_map[i] != key)
|
||||||
|
continue;
|
||||||
|
if (s_pthread_key_values[i].key != key)
|
||||||
|
{
|
||||||
|
s_pthread_key_values[i].key = key;
|
||||||
|
s_pthread_key_values[i].value = nullptr;
|
||||||
|
}
|
||||||
|
ret = s_pthread_key_values[i].value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pthread_spin_unlock(&s_pthread_key_lock);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pthread_setspecific(pthread_key_t key, const void* value)
|
int pthread_setspecific(pthread_key_t key, const void* value)
|
||||||
{
|
{
|
||||||
if (!is_pthread_key_allocated(key))
|
int ret = EINVAL;
|
||||||
return EINVAL;
|
|
||||||
s_pthread_keys[key].value = const_cast<void*>(value);
|
pthread_spin_lock(&s_pthread_key_lock);
|
||||||
return 0;
|
for (size_t i = 0; i < PTHREAD_KEYS_MAX; i++)
|
||||||
|
{
|
||||||
|
if (s_pthread_key_map[i] != key)
|
||||||
|
continue;
|
||||||
|
if (s_pthread_key_values[i].key != key)
|
||||||
|
s_pthread_key_values[i].key = key;
|
||||||
|
s_pthread_key_values[i].value = const_cast<void*>(value);
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pthread_spin_unlock(&s_pthread_key_lock);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pthread_attr_destroy(pthread_attr_t* attr)
|
int pthread_attr_destroy(pthread_attr_t* attr)
|
||||||
|
@ -414,15 +441,22 @@ void pthread_exit(void* value_ptr)
|
||||||
for (size_t iteration = 0; iteration < PTHREAD_DESTRUCTOR_ITERATIONS; iteration++)
|
for (size_t iteration = 0; iteration < PTHREAD_DESTRUCTOR_ITERATIONS; iteration++)
|
||||||
{
|
{
|
||||||
bool called = false;
|
bool called = false;
|
||||||
for (pthread_key_t i = 0; i < PTHREAD_KEYS_MAX; i++)
|
for (size_t i = 0; i < PTHREAD_KEYS_MAX; i++)
|
||||||
{
|
{
|
||||||
if (!is_pthread_key_allocated(i))
|
void (*destructor)(void*) = nullptr;
|
||||||
|
void* value = nullptr;
|
||||||
|
|
||||||
|
pthread_spin_lock(&s_pthread_key_lock);
|
||||||
|
if (s_pthread_key_map[i] && s_pthread_key_values[i].key == s_pthread_key_map[i])
|
||||||
|
{
|
||||||
|
destructor = s_pthread_key_destructors[i];
|
||||||
|
value = s_pthread_key_values[i].value;
|
||||||
|
}
|
||||||
|
pthread_spin_unlock(&s_pthread_key_lock);
|
||||||
|
|
||||||
|
if (!value || !destructor)
|
||||||
continue;
|
continue;
|
||||||
if (!s_pthread_keys[i].value || !s_pthread_keys[i].destructor)
|
destructor(value);
|
||||||
continue;
|
|
||||||
void* old_value = s_pthread_keys[i].value;
|
|
||||||
s_pthread_keys[i].value = nullptr;
|
|
||||||
s_pthread_keys[i].destructor(old_value);
|
|
||||||
called = true;
|
called = true;
|
||||||
}
|
}
|
||||||
if (!called)
|
if (!called)
|
||||||
|
@ -442,7 +476,14 @@ int pthread_equal(pthread_t t1, pthread_t t2)
|
||||||
int pthread_join(pthread_t thread, void** value_ptr)
|
int pthread_join(pthread_t thread, void** value_ptr)
|
||||||
{
|
{
|
||||||
pthread_testcancel();
|
pthread_testcancel();
|
||||||
return syscall(SYS_PTHREAD_JOIN, thread, value_ptr);
|
|
||||||
|
errno = 0;
|
||||||
|
while (syscall(SYS_PTHREAD_JOIN, thread, value_ptr) == -1 && errno == EINTR)
|
||||||
|
{
|
||||||
|
pthread_testcancel();
|
||||||
|
errno = 0;
|
||||||
|
}
|
||||||
|
return errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_t pthread_self(void)
|
pthread_t pthread_self(void)
|
||||||
|
@ -478,6 +519,9 @@ static pthread_mutex_t s_atfork_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
|
||||||
void _pthread_call_atfork(int state)
|
void _pthread_call_atfork(int state)
|
||||||
{
|
{
|
||||||
|
if (state == _PTHREAD_ATFORK_CHILD)
|
||||||
|
_get_uthread()->id = syscall(SYS_PTHREAD_SELF);
|
||||||
|
|
||||||
pthread_mutex_lock(&s_atfork_mutex);
|
pthread_mutex_lock(&s_atfork_mutex);
|
||||||
|
|
||||||
pthread_atfork_t* list = nullptr;
|
pthread_atfork_t* list = nullptr;
|
||||||
|
@ -1070,7 +1114,12 @@ int pthread_cond_broadcast(pthread_cond_t* cond)
|
||||||
{
|
{
|
||||||
pthread_spin_lock(&cond->lock);
|
pthread_spin_lock(&cond->lock);
|
||||||
for (auto* block = cond->block_list; block; block = block->next)
|
for (auto* block = cond->block_list; block; block = block->next)
|
||||||
BAN::atomic_store(block->signaled, 1);
|
{
|
||||||
|
BAN::atomic_store(block->futex, 1);
|
||||||
|
|
||||||
|
const int op = FUTEX_WAKE | (cond->attr.shared ? 0 : FUTEX_PRIVATE);
|
||||||
|
futex(op, &block->futex, 1, nullptr);
|
||||||
|
}
|
||||||
pthread_spin_unlock(&cond->lock);
|
pthread_spin_unlock(&cond->lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1078,8 +1127,13 @@ int pthread_cond_broadcast(pthread_cond_t* cond)
|
||||||
int pthread_cond_signal(pthread_cond_t* cond)
|
int pthread_cond_signal(pthread_cond_t* cond)
|
||||||
{
|
{
|
||||||
pthread_spin_lock(&cond->lock);
|
pthread_spin_lock(&cond->lock);
|
||||||
if (cond->block_list)
|
if (auto* block = cond->block_list)
|
||||||
BAN::atomic_store(cond->block_list->signaled, 1);
|
{
|
||||||
|
BAN::atomic_store(block->futex, 1);
|
||||||
|
|
||||||
|
const int op = FUTEX_WAKE | (cond->attr.shared ? 0 : FUTEX_PRIVATE);
|
||||||
|
futex(op, &block->futex, 1, nullptr);
|
||||||
|
}
|
||||||
pthread_spin_unlock(&cond->lock);
|
pthread_spin_unlock(&cond->lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1094,35 +1148,26 @@ int pthread_cond_timedwait(pthread_cond_t* __restrict cond, pthread_mutex_t* __r
|
||||||
{
|
{
|
||||||
pthread_testcancel();
|
pthread_testcancel();
|
||||||
|
|
||||||
constexpr auto has_timed_out =
|
|
||||||
[](const struct timespec* abstime, clockid_t clock_id) -> bool
|
|
||||||
{
|
|
||||||
if (abstime == nullptr)
|
|
||||||
return false;
|
|
||||||
struct timespec curtime;
|
|
||||||
clock_gettime(clock_id, &curtime);
|
|
||||||
if (curtime.tv_sec < abstime->tv_sec)
|
|
||||||
return false;
|
|
||||||
if (curtime.tv_sec > abstime->tv_sec)
|
|
||||||
return true;
|
|
||||||
return curtime.tv_nsec >= abstime->tv_nsec;
|
|
||||||
};
|
|
||||||
|
|
||||||
pthread_spin_lock(&cond->lock);
|
pthread_spin_lock(&cond->lock);
|
||||||
_pthread_cond_block block = {
|
_pthread_cond_block block = {
|
||||||
.next = cond->block_list,
|
.next = cond->block_list,
|
||||||
.signaled = 0,
|
.futex = 0,
|
||||||
};
|
};
|
||||||
cond->block_list = █
|
cond->block_list = █
|
||||||
pthread_spin_unlock(&cond->lock);
|
pthread_spin_unlock(&cond->lock);
|
||||||
|
|
||||||
pthread_mutex_unlock(mutex);
|
pthread_mutex_unlock(mutex);
|
||||||
|
|
||||||
while (BAN::atomic_load(block.signaled) == 0)
|
while (BAN::atomic_load(block.futex) == 0)
|
||||||
{
|
{
|
||||||
if (has_timed_out(abstime, cond->attr.clock))
|
const int op = FUTEX_WAIT
|
||||||
|
| (cond->attr.shared ? 0 : FUTEX_PRIVATE)
|
||||||
|
| (cond->attr.clock == CLOCK_REALTIME ? FUTEX_REALTIME : 0);
|
||||||
|
if (futex(op, &block.futex, 0, abstime) == -1 && errno == ETIMEDOUT)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(mutex);
|
||||||
return ETIMEDOUT;
|
return ETIMEDOUT;
|
||||||
sched_yield();
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_spin_lock(&cond->lock);
|
pthread_spin_lock(&cond->lock);
|
||||||
|
@ -1192,28 +1237,34 @@ int pthread_barrier_init(pthread_barrier_t* __restrict barrier, const pthread_ba
|
||||||
attr = &default_attr;
|
attr = &default_attr;
|
||||||
*barrier = {
|
*barrier = {
|
||||||
.attr = *attr,
|
.attr = *attr,
|
||||||
|
.lock = PTHREAD_MUTEX_INITIALIZER,
|
||||||
|
.cond = PTHREAD_COND_INITIALIZER,
|
||||||
.target = count,
|
.target = count,
|
||||||
.waiting = 0,
|
.waiting = 0,
|
||||||
|
.generation = 0,
|
||||||
};
|
};
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pthread_barrier_wait(pthread_barrier_t* barrier)
|
int pthread_barrier_wait(pthread_barrier_t* barrier)
|
||||||
{
|
{
|
||||||
const unsigned index = BAN::atomic_add_fetch(barrier->waiting, 1);
|
pthread_mutex_lock(&barrier->lock);
|
||||||
|
|
||||||
// FIXME: this case should be handled, but should be relatively uncommon
|
const auto gen = barrier->generation;
|
||||||
// so i'll just roll with the easy implementation
|
barrier->waiting++;
|
||||||
ASSERT(index <= barrier->target);
|
|
||||||
|
|
||||||
if (index == barrier->target)
|
if (barrier->waiting == barrier->target)
|
||||||
{
|
{
|
||||||
BAN::atomic_store(barrier->waiting, 0);
|
barrier->waiting = 0;
|
||||||
|
barrier->generation++;
|
||||||
|
pthread_cond_broadcast(&barrier->cond);
|
||||||
|
pthread_mutex_unlock(&barrier->lock);
|
||||||
return PTHREAD_BARRIER_SERIAL_THREAD;
|
return PTHREAD_BARRIER_SERIAL_THREAD;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (BAN::atomic_load(barrier->waiting))
|
while (barrier->generation == gen)
|
||||||
sched_yield();
|
pthread_cond_wait(&barrier->cond, &barrier->lock);
|
||||||
|
pthread_mutex_unlock(&barrier->lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,118 +1,142 @@
|
||||||
#include <BAN/Assert.h>
|
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
static FILE* s_pwent_fp = nullptr;
|
static FILE* s_pwent_fp = nullptr;
|
||||||
static passwd s_pwent_struct;
|
static passwd s_pwent_struct;
|
||||||
|
|
||||||
static bool open_pwent()
|
static char* s_pwent_buffer = nullptr;
|
||||||
{
|
static size_t s_pwent_buffer_size = 0;
|
||||||
if (s_pwent_fp)
|
|
||||||
return true;
|
|
||||||
s_pwent_fp = fopen("/etc/passwd", "r");
|
|
||||||
return s_pwent_fp;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void clear_pwent(passwd& passwd)
|
|
||||||
{
|
|
||||||
if (passwd.pw_name)
|
|
||||||
free(passwd.pw_name);
|
|
||||||
passwd.pw_name = nullptr;
|
|
||||||
if (passwd.pw_dir)
|
|
||||||
free(passwd.pw_dir);
|
|
||||||
passwd.pw_dir = nullptr;
|
|
||||||
if (passwd.pw_shell)
|
|
||||||
free(passwd.pw_shell);
|
|
||||||
passwd.pw_shell = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void endpwent(void)
|
void endpwent(void)
|
||||||
|
{
|
||||||
|
if (s_pwent_fp)
|
||||||
|
fclose(s_pwent_fp);
|
||||||
|
s_pwent_fp = nullptr;
|
||||||
|
|
||||||
|
if (s_pwent_buffer)
|
||||||
|
free(s_pwent_buffer);
|
||||||
|
s_pwent_buffer = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setpwent(void)
|
||||||
{
|
{
|
||||||
if (!s_pwent_fp)
|
if (!s_pwent_fp)
|
||||||
return;
|
return;
|
||||||
fclose(s_pwent_fp);
|
fseek(s_pwent_fp, 0, SEEK_SET);
|
||||||
s_pwent_fp = nullptr;
|
}
|
||||||
clear_pwent(s_pwent_struct);
|
|
||||||
|
static int getpwent_impl(FILE* fp, struct passwd* pwd, char* buffer, size_t bufsize, struct passwd** result)
|
||||||
|
{
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (fgets(buffer, bufsize, fp) == nullptr)
|
||||||
|
{
|
||||||
|
if (ferror(fp))
|
||||||
|
return errno;
|
||||||
|
*result = nullptr;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t line_len = strlen(buffer);
|
||||||
|
if (line_len == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (buffer[line_len - 1] == '\n')
|
||||||
|
buffer[line_len - 1] = '\0';
|
||||||
|
else if (!feof(fp))
|
||||||
|
return (errno = ERANGE);
|
||||||
|
|
||||||
|
#define GET_STRING() ({ \
|
||||||
|
ptr = strchr(ptr, ':'); \
|
||||||
|
if (ptr == nullptr) \
|
||||||
|
continue; \
|
||||||
|
*ptr++ = '\0'; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define GET_INT() ({ \
|
||||||
|
if (!isdigit(*ptr)) \
|
||||||
|
continue; \
|
||||||
|
long val = 0; \
|
||||||
|
while (isdigit(*ptr)) \
|
||||||
|
val = (val * 10) + (*ptr++ - '0'); \
|
||||||
|
if (*ptr != ':') \
|
||||||
|
continue; \
|
||||||
|
*ptr++ = '\0'; \
|
||||||
|
val; \
|
||||||
|
})
|
||||||
|
|
||||||
|
char* ptr = buffer;
|
||||||
|
|
||||||
|
pwd->pw_name = ptr;
|
||||||
|
GET_STRING();
|
||||||
|
|
||||||
|
pwd->pw_passwd = ptr;
|
||||||
|
GET_STRING();
|
||||||
|
|
||||||
|
pwd->pw_uid = GET_INT();
|
||||||
|
|
||||||
|
pwd->pw_gid = GET_INT();
|
||||||
|
|
||||||
|
pwd->pw_gecos = ptr;
|
||||||
|
GET_STRING();
|
||||||
|
|
||||||
|
pwd->pw_dir = ptr;
|
||||||
|
GET_STRING();
|
||||||
|
|
||||||
|
pwd->pw_shell = ptr;
|
||||||
|
|
||||||
|
*result = pwd;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct passwd* getpwent(void)
|
struct passwd* getpwent(void)
|
||||||
{
|
{
|
||||||
if (!s_pwent_fp)
|
if (s_pwent_fp == nullptr)
|
||||||
if (!open_pwent())
|
|
||||||
return nullptr;
|
|
||||||
clear_pwent(s_pwent_struct);
|
|
||||||
|
|
||||||
static char buffer[4096];
|
|
||||||
if (!fgets(buffer, sizeof(buffer), s_pwent_fp))
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
size_t buffer_len = strlen(buffer);
|
|
||||||
|
|
||||||
ASSERT(buffer[buffer_len - 1] == '\n');
|
|
||||||
buffer[buffer_len - 1] = '\0';
|
|
||||||
buffer_len--;
|
|
||||||
|
|
||||||
const char* ptr = buffer;
|
|
||||||
for (int i = 0; i < 7; i++)
|
|
||||||
{
|
{
|
||||||
char* end = strchr(ptr, ':');
|
s_pwent_fp = fopen("/etc/passwd", "r");
|
||||||
ASSERT((i < 6) ? end != nullptr : end == nullptr);
|
if (s_pwent_fp == nullptr)
|
||||||
if (!end)
|
return nullptr;
|
||||||
end = buffer + buffer_len;
|
|
||||||
*end = '\0';
|
|
||||||
|
|
||||||
const size_t field_len = end - ptr;
|
|
||||||
|
|
||||||
switch (i)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
s_pwent_struct.pw_name = strndup(ptr, field_len + 1);
|
|
||||||
if (!s_pwent_struct.pw_name)
|
|
||||||
return nullptr;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
s_pwent_struct.pw_passwd = strndup(ptr, field_len + 1);
|
|
||||||
if (!s_pwent_struct.pw_passwd)
|
|
||||||
return nullptr;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
ASSERT(1 <= field_len && field_len <= 9);
|
|
||||||
for (size_t j = 0; j < field_len; j++)
|
|
||||||
ASSERT(isdigit(ptr[j]));
|
|
||||||
s_pwent_struct.pw_uid = atoi(ptr);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
ASSERT(1 <= field_len && field_len <= 9);
|
|
||||||
for (size_t j = 0; j < field_len; j++)
|
|
||||||
ASSERT(isdigit(ptr[j]));
|
|
||||||
s_pwent_struct.pw_gid = atoi(ptr);
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
s_pwent_struct.pw_gecos = strndup(ptr, field_len + 1);
|
|
||||||
if (!s_pwent_struct.pw_gecos)
|
|
||||||
return nullptr;
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
s_pwent_struct.pw_dir = strndup(ptr, field_len + 1);
|
|
||||||
if (!s_pwent_struct.pw_dir)
|
|
||||||
return nullptr;
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
s_pwent_struct.pw_shell = strndup(ptr, field_len + 1);
|
|
||||||
if (!s_pwent_struct.pw_shell)
|
|
||||||
return nullptr;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
ptr = end + 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return &s_pwent_struct;
|
if (s_pwent_buffer == nullptr)
|
||||||
|
{
|
||||||
|
long size = sysconf(_SC_GETPW_R_SIZE_MAX);
|
||||||
|
if (size == -1)
|
||||||
|
size = 512;
|
||||||
|
|
||||||
|
s_pwent_buffer = static_cast<char*>(malloc(size));
|
||||||
|
if (s_pwent_buffer == nullptr)
|
||||||
|
return nullptr;
|
||||||
|
s_pwent_buffer_size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
const off_t old_offset = ftello(s_pwent_fp);
|
||||||
|
|
||||||
|
passwd* result;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
const int error = getpwent_impl(s_pwent_fp, &s_pwent_struct, s_pwent_buffer, s_pwent_buffer_size, &result);
|
||||||
|
if (error == 0)
|
||||||
|
break;
|
||||||
|
fseeko(s_pwent_fp, old_offset, SEEK_SET);
|
||||||
|
if (error != ERANGE)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
const size_t new_size = s_pwent_buffer_size * 2;
|
||||||
|
char* new_buffer = static_cast<char*>(realloc(s_pwent_buffer, new_size));
|
||||||
|
if (new_buffer == nullptr)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
s_pwent_buffer = new_buffer;
|
||||||
|
s_pwent_buffer_size = new_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct passwd* getpwnam(const char* name)
|
struct passwd* getpwnam(const char* name)
|
||||||
|
@ -135,9 +159,44 @@ struct passwd* getpwuid(uid_t uid)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setpwent(void)
|
int getpwuid_r(uid_t uid, struct passwd* pwd, char* buffer, size_t bufsize, struct passwd** result)
|
||||||
{
|
{
|
||||||
if (!s_pwent_fp)
|
FILE* fp = fopen("/etc/passwd", "r");
|
||||||
return;
|
if (fp == nullptr)
|
||||||
fseek(s_pwent_fp, 0, SEEK_SET);
|
return errno;
|
||||||
|
|
||||||
|
int ret = 0;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if ((ret = getpwent_impl(fp, pwd, buffer, bufsize, result)))
|
||||||
|
break;
|
||||||
|
if (*result == nullptr)
|
||||||
|
break;
|
||||||
|
if (pwd->pw_uid == uid)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getpwnam_r(const char* name, struct passwd* pwd, char* buffer, size_t bufsize, struct passwd** result)
|
||||||
|
{
|
||||||
|
FILE* fp = fopen("/etc/passwd", "r");
|
||||||
|
if (fp == nullptr)
|
||||||
|
return errno;
|
||||||
|
|
||||||
|
int ret = 0;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if ((ret = getpwent_impl(fp, pwd, buffer, bufsize, result)))
|
||||||
|
break;
|
||||||
|
if (*result == nullptr)
|
||||||
|
break;
|
||||||
|
if (strcmp(pwd->pw_name, name) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -542,6 +542,9 @@ int getc_unlocked(FILE* file)
|
||||||
if (file->eof)
|
if (file->eof)
|
||||||
return EOF;
|
return EOF;
|
||||||
|
|
||||||
|
if (file == stdin && file->buffer_type == _IOLBF && stdout->buffer_type == _IOLBF && stdout->buffer_idx)
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
// read characters from ungetc
|
// read characters from ungetc
|
||||||
if (file->unget_buf_idx)
|
if (file->unget_buf_idx)
|
||||||
{
|
{
|
||||||
|
|
|
@ -570,6 +570,45 @@ int mblen(const char* s, size_t n)
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int mbtowc(wchar_t* __restrict pwc, const char* __restrict s, size_t n)
|
||||||
|
{
|
||||||
|
// no state-dependent encodings
|
||||||
|
if (s == nullptr)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
switch (__getlocale(LC_CTYPE))
|
||||||
|
{
|
||||||
|
case LOCALE_INVALID:
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
case LOCALE_POSIX:
|
||||||
|
if (pwc != nullptr)
|
||||||
|
*pwc = *s;
|
||||||
|
return *s ? 1 : 0;
|
||||||
|
case LOCALE_UTF8:
|
||||||
|
const auto* us = reinterpret_cast<const unsigned char*>(s);
|
||||||
|
|
||||||
|
const uint32_t length = BAN::UTF8::byte_length(*us);
|
||||||
|
if (length == BAN::UTF8::invalid || n < length)
|
||||||
|
{
|
||||||
|
errno = EILSEQ;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto wch = BAN::UTF8::to_codepoint(us);
|
||||||
|
if (wch == BAN::UTF8::invalid)
|
||||||
|
{
|
||||||
|
errno = EILSEQ;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pwc)
|
||||||
|
*pwc = wch;
|
||||||
|
|
||||||
|
return wch ? length : 0;
|
||||||
|
}
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
size_t mbstowcs(wchar_t* __restrict pwcs, const char* __restrict s, size_t n)
|
size_t mbstowcs(wchar_t* __restrict pwcs, const char* __restrict s, size_t n)
|
||||||
{
|
{
|
||||||
size_t written = 0;
|
size_t written = 0;
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/futex.h>
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
int futex(int op, const uint32_t* addr, uint32_t value, const struct timespec* abstime)
|
||||||
|
{
|
||||||
|
errno = 0;
|
||||||
|
while (syscall(SYS_FUTEX, op, addr, value, abstime) == -1 && errno == EINTR)
|
||||||
|
errno = 0;
|
||||||
|
return errno;
|
||||||
|
}
|
|
@ -24,6 +24,11 @@ int munmap(void* addr, size_t len)
|
||||||
return syscall(SYS_MUNMAP, addr, len);
|
return syscall(SYS_MUNMAP, addr, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int mprotect(void* addr, size_t len, int prot)
|
||||||
|
{
|
||||||
|
return syscall(SYS_MPROTECT, addr, len, prot);
|
||||||
|
}
|
||||||
|
|
||||||
int msync(void* addr, size_t len, int flags)
|
int msync(void* addr, size_t len, int flags)
|
||||||
{
|
{
|
||||||
pthread_testcancel();
|
pthread_testcancel();
|
||||||
|
@ -45,8 +50,3 @@ int mlock(const void*, size_t)
|
||||||
{
|
{
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
int mprotect(void*, size_t, int)
|
|
||||||
{
|
|
||||||
ASSERT_NOT_REACHED();
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#include <BAN/Debug.h>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
|
@ -33,7 +36,7 @@ int listen(int socket, int backlog)
|
||||||
|
|
||||||
ssize_t recv(int socket, void* __restrict buffer, size_t length, int flags)
|
ssize_t recv(int socket, void* __restrict buffer, size_t length, int flags)
|
||||||
{
|
{
|
||||||
pthread_testcancel();
|
// cancellation point in recvfrom
|
||||||
return recvfrom(socket, buffer, length, flags, nullptr, nullptr);
|
return recvfrom(socket, buffer, length, flags, nullptr, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +56,7 @@ 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)
|
ssize_t send(int socket, const void* message, size_t length, int flags)
|
||||||
{
|
{
|
||||||
pthread_testcancel();
|
// cancellation point in sendto
|
||||||
return sendto(socket, message, length, flags, nullptr, 0);
|
return sendto(socket, message, length, flags, nullptr, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,6 +74,74 @@ ssize_t sendto(int socket, const void* message, size_t length, int flags, const
|
||||||
return syscall(SYS_SENDTO, &arguments);
|
return syscall(SYS_SENDTO, &arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ssize_t recvmsg(int socket, struct msghdr* message, int flags)
|
||||||
|
{
|
||||||
|
if (CMSG_FIRSTHDR(message))
|
||||||
|
{
|
||||||
|
dwarnln("TODO: recvmsg ancillary data");
|
||||||
|
errno = ENOTSUP;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t total_recv = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < message->msg_iovlen; i++)
|
||||||
|
{
|
||||||
|
const ssize_t nrecv = recvfrom(
|
||||||
|
socket,
|
||||||
|
message->msg_iov[i].iov_base,
|
||||||
|
message->msg_iov[i].iov_len,
|
||||||
|
flags,
|
||||||
|
static_cast<sockaddr*>(message->msg_name),
|
||||||
|
&message->msg_namelen
|
||||||
|
);
|
||||||
|
|
||||||
|
if (nrecv < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
total_recv += nrecv;
|
||||||
|
|
||||||
|
if (static_cast<size_t>(nrecv) < message->msg_iov[i].iov_len)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return total_recv;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t sendmsg(int socket, const struct msghdr* message, int flags)
|
||||||
|
{
|
||||||
|
if (CMSG_FIRSTHDR(message))
|
||||||
|
{
|
||||||
|
dwarnln("TODO: sendmsg ancillary data");
|
||||||
|
errno = ENOTSUP;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t total_sent = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < message->msg_iovlen; i++)
|
||||||
|
{
|
||||||
|
const ssize_t nsend = sendto(
|
||||||
|
socket,
|
||||||
|
message->msg_iov[i].iov_base,
|
||||||
|
message->msg_iov[i].iov_len,
|
||||||
|
flags,
|
||||||
|
static_cast<sockaddr*>(message->msg_name),
|
||||||
|
message->msg_namelen
|
||||||
|
);
|
||||||
|
|
||||||
|
if (nsend < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
total_sent += nsend;
|
||||||
|
|
||||||
|
if (static_cast<size_t>(nsend) < message->msg_iov[i].iov_len)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return total_sent;
|
||||||
|
}
|
||||||
|
|
||||||
int socket(int domain, int type, int protocol)
|
int socket(int domain, int type, int protocol)
|
||||||
{
|
{
|
||||||
return syscall(SYS_SOCKET, domain, type, protocol);
|
return syscall(SYS_SOCKET, domain, type, protocol);
|
||||||
|
|
|
@ -9,7 +9,7 @@ ssize_t readv(int fildes, const struct iovec* iov, int iovcnt)
|
||||||
size_t result = 0;
|
size_t result = 0;
|
||||||
for (int i = 0; i < iovcnt; i++)
|
for (int i = 0; i < iovcnt; i++)
|
||||||
{
|
{
|
||||||
uint8_t* base = static_cast<uint8_t*>(iov->iov_base);
|
uint8_t* base = static_cast<uint8_t*>(iov[i].iov_base);
|
||||||
|
|
||||||
size_t nread = 0;
|
size_t nread = 0;
|
||||||
while (nread < iov[i].iov_len)
|
while (nread < iov[i].iov_len)
|
||||||
|
@ -33,7 +33,7 @@ ssize_t writev(int fildes, const struct iovec* iov, int iovcnt)
|
||||||
size_t result = 0;
|
size_t result = 0;
|
||||||
for (int i = 0; i < iovcnt; i++)
|
for (int i = 0; i < iovcnt; i++)
|
||||||
{
|
{
|
||||||
const uint8_t* base = static_cast<const uint8_t*>(iov->iov_base);
|
const uint8_t* base = static_cast<const uint8_t*>(iov[i].iov_base);
|
||||||
|
|
||||||
size_t nwrite = 0;
|
size_t nwrite = 0;
|
||||||
while (nwrite < iov[i].iov_len)
|
while (nwrite < iov[i].iov_len)
|
||||||
|
|
|
@ -787,12 +787,19 @@ char* getlogin(void)
|
||||||
|
|
||||||
char* ttyname(int fildes)
|
char* ttyname(int fildes)
|
||||||
{
|
{
|
||||||
static char storage[_POSIX_TTY_NAME_MAX];
|
static char storage[TTY_NAME_MAX];
|
||||||
if (syscall(SYS_TTYNAME, fildes, storage) == -1)
|
if (ttyname_r(fildes, storage, sizeof(storage)) != 0)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return storage;
|
return storage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ttyname_r(int fildes, char* name, size_t namesize)
|
||||||
|
{
|
||||||
|
if (syscall(SYS_TTYNAME, fildes, name, namesize))
|
||||||
|
return errno;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int access(const char* path, int amode)
|
int access(const char* path, int amode)
|
||||||
{
|
{
|
||||||
return syscall(SYS_ACCESS, path, amode);
|
return syscall(SYS_ACCESS, path, amode);
|
||||||
|
@ -875,7 +882,35 @@ size_t confstr(int name, char* buf, size_t len)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
long pathconf(const char* path, int name);
|
long fpathconf(int fd, int name)
|
||||||
|
{
|
||||||
|
(void)fd;
|
||||||
|
switch (name)
|
||||||
|
{
|
||||||
|
#define LIMIT_CASE(name) case _PC_##name: return name;
|
||||||
|
LIMIT_CASE(LINK_MAX)
|
||||||
|
LIMIT_CASE(MAX_CANON)
|
||||||
|
LIMIT_CASE(MAX_INPUT)
|
||||||
|
LIMIT_CASE(NAME_MAX)
|
||||||
|
LIMIT_CASE(PATH_MAX)
|
||||||
|
LIMIT_CASE(PIPE_BUF)
|
||||||
|
#undef LIMIT_CASE
|
||||||
|
#define POSIX_CASE(name) case _PC_##name: return _POSIX_##name;
|
||||||
|
POSIX_CASE(CHOWN_RESTRICTED)
|
||||||
|
POSIX_CASE(NO_TRUNC)
|
||||||
|
POSIX_CASE(VDISABLE)
|
||||||
|
#undef POSIX_CASE
|
||||||
|
}
|
||||||
|
|
||||||
|
errno = EINVAL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
long pathconf(const char* path, int name)
|
||||||
|
{
|
||||||
|
(void)path;
|
||||||
|
return fpathconf(0, name);
|
||||||
|
}
|
||||||
|
|
||||||
long sysconf(int name)
|
long sysconf(int name)
|
||||||
{
|
{
|
||||||
|
@ -1015,6 +1050,9 @@ long sysconf(int name)
|
||||||
case _SC_PAGE_SIZE:
|
case _SC_PAGE_SIZE:
|
||||||
case _SC_PAGESIZE: return getpagesize();
|
case _SC_PAGESIZE: return getpagesize();
|
||||||
|
|
||||||
|
case _SC_NPROCESSORS_ONLN: return syscall(SYS_GET_NPROCESSOR);
|
||||||
|
case _SC_NPROCESSORS_CONF: return syscall(SYS_GET_NPROCESSOR);
|
||||||
|
|
||||||
case _SC_CLK_TCK: return 100;
|
case _SC_CLK_TCK: return 100;
|
||||||
case _SC_GETGR_R_SIZE_MAX: return 1024;
|
case _SC_GETGR_R_SIZE_MAX: return 1024;
|
||||||
case _SC_GETPW_R_SIZE_MAX: return 1024;
|
case _SC_GETPW_R_SIZE_MAX: return 1024;
|
||||||
|
|
|
@ -142,10 +142,10 @@ namespace LibGUI
|
||||||
return on_socket_error(__FUNCTION__);
|
return on_socket_error(__FUNCTION__);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::set_mouse_capture(bool captured)
|
void Window::set_mouse_relative(bool enabled)
|
||||||
{
|
{
|
||||||
WindowPacket::WindowSetMouseCapture packet;
|
WindowPacket::WindowSetMouseRelative packet;
|
||||||
packet.captured = captured;
|
packet.enabled = enabled;
|
||||||
|
|
||||||
if (auto ret = packet.send_serialized(m_server_fd); ret.is_error())
|
if (auto ret = packet.send_serialized(m_server_fd); ret.is_error())
|
||||||
return on_socket_error(__FUNCTION__);
|
return on_socket_error(__FUNCTION__);
|
||||||
|
|
|
@ -205,7 +205,7 @@ namespace LibGUI
|
||||||
WindowInvalidate,
|
WindowInvalidate,
|
||||||
WindowSetPosition,
|
WindowSetPosition,
|
||||||
WindowSetAttributes,
|
WindowSetAttributes,
|
||||||
WindowSetMouseCapture,
|
WindowSetMouseRelative,
|
||||||
WindowSetSize,
|
WindowSetSize,
|
||||||
WindowSetMinSize,
|
WindowSetMinSize,
|
||||||
WindowSetMaxSize,
|
WindowSetMaxSize,
|
||||||
|
@ -266,8 +266,8 @@ namespace LibGUI
|
||||||
);
|
);
|
||||||
|
|
||||||
DEFINE_PACKET(
|
DEFINE_PACKET(
|
||||||
WindowSetMouseCapture,
|
WindowSetMouseRelative,
|
||||||
bool, captured
|
bool, enabled
|
||||||
);
|
);
|
||||||
|
|
||||||
DEFINE_PACKET(
|
DEFINE_PACKET(
|
||||||
|
|
|
@ -43,7 +43,7 @@ namespace LibGUI
|
||||||
void invalidate(int32_t x, int32_t y, uint32_t width, uint32_t height);
|
void invalidate(int32_t x, int32_t y, uint32_t width, uint32_t height);
|
||||||
void invalidate() { return invalidate(0, 0, width(), height()); }
|
void invalidate() { return invalidate(0, 0, width(), height()); }
|
||||||
|
|
||||||
void set_mouse_capture(bool captured);
|
void set_mouse_relative(bool enabled);
|
||||||
void set_fullscreen(bool fullscreen);
|
void set_fullscreen(bool fullscreen);
|
||||||
void set_title(BAN::StringView title);
|
void set_title(BAN::StringView title);
|
||||||
|
|
||||||
|
|
|
@ -1200,21 +1200,32 @@ static void initialize_tls(MasterTLS master_tls)
|
||||||
|
|
||||||
memcpy(tls_addr, master_tls.addr, master_tls.size);
|
memcpy(tls_addr, master_tls.addr, master_tls.size);
|
||||||
|
|
||||||
uthread* uthread = reinterpret_cast<struct uthread*>(tls_addr + master_tls.size);
|
uthread& uthread = *reinterpret_cast<struct uthread*>(tls_addr + master_tls.size);
|
||||||
uthread->self = uthread;
|
|
||||||
uthread->master_tls_addr = master_tls.addr;
|
|
||||||
uthread->master_tls_size = master_tls.size;
|
|
||||||
|
|
||||||
uthread->dtv[0] = master_tls.module_count;
|
// uthread is prepared in libc init, but some other stuff may be calling pthread functions
|
||||||
|
// for example __cxa_guard_release calls pthread_cond_broadcast
|
||||||
|
uthread = {
|
||||||
|
.self = &uthread,
|
||||||
|
.master_tls_addr = master_tls.addr,
|
||||||
|
.master_tls_size = master_tls.size,
|
||||||
|
.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] = master_tls.module_count;
|
||||||
for (size_t i = 0; i < s_loaded_file_count; i++)
|
for (size_t i = 0; i < s_loaded_file_count; i++)
|
||||||
{
|
{
|
||||||
const auto& elf = s_loaded_files[i];
|
const auto& elf = s_loaded_files[i];
|
||||||
if (elf.tls_addr == nullptr)
|
if (elf.tls_addr == nullptr)
|
||||||
continue;
|
continue;
|
||||||
uthread->dtv[elf.tls_module] = reinterpret_cast<uintptr_t>(tls_addr) + uthread->master_tls_size - elf.tls_offset;
|
uthread.dtv[elf.tls_module] = reinterpret_cast<uintptr_t>(tls_addr) + uthread.master_tls_size - elf.tls_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
syscall(SYS_SET_TLS, uthread);
|
syscall(SYS_SET_TLS, &uthread);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void initialize_environ(char** envp)
|
static void initialize_environ(char** envp)
|
||||||
|
@ -1352,6 +1363,9 @@ void* __dlopen(const char* file, int mode)
|
||||||
|
|
||||||
// FIXME: RTLD_{LOCAL,GLOBAL}
|
// FIXME: RTLD_{LOCAL,GLOBAL}
|
||||||
|
|
||||||
|
if (file == nullptr)
|
||||||
|
return &s_loaded_files[0];
|
||||||
|
|
||||||
char path_buffer[PATH_MAX];
|
char path_buffer[PATH_MAX];
|
||||||
if (!find_library(file, path_buffer))
|
if (!find_library(file, path_buffer))
|
||||||
{
|
{
|
||||||
|
|
|
@ -199,13 +199,13 @@ void WindowServer::on_window_set_attributes(int fd, const LibGUI::WindowPacket::
|
||||||
dwarnln("could not send window shown event: {}", ret.error());
|
dwarnln("could not send window shown event: {}", ret.error());
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowServer::on_window_set_mouse_capture(int fd, const LibGUI::WindowPacket::WindowSetMouseCapture& packet)
|
void WindowServer::on_window_set_mouse_relative(int fd, const LibGUI::WindowPacket::WindowSetMouseRelative& packet)
|
||||||
{
|
{
|
||||||
if (m_is_mouse_captured && packet.captured)
|
if (m_is_mouse_relative && packet.enabled)
|
||||||
{
|
{
|
||||||
ASSERT(m_focused_window);
|
ASSERT(m_focused_window);
|
||||||
if (fd != m_focused_window->client_fd())
|
if (fd != m_focused_window->client_fd())
|
||||||
dwarnln("client tried to set mouse capture while other window has it already captured");
|
dwarnln("client tried to set mouse relative while other window has it already");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,11 +221,11 @@ void WindowServer::on_window_set_mouse_capture(int fd, const LibGUI::WindowPacke
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (packet.captured == m_is_mouse_captured)
|
if (packet.enabled == m_is_mouse_relative)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
set_focused_window(target_window);
|
set_focused_window(target_window);
|
||||||
m_is_mouse_captured = packet.captured;
|
m_is_mouse_relative = packet.enabled;
|
||||||
invalidate(cursor_area());
|
invalidate(cursor_area());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -490,7 +490,7 @@ void WindowServer::on_key_event(LibInput::KeyEvent event)
|
||||||
|
|
||||||
void WindowServer::on_mouse_button(LibInput::MouseButtonEvent event)
|
void WindowServer::on_mouse_button(LibInput::MouseButtonEvent event)
|
||||||
{
|
{
|
||||||
if (m_is_mouse_captured)
|
if (m_is_mouse_relative)
|
||||||
{
|
{
|
||||||
ASSERT(m_focused_window);
|
ASSERT(m_focused_window);
|
||||||
|
|
||||||
|
@ -681,7 +681,7 @@ void WindowServer::on_mouse_move_impl(int32_t new_x, int32_t new_y)
|
||||||
|
|
||||||
void WindowServer::on_mouse_move(LibInput::MouseMoveEvent event)
|
void WindowServer::on_mouse_move(LibInput::MouseMoveEvent event)
|
||||||
{
|
{
|
||||||
if (m_is_mouse_captured)
|
if (m_is_mouse_relative)
|
||||||
{
|
{
|
||||||
ASSERT(m_focused_window);
|
ASSERT(m_focused_window);
|
||||||
|
|
||||||
|
@ -712,7 +712,7 @@ void WindowServer::on_mouse_move(LibInput::MouseMoveEvent event)
|
||||||
}
|
}
|
||||||
|
|
||||||
const int32_t new_x = BAN::Math::clamp(m_cursor.x + event.rel_x, min_x, max_x);
|
const int32_t new_x = BAN::Math::clamp(m_cursor.x + event.rel_x, min_x, max_x);
|
||||||
const int32_t new_y = BAN::Math::clamp(m_cursor.y + event.rel_y, min_y, max_y);
|
const int32_t new_y = BAN::Math::clamp(m_cursor.y - event.rel_y, min_y, max_y);
|
||||||
return on_mouse_move_impl(new_x, new_y);
|
return on_mouse_move_impl(new_x, new_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -724,6 +724,12 @@ void WindowServer::on_mouse_move_abs(LibInput::MouseMoveAbsEvent event)
|
||||||
return (val - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
|
return (val - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (m_is_mouse_relative)
|
||||||
|
{
|
||||||
|
dwarnln("relative mouse not supported with absolute mouse");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int32_t out_min_x, out_max_x;
|
int32_t out_min_x, out_max_x;
|
||||||
int32_t out_min_y, out_max_y;
|
int32_t out_min_y, out_max_y;
|
||||||
|
|
||||||
|
@ -767,9 +773,9 @@ void WindowServer::set_focused_window(BAN::RefPtr<Window> window)
|
||||||
if (m_focused_window == window)
|
if (m_focused_window == window)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (m_is_mouse_captured)
|
if (m_is_mouse_relative)
|
||||||
{
|
{
|
||||||
m_is_mouse_captured = false;
|
m_is_mouse_relative = false;
|
||||||
invalidate(cursor_area());
|
invalidate(cursor_area());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -903,7 +909,7 @@ void WindowServer::invalidate(Rectangle area)
|
||||||
mark_pending_sync(dst_area);
|
mark_pending_sync(dst_area);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_is_mouse_captured)
|
if (!m_is_mouse_relative)
|
||||||
{
|
{
|
||||||
auto cursor_area = this->cursor_area();
|
auto cursor_area = this->cursor_area();
|
||||||
cursor_area.x -= m_focused_window->client_x();
|
cursor_area.x -= m_focused_window->client_x();
|
||||||
|
@ -1140,7 +1146,7 @@ void WindowServer::invalidate(Rectangle area)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_is_mouse_captured)
|
if (!m_is_mouse_relative)
|
||||||
{
|
{
|
||||||
if (const auto overlap = cursor_area().get_overlap(area); overlap.has_value())
|
if (const auto overlap = cursor_area().get_overlap(area); overlap.has_value())
|
||||||
{
|
{
|
||||||
|
@ -1355,8 +1361,8 @@ BAN::RefPtr<Window> WindowServer::find_window_with_fd(int fd) const
|
||||||
|
|
||||||
BAN::RefPtr<Window> WindowServer::find_hovered_window() const
|
BAN::RefPtr<Window> WindowServer::find_hovered_window() const
|
||||||
{
|
{
|
||||||
for (auto window : m_client_windows)
|
for (size_t i = m_client_windows.size(); i > 0; i--)
|
||||||
if (window->full_area().contains(m_cursor))
|
if (auto window = m_client_windows[i - 1]; window->client_area().contains(m_cursor))
|
||||||
return window;
|
return window;
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ public:
|
||||||
void on_window_invalidate(int fd, const LibGUI::WindowPacket::WindowInvalidate&);
|
void on_window_invalidate(int fd, const LibGUI::WindowPacket::WindowInvalidate&);
|
||||||
void on_window_set_position(int fd, const LibGUI::WindowPacket::WindowSetPosition&);
|
void on_window_set_position(int fd, const LibGUI::WindowPacket::WindowSetPosition&);
|
||||||
void on_window_set_attributes(int fd, const LibGUI::WindowPacket::WindowSetAttributes&);
|
void on_window_set_attributes(int fd, const LibGUI::WindowPacket::WindowSetAttributes&);
|
||||||
void on_window_set_mouse_capture(int fd, const LibGUI::WindowPacket::WindowSetMouseCapture&);
|
void on_window_set_mouse_relative(int fd, const LibGUI::WindowPacket::WindowSetMouseRelative&);
|
||||||
void on_window_set_size(int fd, const LibGUI::WindowPacket::WindowSetSize&);
|
void on_window_set_size(int fd, const LibGUI::WindowPacket::WindowSetSize&);
|
||||||
void on_window_set_min_size(int fd, const LibGUI::WindowPacket::WindowSetMinSize&);
|
void on_window_set_min_size(int fd, const LibGUI::WindowPacket::WindowSetMinSize&);
|
||||||
void on_window_set_max_size(int fd, const LibGUI::WindowPacket::WindowSetMaxSize&);
|
void on_window_set_max_size(int fd, const LibGUI::WindowPacket::WindowSetMaxSize&);
|
||||||
|
@ -112,7 +112,7 @@ private:
|
||||||
uint8_t m_resize_quadrant { 0 };
|
uint8_t m_resize_quadrant { 0 };
|
||||||
Position m_resize_start;
|
Position m_resize_start;
|
||||||
|
|
||||||
bool m_is_mouse_captured { false };
|
bool m_is_mouse_relative { false };
|
||||||
|
|
||||||
bool m_deleted_window { false };
|
bool m_deleted_window { false };
|
||||||
bool m_is_stopped { false };
|
bool m_is_stopped { false };
|
||||||
|
|
|
@ -364,17 +364,17 @@ int main()
|
||||||
if (auto ret = LibGUI::WindowPacket::enum::deserialize(client_data.packet_buffer.span()); !ret.is_error()) \
|
if (auto ret = LibGUI::WindowPacket::enum::deserialize(client_data.packet_buffer.span()); !ret.is_error()) \
|
||||||
window_server.function(fd, ret.release_value()); \
|
window_server.function(fd, ret.release_value()); \
|
||||||
break
|
break
|
||||||
WINDOW_PACKET_CASE(WindowCreate, on_window_create);
|
WINDOW_PACKET_CASE(WindowCreate, on_window_create);
|
||||||
WINDOW_PACKET_CASE(WindowInvalidate, on_window_invalidate);
|
WINDOW_PACKET_CASE(WindowInvalidate, on_window_invalidate);
|
||||||
WINDOW_PACKET_CASE(WindowSetPosition, on_window_set_position);
|
WINDOW_PACKET_CASE(WindowSetPosition, on_window_set_position);
|
||||||
WINDOW_PACKET_CASE(WindowSetAttributes, on_window_set_attributes);
|
WINDOW_PACKET_CASE(WindowSetAttributes, on_window_set_attributes);
|
||||||
WINDOW_PACKET_CASE(WindowSetMouseCapture, on_window_set_mouse_capture);
|
WINDOW_PACKET_CASE(WindowSetMouseRelative, on_window_set_mouse_relative);
|
||||||
WINDOW_PACKET_CASE(WindowSetSize, on_window_set_size);
|
WINDOW_PACKET_CASE(WindowSetSize, on_window_set_size);
|
||||||
WINDOW_PACKET_CASE(WindowSetMinSize, on_window_set_min_size);
|
WINDOW_PACKET_CASE(WindowSetMinSize, on_window_set_min_size);
|
||||||
WINDOW_PACKET_CASE(WindowSetMaxSize, on_window_set_max_size);
|
WINDOW_PACKET_CASE(WindowSetMaxSize, on_window_set_max_size);
|
||||||
WINDOW_PACKET_CASE(WindowSetFullscreen, on_window_set_fullscreen);
|
WINDOW_PACKET_CASE(WindowSetFullscreen, on_window_set_fullscreen);
|
||||||
WINDOW_PACKET_CASE(WindowSetTitle, on_window_set_title);
|
WINDOW_PACKET_CASE(WindowSetTitle, on_window_set_title);
|
||||||
WINDOW_PACKET_CASE(WindowSetCursor, on_window_set_cursor);
|
WINDOW_PACKET_CASE(WindowSetCursor, on_window_set_cursor);
|
||||||
#undef WINDOW_PACKET_CASE
|
#undef WINDOW_PACKET_CASE
|
||||||
default:
|
default:
|
||||||
dprintln("unhandled packet type: {}", *reinterpret_cast<uint32_t*>(client_data.packet_buffer.data()));
|
dprintln("unhandled packet type: {}", *reinterpret_cast<uint32_t*>(client_data.packet_buffer.data()));
|
||||||
|
|
Loading…
Reference in New Issue