Compare commits
No commits in common. "eb9fe8ffc6687c6196a7f412ff8ff31ebeed1d81" and "987cc3c237ab933bb9aee48815cb80d6fb470ad4" have entirely different histories.
eb9fe8ffc6
...
987cc3c237
|
@ -14,23 +14,6 @@
|
|||
# multiboot2 header
|
||||
.section .multiboot, "aw"
|
||||
.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:
|
||||
.long 0xE85250D6
|
||||
.long 0
|
||||
|
|
|
@ -14,23 +14,6 @@
|
|||
# multiboot2 header
|
||||
.section .multiboot, "aw"
|
||||
.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:
|
||||
.long 0xE85250D6
|
||||
.long 0
|
||||
|
|
|
@ -16,11 +16,7 @@ namespace Kernel
|
|||
virtual bool is_partition() 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, int status_flags)
|
||||
{
|
||||
(void)offset; (void)len; (void)status_flags;
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
}
|
||||
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 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_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, int status_flags) override;
|
||||
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> mmap_region(PageTable&, off_t offset, size_t len, AddressRange, MemoryRegion::Type, PageTable::flags_t) override;
|
||||
|
||||
virtual dev_t rdev() const override { return m_rdev; }
|
||||
virtual BAN::StringView name() const override { return m_name.sv(); }
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace Kernel
|
|||
|
||||
class FileBackedRegion;
|
||||
class FileSystem;
|
||||
struct SharedFileData;
|
||||
class SharedFileData;
|
||||
|
||||
class Inode : public BAN::RefCounted<Inode>
|
||||
{
|
||||
|
|
|
@ -27,18 +27,18 @@ namespace Kernel
|
|||
BAN_NON_MOVABLE(FileBackedRegion);
|
||||
|
||||
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, int status_flags);
|
||||
static BAN::ErrorOr<BAN::UniqPtr<FileBackedRegion>> create(BAN::RefPtr<Inode>, PageTable&, off_t offset, size_t size, AddressRange address_range, Type, PageTable::flags_t);
|
||||
~FileBackedRegion();
|
||||
|
||||
BAN::ErrorOr<void> msync(vaddr_t, size_t, int) override;
|
||||
virtual BAN::ErrorOr<void> msync(vaddr_t, size_t, int) override;
|
||||
|
||||
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) override;
|
||||
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) override;
|
||||
|
||||
protected:
|
||||
BAN::ErrorOr<bool> allocate_page_containing_impl(vaddr_t vaddr, bool wants_write) override;
|
||||
virtual BAN::ErrorOr<bool> allocate_page_containing_impl(vaddr_t vaddr, bool wants_write) override;
|
||||
|
||||
private:
|
||||
FileBackedRegion(BAN::RefPtr<Inode>, PageTable&, off_t offset, ssize_t size, Type type, PageTable::flags_t flags, int status_flags);
|
||||
FileBackedRegion(BAN::RefPtr<Inode>, PageTable&, off_t offset, ssize_t size, Type flags, PageTable::flags_t page_flags);
|
||||
|
||||
private:
|
||||
BAN::RefPtr<Inode> m_inode;
|
||||
|
|
|
@ -11,22 +11,22 @@ namespace Kernel
|
|||
BAN_NON_MOVABLE(MemoryBackedRegion);
|
||||
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::UniqPtr<MemoryBackedRegion>> create(PageTable&, size_t size, AddressRange, Type, PageTable::flags_t, int status_flags);
|
||||
static BAN::ErrorOr<BAN::UniqPtr<MemoryBackedRegion>> create(PageTable&, size_t size, AddressRange, Type, PageTable::flags_t);
|
||||
~MemoryBackedRegion();
|
||||
|
||||
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) override;
|
||||
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) override;
|
||||
|
||||
BAN::ErrorOr<void> msync(vaddr_t, size_t, int) override { return {}; }
|
||||
virtual BAN::ErrorOr<void> msync(vaddr_t, size_t, int) override { return {}; }
|
||||
|
||||
// Copy data from buffer into this region
|
||||
// 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);
|
||||
|
||||
protected:
|
||||
BAN::ErrorOr<bool> allocate_page_containing_impl(vaddr_t vaddr, bool wants_write) override;
|
||||
virtual BAN::ErrorOr<bool> allocate_page_containing_impl(vaddr_t vaddr, bool wants_write) override;
|
||||
|
||||
private:
|
||||
MemoryBackedRegion(PageTable&, size_t size, Type, PageTable::flags_t, int status_flags);
|
||||
MemoryBackedRegion(PageTable&, size_t size, Type, PageTable::flags_t);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -39,10 +39,6 @@ namespace Kernel
|
|||
size_t size() const { return m_size; }
|
||||
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 physical_page_count() const { return m_physical_page_count; }
|
||||
|
||||
|
@ -50,7 +46,6 @@ namespace Kernel
|
|||
void unpin();
|
||||
void wait_not_pinned();
|
||||
|
||||
BAN::ErrorOr<void> mprotect(PageTable::flags_t);
|
||||
virtual BAN::ErrorOr<void> msync(vaddr_t, size_t, int) = 0;
|
||||
|
||||
// Returns error if no memory was available
|
||||
|
@ -61,7 +56,7 @@ namespace Kernel
|
|||
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) = 0;
|
||||
|
||||
protected:
|
||||
MemoryRegion(PageTable&, size_t size, Type type, PageTable::flags_t flags, int status_flags);
|
||||
MemoryRegion(PageTable&, size_t size, Type type, PageTable::flags_t flags);
|
||||
BAN::ErrorOr<void> initialize(AddressRange);
|
||||
|
||||
virtual BAN::ErrorOr<bool> allocate_page_containing_impl(vaddr_t address, bool wants_write) = 0;
|
||||
|
@ -70,8 +65,7 @@ namespace Kernel
|
|||
PageTable& m_page_table;
|
||||
const size_t m_size;
|
||||
const Type m_type;
|
||||
PageTable::flags_t m_flags;
|
||||
const int m_status_flags;
|
||||
const PageTable::flags_t m_flags;
|
||||
vaddr_t m_vaddr { 0 };
|
||||
size_t m_physical_page_count { 0 };
|
||||
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
#include <kernel/Lock/SpinLock.h>
|
||||
#include <kernel/Memory/MemoryRegion.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
|
@ -57,16 +55,15 @@ namespace Kernel
|
|||
public:
|
||||
static BAN::ErrorOr<BAN::UniqPtr<SharedMemoryObject>> create(BAN::RefPtr<SharedMemoryObjectManager::Object>, PageTable&, AddressRange);
|
||||
|
||||
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) override;
|
||||
|
||||
BAN::ErrorOr<void> msync(vaddr_t, size_t, int) override { return {}; }
|
||||
virtual BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) override;
|
||||
virtual BAN::ErrorOr<void> msync(vaddr_t, size_t, int) override { return {}; }
|
||||
|
||||
protected:
|
||||
BAN::ErrorOr<bool> allocate_page_containing_impl(vaddr_t vaddr, bool wants_write) override;
|
||||
virtual BAN::ErrorOr<bool> allocate_page_containing_impl(vaddr_t vaddr, bool wants_write) override;
|
||||
|
||||
private:
|
||||
SharedMemoryObject(BAN::RefPtr<SharedMemoryObjectManager::Object> object, PageTable& page_table)
|
||||
: MemoryRegion(page_table, object->size, MemoryRegion::Type::SHARED, object->flags, O_EXEC | O_RDWR)
|
||||
: MemoryRegion(page_table, object->size, MemoryRegion::Type::SHARED, object->flags)
|
||||
, m_object(object)
|
||||
{ }
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ namespace Kernel
|
|||
|
||||
bool contains(vaddr_t address) const { return vaddr() <= address && address < vaddr() + size(); }
|
||||
|
||||
BAN::ErrorOr<bool> allocate_page_for_demand_paging(vaddr_t address);
|
||||
BAN::ErrorOr<void> allocate_page_for_demand_paging(vaddr_t address);
|
||||
|
||||
private:
|
||||
VirtualRange(PageTable&, bool preallocated, bool has_guard_pages, vaddr_t, size_t, PageTable::flags_t);
|
||||
|
|
|
@ -161,8 +161,6 @@ namespace Kernel
|
|||
|
||||
BAN::ErrorOr<long> sys_sync(bool should_block);
|
||||
|
||||
BAN::ErrorOr<long> sys_get_nprocessor();
|
||||
|
||||
static BAN::ErrorOr<long> clean_poweroff(int command);
|
||||
BAN::ErrorOr<long> sys_poweroff(int command);
|
||||
|
||||
|
@ -170,14 +168,13 @@ namespace Kernel
|
|||
|
||||
BAN::ErrorOr<long> sys_mmap(const sys_mmap_t*);
|
||||
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_smo_create(size_t len, int prot);
|
||||
BAN::ErrorOr<long> sys_smo_delete(SharedMemoryObjectManager::Key);
|
||||
BAN::ErrorOr<long> sys_smo_map(SharedMemoryObjectManager::Key);
|
||||
|
||||
BAN::ErrorOr<long> sys_ttyname(int fildes, char* name, size_t namesize);
|
||||
BAN::ErrorOr<long> sys_ttyname(int fildes, char* storage);
|
||||
BAN::ErrorOr<long> sys_isatty(int fildes);
|
||||
BAN::ErrorOr<long> sys_posix_openpt(int flags);
|
||||
BAN::ErrorOr<long> sys_ptsname(int fildes, char* buffer, size_t buffer_len);
|
||||
|
@ -190,7 +187,6 @@ namespace Kernel
|
|||
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_futex(int op, const uint32_t* addr, uint32_t val, const timespec* abstime);
|
||||
BAN::ErrorOr<long> sys_yield();
|
||||
BAN::ErrorOr<long> sys_set_tls(void*);
|
||||
BAN::ErrorOr<long> sys_get_tls();
|
||||
|
@ -222,7 +218,7 @@ namespace Kernel
|
|||
// Returns error if page could not be allocated
|
||||
// Returns true if the page was allocated successfully
|
||||
// Return false if access was page violation (segfault)
|
||||
BAN::ErrorOr<bool> allocate_page_for_demand_paging(vaddr_t addr, bool wants_write, bool wants_exec);
|
||||
BAN::ErrorOr<bool> allocate_page_for_demand_paging(vaddr_t addr, bool wants_write);
|
||||
|
||||
// FIXME: remove this API
|
||||
BAN::ErrorOr<BAN::String> absolute_path_of(BAN::StringView) const;
|
||||
|
@ -339,14 +335,6 @@ namespace Kernel
|
|||
BAN::UniqPtr<PageTable> m_page_table;
|
||||
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;
|
||||
};
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#include <kernel/BootInfo.h>
|
||||
#include <kernel/BananBootloader.h>
|
||||
#include <kernel/multiboot.h>
|
||||
#include <kernel/multiboot2.h>
|
||||
|
||||
namespace Kernel
|
||||
|
@ -21,70 +20,6 @@ namespace Kernel
|
|||
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)
|
||||
{
|
||||
const auto& multiboot2_info = *reinterpret_cast<const multiboot2_info_t*>(info);
|
||||
|
@ -214,23 +149,17 @@ namespace Kernel
|
|||
|
||||
bool validate_boot_magic(uint32_t magic)
|
||||
{
|
||||
switch (magic)
|
||||
{
|
||||
case MULTIBOOT_MAGIC:
|
||||
case MULTIBOOT2_MAGIC:
|
||||
case BANAN_BOOTLOADER_MAGIC:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
if (magic == MULTIBOOT2_MAGIC)
|
||||
return true;
|
||||
if (magic == BANAN_BOOTLOADER_MAGIC)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void parse_boot_info(uint32_t magic, uint32_t info)
|
||||
{
|
||||
switch (magic)
|
||||
{
|
||||
case MULTIBOOT_MAGIC:
|
||||
return parse_boot_info_multiboot(info);
|
||||
case MULTIBOOT2_MAGIC:
|
||||
return parse_boot_info_multiboot2(info);
|
||||
case BANAN_BOOTLOADER_MAGIC:
|
||||
|
@ -243,8 +172,6 @@ namespace Kernel
|
|||
{
|
||||
switch (magic)
|
||||
{
|
||||
case MULTIBOOT_MAGIC:
|
||||
return get_early_boot_command_line_multiboot(info);
|
||||
case MULTIBOOT2_MAGIC:
|
||||
return get_early_boot_command_line_multiboot2(info);
|
||||
case BANAN_BOOTLOADER_MAGIC:
|
||||
|
|
|
@ -241,9 +241,9 @@ namespace Kernel
|
|||
class FramebufferMemoryRegion : public MemoryRegion
|
||||
{
|
||||
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, int status_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, BAN::RefPtr<FramebufferDevice> framebuffer)
|
||||
{
|
||||
auto* region_ptr = new FramebufferMemoryRegion(page_table, size, region_type, page_flags, status_flags, framebuffer);
|
||||
auto* region_ptr = new FramebufferMemoryRegion(page_table, size, region_type, page_flags, framebuffer);
|
||||
if (region_ptr == nullptr)
|
||||
return BAN::Error::from_errno(ENOMEM);
|
||||
auto region = BAN::UniqPtr<FramebufferMemoryRegion>::adopt(region_ptr);
|
||||
|
@ -258,7 +258,7 @@ namespace Kernel
|
|||
m_framebuffer->sync_pixels_full();
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> msync(vaddr_t vaddr, size_t size, int flags) override
|
||||
virtual BAN::ErrorOr<void> msync(vaddr_t vaddr, size_t size, int flags) override
|
||||
{
|
||||
if (flags != MS_SYNC)
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
|
@ -281,9 +281,9 @@ namespace Kernel
|
|||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> clone(PageTable& new_page_table) override
|
||||
virtual 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_status_flags, m_framebuffer);
|
||||
auto* region_ptr = new FramebufferMemoryRegion(new_page_table, m_size, m_type, m_flags, m_framebuffer);
|
||||
if (region_ptr == nullptr)
|
||||
return BAN::Error::from_errno(ENOMEM);
|
||||
auto region = BAN::UniqPtr<FramebufferMemoryRegion>::adopt(region_ptr);
|
||||
|
@ -297,7 +297,7 @@ namespace Kernel
|
|||
// Returns error if no memory was available
|
||||
// Returns true if page was succesfully allocated
|
||||
// Returns false if page was already allocated
|
||||
BAN::ErrorOr<bool> allocate_page_containing_impl(vaddr_t vaddr, bool wants_write) override
|
||||
virtual BAN::ErrorOr<bool> allocate_page_containing_impl(vaddr_t vaddr, bool wants_write) override
|
||||
{
|
||||
(void)wants_write;
|
||||
|
||||
|
@ -312,8 +312,8 @@ namespace Kernel
|
|||
}
|
||||
|
||||
private:
|
||||
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, status_flags)
|
||||
FramebufferMemoryRegion(PageTable& page_table, size_t size, MemoryRegion::Type region_type, PageTable::flags_t page_flags, BAN::RefPtr<FramebufferDevice> framebuffer)
|
||||
: MemoryRegion(page_table, size, region_type, page_flags)
|
||||
, m_framebuffer(framebuffer)
|
||||
{ }
|
||||
|
||||
|
@ -370,7 +370,7 @@ namespace Kernel
|
|||
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, int status_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)
|
||||
{
|
||||
if (offset != 0)
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
|
@ -379,7 +379,7 @@ namespace Kernel
|
|||
if (region_type != MemoryRegion::Type::SHARED)
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
|
||||
auto region = TRY(FramebufferMemoryRegion::create(page_table, len, address_range, region_type, page_flags, status_flags, this));
|
||||
auto region = TRY(FramebufferMemoryRegion::create(page_table, len, address_range, region_type, page_flags, this));
|
||||
return BAN::UniqPtr<MemoryRegion>(BAN::move(region));
|
||||
}
|
||||
|
||||
|
|
|
@ -212,7 +212,7 @@ namespace Kernel::ELF
|
|||
file_backed_size,
|
||||
{ .start = pheader_base, .end = pheader_base + file_backed_size },
|
||||
MemoryRegion::Type::PRIVATE,
|
||||
flags, O_EXEC | O_RDWR
|
||||
flags
|
||||
));
|
||||
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),
|
||||
{ .start = aligned_vaddr + file_backed_size, .end = pheader_base + program_header.p_memsz },
|
||||
MemoryRegion::Type::PRIVATE,
|
||||
flags, O_EXEC | O_RDWR
|
||||
flags
|
||||
));
|
||||
|
||||
if (file_backed_size < program_header.p_filesz)
|
||||
|
@ -267,8 +267,7 @@ namespace Kernel::ELF
|
|||
offset + region_size,
|
||||
{ .start = last_loaded_address, .end = USERSPACE_END },
|
||||
MemoryRegion::Type::PRIVATE,
|
||||
PageTable::Flags::UserSupervisor | PageTable::Flags::Present,
|
||||
O_EXEC | O_RDWR
|
||||
PageTable::Flags::UserSupervisor | PageTable::Flags::Present
|
||||
));
|
||||
|
||||
for (vaddr_t vaddr = region->vaddr(); vaddr < region->vaddr() + offset + region->size(); vaddr += PAGE_SIZE)
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#include <kernel/BootInfo.h>
|
||||
#include <kernel/FS/ProcFS/FileSystem.h>
|
||||
#include <kernel/FS/ProcFS/Inode.h>
|
||||
|
||||
|
@ -34,10 +33,6 @@ namespace Kernel
|
|||
*s_instance, 0444, 0, 0
|
||||
));
|
||||
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()
|
||||
|
|
|
@ -109,8 +109,7 @@ namespace Kernel
|
|||
|
||||
if (file_type == DIRTYPE)
|
||||
{
|
||||
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());
|
||||
TRY(parent_inode->create_directory(file_name_sv, file_mode, file_uid, file_gid));
|
||||
}
|
||||
else if (file_type == LNKTYPE)
|
||||
{
|
||||
|
@ -118,46 +117,40 @@ namespace Kernel
|
|||
}
|
||||
else if (file_type == SYMTYPE)
|
||||
{
|
||||
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());
|
||||
else
|
||||
{
|
||||
char link_target[101] {};
|
||||
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);
|
||||
});
|
||||
TRY(parent_inode->create_file(file_name_sv, file_mode, file_uid, file_gid));
|
||||
|
||||
if (link_target[0])
|
||||
{
|
||||
auto inode = TRY(parent_inode->find_inode(file_name_sv));
|
||||
TRY(inode->set_link_target(link_target));
|
||||
}
|
||||
char link_target[101] {};
|
||||
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
|
||||
{
|
||||
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());
|
||||
else
|
||||
TRY(parent_inode->create_file(file_name_sv, file_mode, file_uid, file_gid));
|
||||
|
||||
if (file_size)
|
||||
{
|
||||
if (file_size)
|
||||
auto inode = TRY(parent_inode->find_inode(file_name_sv));
|
||||
|
||||
size_t nwritten = 0;
|
||||
while (nwritten < file_size)
|
||||
{
|
||||
auto inode = TRY(parent_inode->find_inode(file_name_sv));
|
||||
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);
|
||||
});
|
||||
|
||||
size_t nwritten = 0;
|
||||
while (nwritten < file_size)
|
||||
{
|
||||
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;
|
||||
}
|
||||
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,26 +188,6 @@ namespace Kernel
|
|||
|
||||
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
|
||||
if (ARCH(i686) && !GDT::is_user_segment(interrupt_stack->cs))
|
||||
; // 32 bit does not push stack pointer when no CPL change happens
|
||||
|
@ -227,6 +207,26 @@ namespace Kernel
|
|||
Thread::current().handle_signal(SIGKILL);
|
||||
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,7 +338,6 @@ namespace Kernel
|
|||
ASSERT(InterruptController::get().is_in_service(IRQ_IPI - IRQ_VECTOR_BASE));
|
||||
InterruptController::get().eoi(IRQ_IPI - IRQ_VECTOR_BASE);
|
||||
Processor::handle_ipi();
|
||||
Processor::scheduler().reschedule_if_idle();
|
||||
}
|
||||
|
||||
extern "C" void cpp_timer_handler()
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
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, int status_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)
|
||||
{
|
||||
ASSERT(inode->mode().ifreg());
|
||||
|
||||
|
@ -16,14 +16,14 @@ namespace Kernel
|
|||
if ((size > (size_t)inode->size() || (size_t)offset > (size_t)inode->size() - size))
|
||||
return BAN::Error::from_errno(EOVERFLOW);
|
||||
|
||||
auto* region_ptr = new FileBackedRegion(inode, page_table, offset, size, type, flags, status_flags);
|
||||
auto* region_ptr = new FileBackedRegion(inode, page_table, offset, size, type, flags);
|
||||
if (region_ptr == nullptr)
|
||||
return BAN::Error::from_errno(ENOMEM);
|
||||
auto region = BAN::UniqPtr<FileBackedRegion>::adopt(region_ptr);
|
||||
|
||||
TRY(region->initialize(address_range));
|
||||
|
||||
if (type == Type::PRIVATE)
|
||||
if (type == Type::PRIVATE && (flags & PageTable::Flags::ReadWrite))
|
||||
TRY(region->m_dirty_pages.resize(BAN::Math::div_round_up<size_t>(size, PAGE_SIZE)));
|
||||
|
||||
LockGuard _(inode->m_mutex);
|
||||
|
@ -39,8 +39,8 @@ namespace Kernel
|
|||
return region;
|
||||
}
|
||||
|
||||
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, status_flags)
|
||||
FileBackedRegion::FileBackedRegion(BAN::RefPtr<Inode> inode, PageTable& page_table, off_t offset, ssize_t size, Type type, PageTable::flags_t flags)
|
||||
: MemoryRegion(page_table, size, type, flags)
|
||||
, m_inode(inode)
|
||||
, m_offset(offset)
|
||||
{
|
||||
|
@ -200,7 +200,7 @@ namespace Kernel
|
|||
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> FileBackedRegion::clone(PageTable& page_table)
|
||||
{
|
||||
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, m_status_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));
|
||||
|
||||
// non-dirty pages can go through demand paging
|
||||
|
||||
|
|
|
@ -4,12 +4,12 @@
|
|||
namespace Kernel
|
||||
{
|
||||
|
||||
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)
|
||||
BAN::ErrorOr<BAN::UniqPtr<MemoryBackedRegion>> MemoryBackedRegion::create(PageTable& page_table, size_t size, AddressRange address_range, Type type, PageTable::flags_t flags)
|
||||
{
|
||||
if (type != Type::PRIVATE)
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
|
||||
auto* region_ptr = new MemoryBackedRegion(page_table, size, type, flags, status_flags);
|
||||
auto* region_ptr = new MemoryBackedRegion(page_table, size, type, flags);
|
||||
if (region_ptr == nullptr)
|
||||
return BAN::Error::from_errno(ENOMEM);
|
||||
auto region = BAN::UniqPtr<MemoryBackedRegion>::adopt(region_ptr);
|
||||
|
@ -19,8 +19,8 @@ namespace Kernel
|
|||
return region;
|
||||
}
|
||||
|
||||
MemoryBackedRegion::MemoryBackedRegion(PageTable& page_table, size_t size, Type type, PageTable::flags_t flags, int status_flags)
|
||||
: MemoryRegion(page_table, size, type, flags, status_flags)
|
||||
MemoryBackedRegion::MemoryBackedRegion(PageTable& page_table, size_t size, Type type, PageTable::flags_t flags)
|
||||
: MemoryRegion(page_table, size, type, flags)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -68,7 +68,7 @@ namespace Kernel
|
|||
ASSERT(&PageTable::current() == &m_page_table);
|
||||
|
||||
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, m_status_flags));
|
||||
auto result = TRY(MemoryBackedRegion::create(new_page_table, m_size, { .start = m_vaddr, .end = m_vaddr + aligned_size }, m_type, m_flags));
|
||||
|
||||
for (size_t offset = 0; offset < m_size; offset += PAGE_SIZE)
|
||||
{
|
||||
|
|
|
@ -4,12 +4,11 @@
|
|||
namespace Kernel
|
||||
{
|
||||
|
||||
MemoryRegion::MemoryRegion(PageTable& page_table, size_t size, Type type, PageTable::flags_t flags, int status_flags)
|
||||
MemoryRegion::MemoryRegion(PageTable& page_table, size_t size, Type type, PageTable::flags_t flags)
|
||||
: m_page_table(page_table)
|
||||
, m_size(size)
|
||||
, m_type(type)
|
||||
, m_flags(flags)
|
||||
, m_status_flags(status_flags)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -50,25 +49,6 @@ namespace Kernel
|
|||
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)
|
||||
{
|
||||
ASSERT(contains(address));
|
||||
|
|
|
@ -99,7 +99,7 @@ namespace Kernel
|
|||
else
|
||||
{
|
||||
const size_t page_count = size() / PAGE_SIZE;
|
||||
for (size_t i = 0; i < page_count; i++)
|
||||
for (size_t i = m_has_guard_pages; i < page_count; i++)
|
||||
{
|
||||
PageTable::with_fast_page(m_paddrs[i], [&] {
|
||||
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));
|
||||
|
||||
const size_t page_count = size() / PAGE_SIZE;
|
||||
for (size_t i = 0; i < page_count; i++)
|
||||
for (size_t i = m_has_guard_pages; i < page_count; i++)
|
||||
{
|
||||
if (m_paddrs[i] == 0)
|
||||
continue;
|
||||
|
@ -140,17 +140,15 @@ namespace Kernel
|
|||
return result;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<bool> VirtualRange::allocate_page_for_demand_paging(vaddr_t vaddr)
|
||||
BAN::ErrorOr<void> VirtualRange::allocate_page_for_demand_paging(vaddr_t vaddr)
|
||||
{
|
||||
ASSERT(!m_preallocated);
|
||||
ASSERT(vaddr % PAGE_SIZE == 0);
|
||||
ASSERT(contains(vaddr));
|
||||
ASSERT(&PageTable::current() == &m_page_table);
|
||||
|
||||
if (m_preallocated)
|
||||
return false;
|
||||
|
||||
const size_t index = (vaddr - this->vaddr()) / PAGE_SIZE;
|
||||
if (m_paddrs[index])
|
||||
return false;
|
||||
ASSERT(m_paddrs[index] == 0);
|
||||
|
||||
SpinLockGuard _(m_lock);
|
||||
|
||||
|
@ -161,7 +159,7 @@ namespace Kernel
|
|||
m_page_table.map_page_at(m_paddrs[index], vaddr, m_flags);
|
||||
memset(reinterpret_cast<void*>(vaddr), 0, PAGE_SIZE);
|
||||
|
||||
return true;
|
||||
return {};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -29,16 +29,17 @@ namespace Kernel
|
|||
, m_type(type)
|
||||
, m_rdev(get_rdev(type))
|
||||
{
|
||||
ASSERT(minor(m_rdev) < 10);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case Type::Ethernet:
|
||||
ASSERT(minor(m_rdev) < 10);
|
||||
strcpy(m_name, "ethx");
|
||||
m_name[3] = minor(m_rdev) + '0';
|
||||
break;
|
||||
case Type::Loopback:
|
||||
ASSERT(minor(m_rdev) == 0);
|
||||
strcpy(m_name, "lo");
|
||||
strcpy(m_name, "lox");
|
||||
m_name[2] = minor(m_rdev) + '0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -429,8 +429,6 @@ namespace Kernel
|
|||
size_t nread;
|
||||
{
|
||||
LockGuard _(inode->m_mutex);
|
||||
if (!inode->can_read() && inode->has_hungup())
|
||||
return 0;
|
||||
if (is_nonblock && !inode->can_read())
|
||||
return BAN::Error::from_errno(EAGAIN);
|
||||
nread = TRY(inode->read(offset, buffer));
|
||||
|
@ -466,11 +464,6 @@ namespace Kernel
|
|||
size_t nwrite;
|
||||
{
|
||||
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())
|
||||
return BAN::Error::from_errno(EAGAIN);
|
||||
nwrite = TRY(inode->write(offset, buffer));
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/banan-os.h>
|
||||
#include <sys/futex.h>
|
||||
#include <sys/sysmacros.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
|
@ -318,8 +317,7 @@ namespace Kernel
|
|||
tls_size,
|
||||
{ .start = master_addr, .end = USERSPACE_END },
|
||||
MemoryRegion::Type::PRIVATE,
|
||||
PageTable::Flags::UserSupervisor | PageTable::Flags::ReadWrite | PageTable::Flags::Present,
|
||||
O_EXEC | O_RDWR
|
||||
PageTable::Flags::UserSupervisor | PageTable::Flags::ReadWrite | PageTable::Flags::Present
|
||||
));
|
||||
|
||||
BAN::Vector<uint8_t> temp_buffer;
|
||||
|
@ -983,32 +981,24 @@ namespace Kernel
|
|||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<bool> Process::allocate_page_for_demand_paging(vaddr_t address, bool wants_write, bool wants_exec)
|
||||
BAN::ErrorOr<bool> Process::allocate_page_for_demand_paging(vaddr_t address, bool wants_write)
|
||||
{
|
||||
ASSERT(&Process::current() == this);
|
||||
|
||||
LockGuard _(m_process_lock);
|
||||
|
||||
{
|
||||
// NOTE: page can be already allocated by another thread!
|
||||
|
||||
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);
|
||||
{
|
||||
TRY(Thread::current().userspace_stack().allocate_page_for_demand_paging(address));
|
||||
return true;
|
||||
}
|
||||
|
||||
for (auto& region : m_mapped_regions)
|
||||
{
|
||||
if (!region->contains(address))
|
||||
continue;
|
||||
return region->allocate_page_containing(address, wants_write);
|
||||
TRY(region->allocate_page_containing(address, wants_write));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -2021,11 +2011,6 @@ namespace Kernel
|
|||
return 0;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> Process::sys_get_nprocessor()
|
||||
{
|
||||
return Processor::count();
|
||||
}
|
||||
|
||||
[[noreturn]] static void reset_system()
|
||||
{
|
||||
(void)ACPI::ACPI::get().reset();
|
||||
|
@ -2147,8 +2132,7 @@ namespace Kernel
|
|||
page_table(),
|
||||
args.len,
|
||||
address_range,
|
||||
region_type, page_flags,
|
||||
O_EXEC | O_RDWR
|
||||
region_type, page_flags
|
||||
));
|
||||
|
||||
LockGuard _(m_process_lock);
|
||||
|
@ -2175,8 +2159,7 @@ namespace Kernel
|
|||
page_table(),
|
||||
args.off, args.len,
|
||||
address_range,
|
||||
region_type, page_flags,
|
||||
status_flags
|
||||
region_type, page_flags
|
||||
));
|
||||
}
|
||||
else if (inode->is_device())
|
||||
|
@ -2185,8 +2168,7 @@ namespace Kernel
|
|||
page_table(),
|
||||
args.off, args.len,
|
||||
address_range,
|
||||
region_type, page_flags,
|
||||
status_flags
|
||||
region_type, page_flags
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -2232,70 +2214,6 @@ namespace Kernel
|
|||
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)
|
||||
{
|
||||
if (flags != MS_SYNC && flags != MS_ASYNC && flags != MS_INVALIDATE)
|
||||
|
@ -2352,17 +2270,17 @@ namespace Kernel
|
|||
return m_mapped_regions.back()->vaddr();
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> Process::sys_ttyname(int fildes, char* name, size_t namesize)
|
||||
BAN::ErrorOr<long> Process::sys_ttyname(int fildes, char* storage)
|
||||
{
|
||||
LockGuard _(m_process_lock);
|
||||
TRY(validate_pointer_access(name, namesize, true));
|
||||
TRY(validate_pointer_access(storage, TTY_NAME_MAX, true));
|
||||
auto inode = TRY(m_open_file_descriptors.inode_of(fildes));
|
||||
if (!inode->is_tty())
|
||||
return BAN::Error::from_errno(ENOTTY);
|
||||
auto path = TRY(m_open_file_descriptors.path_of(fildes));
|
||||
if (namesize < path.size() + 1)
|
||||
return BAN::Error::from_errno(ERANGE);
|
||||
strcpy(name, path.data());
|
||||
ASSERT(path.size() < TTY_NAME_MAX);
|
||||
strncpy(storage, path.data(), path.size());
|
||||
storage[path.size()] = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2573,7 +2491,14 @@ namespace Kernel
|
|||
*oact = m_signal_handlers[signal];
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -2619,96 +2544,6 @@ namespace Kernel
|
|||
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()
|
||||
{
|
||||
Processor::yield();
|
||||
|
@ -3220,8 +3055,9 @@ namespace Kernel
|
|||
BAN::ErrorOr<void> Process::validate_pointer_access_check(const void* ptr, size_t size, bool needs_write)
|
||||
{
|
||||
ASSERT(&Process::current() == this);
|
||||
auto& thread = Thread::current();
|
||||
|
||||
const vaddr_t vaddr = reinterpret_cast<vaddr_t>(ptr);
|
||||
vaddr_t vaddr = (vaddr_t)ptr;
|
||||
|
||||
// NOTE: detect overflow
|
||||
if (vaddr + size < vaddr)
|
||||
|
@ -3231,12 +3067,14 @@ namespace Kernel
|
|||
if (vaddr + size > USERSPACE_END)
|
||||
goto unauthorized_access;
|
||||
|
||||
for (const auto* thread : m_threads)
|
||||
if (vaddr >= thread->userspace_stack_bottom() && vaddr + size <= thread->userspace_stack_top())
|
||||
return {};
|
||||
if (vaddr == 0)
|
||||
return {};
|
||||
|
||||
if (vaddr >= thread.userspace_stack_bottom() && vaddr + size <= thread.userspace_stack_top())
|
||||
return {};
|
||||
|
||||
// FIXME: should we allow cross mapping access?
|
||||
for (const auto& mapped_region : m_mapped_regions)
|
||||
for (auto& mapped_region : m_mapped_regions)
|
||||
{
|
||||
if (!mapped_region->contains_fully(vaddr, size))
|
||||
continue;
|
||||
|
@ -3269,7 +3107,7 @@ unauthorized_access:
|
|||
const vaddr_t current = page_start + i * PAGE_SIZE;
|
||||
if (page_table().get_page_flags(current) & PageTable::Flags::Present)
|
||||
continue;
|
||||
TRY(Process::allocate_page_for_demand_paging(current, needs_write, false));
|
||||
TRY(Process::allocate_page_for_demand_paging(current, needs_write));
|
||||
}
|
||||
|
||||
return {};
|
||||
|
|
|
@ -119,15 +119,9 @@ namespace Kernel
|
|||
|
||||
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(
|
||||
page_table,
|
||||
stack_addr_start, USERSPACE_END,
|
||||
0x200000, USERSPACE_END,
|
||||
kernel_stack_size,
|
||||
PageTable::Flags::ReadWrite | PageTable::Flags::Present,
|
||||
true, true
|
||||
|
@ -135,7 +129,7 @@ namespace Kernel
|
|||
|
||||
thread->m_userspace_stack = TRY(VirtualRange::create_to_vaddr_range(
|
||||
page_table,
|
||||
stack_addr_start, USERSPACE_END,
|
||||
0x200000, USERSPACE_END,
|
||||
userspace_stack_size,
|
||||
PageTable::Flags::UserSupervisor | PageTable::Flags::ReadWrite | PageTable::Flags::Present,
|
||||
true, true
|
||||
|
@ -513,16 +507,9 @@ namespace Kernel
|
|||
bool has_sa_restart;
|
||||
{
|
||||
SpinLockGuard _(m_process->m_signal_lock);
|
||||
|
||||
auto& handler = m_process->m_signal_handlers[signal];
|
||||
|
||||
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);
|
||||
ASSERT(!(m_process->m_signal_handlers[signal].sa_flags & SA_SIGINFO));
|
||||
signal_handler = (vaddr_t)m_process->m_signal_handlers[signal].sa_handler;
|
||||
has_sa_restart = !!(m_process->m_signal_handlers[signal].sa_flags & SA_RESTART);
|
||||
}
|
||||
|
||||
m_signal_pending_mask &= ~(1ull << signal);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
diff -ruN SDL-release-2.30.11/CMakeLists.txt SDL2-2.30.11-banan_os/CMakeLists.txt
|
||||
diff -ruN SDL-release-2.30.11/CMakeLists.txt SDL-release-2.30.11-banan_os/CMakeLists.txt
|
||||
--- SDL-release-2.30.11/CMakeLists.txt 2025-01-01 19:09:38.000000000 +0200
|
||||
+++ SDL2-2.30.11-banan_os/CMakeLists.txt 2025-08-03 14:04:09.894244781 +0300
|
||||
+++ SDL-release-2.30.11-banan_os/CMakeLists.txt 2025-06-25 16:53:26.163363407 +0300
|
||||
@@ -1452,7 +1452,7 @@
|
||||
CheckPTHREAD()
|
||||
CheckLibUnwind()
|
||||
|
@ -60,9 +60,9 @@ diff -ruN SDL-release-2.30.11/CMakeLists.txt SDL2-2.30.11-banan_os/CMakeLists.tx
|
|||
elseif(RISCOS)
|
||||
if(SDL_MISC)
|
||||
file(GLOB MISC_SOURCES ${SDL2_SOURCE_DIR}/src/misc/riscos/*.c)
|
||||
diff -ruN SDL-release-2.30.11/include/SDL_config.h.cmake SDL2-2.30.11-banan_os/include/SDL_config.h.cmake
|
||||
diff -ruN SDL-release-2.30.11/include/SDL_config.h.cmake SDL-release-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
|
||||
+++ SDL2-2.30.11-banan_os/include/SDL_config.h.cmake 2025-08-03 14:04:09.894803585 +0300
|
||||
+++ SDL-release-2.30.11-banan_os/include/SDL_config.h.cmake 2025-06-24 19:53:27.963249565 +0300
|
||||
@@ -406,6 +406,7 @@
|
||||
#cmakedefine SDL_VIDEO_DRIVER_ANDROID @SDL_VIDEO_DRIVER_ANDROID@
|
||||
#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 SDL2-2.30.11-banan_os/i
|
|||
#cmakedefine SDL_VIDEO_DRIVER_COCOA @SDL_VIDEO_DRIVER_COCOA@
|
||||
#cmakedefine SDL_VIDEO_DRIVER_UIKIT @SDL_VIDEO_DRIVER_UIKIT@
|
||||
#cmakedefine SDL_VIDEO_DRIVER_DIRECTFB @SDL_VIDEO_DRIVER_DIRECTFB@
|
||||
diff -ruN SDL-release-2.30.11/include/SDL_platform.h SDL2-2.30.11-banan_os/include/SDL_platform.h
|
||||
diff -ruN SDL-release-2.30.11/include/SDL_platform.h SDL-release-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
|
||||
+++ SDL2-2.30.11-banan_os/include/SDL_platform.h 2025-08-03 14:04:09.895022748 +0300
|
||||
+++ SDL-release-2.30.11-banan_os/include/SDL_platform.h 2025-06-24 17:54:20.094530618 +0300
|
||||
@@ -36,6 +36,10 @@
|
||||
#undef __HAIKU__
|
||||
#define __HAIKU__ 1
|
||||
|
@ -85,9 +85,9 @@ diff -ruN SDL-release-2.30.11/include/SDL_platform.h SDL2-2.30.11-banan_os/inclu
|
|||
#if defined(bsdi) || defined(__bsdi) || defined(__bsdi__)
|
||||
#undef __BSDI__
|
||||
#define __BSDI__ 1
|
||||
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
|
||||
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
|
||||
--- SDL-release-2.30.11/src/misc/banan_os/SDL_sysurl.cpp 1970-01-01 02:00:00.000000000 +0200
|
||||
+++ SDL2-2.30.11-banan_os/src/misc/banan_os/SDL_sysurl.cpp 2025-08-03 14:04:09.895198889 +0300
|
||||
+++ SDL-release-2.30.11-banan_os/src/misc/banan_os/SDL_sysurl.cpp 2025-06-24 18:51:56.695953622 +0300
|
||||
@@ -0,0 +1,30 @@
|
||||
+/*
|
||||
+ Simple DirectMedia Layer
|
||||
|
@ -119,9 +119,9 @@ diff -ruN SDL-release-2.30.11/src/misc/banan_os/SDL_sysurl.cpp SDL2-2.30.11-bana
|
|||
+
|
||||
+/* vi: set ts=4 sw=4 expandtab: */
|
||||
+
|
||||
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
|
||||
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
|
||||
--- SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_message_box.cpp 1970-01-01 02:00:00.000000000 +0200
|
||||
+++ SDL2-2.30.11-banan_os/src/video/banan_os/SDL_banan_os_message_box.cpp 2025-08-03 14:04:09.895299391 +0300
|
||||
+++ 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
|
||||
@@ -0,0 +1,60 @@
|
||||
+/*
|
||||
+ 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 */
|
||||
+
|
||||
+/* vi: set ts=4 sw=4 expandtab: */
|
||||
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
|
||||
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
|
||||
--- SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_message_box.h 1970-01-01 02:00:00.000000000 +0200
|
||||
+++ SDL2-2.30.11-banan_os/src/video/banan_os/SDL_banan_os_message_box.h 2025-08-03 14:04:09.895347931 +0300
|
||||
+++ 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
|
||||
@@ -0,0 +1,45 @@
|
||||
+/*
|
||||
+ Simple DirectMedia Layer
|
||||
|
@ -232,10 +232,10 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_message_box.h SDL2
|
|||
+#endif
|
||||
+
|
||||
+/* vi: set ts=4 sw=4 expandtab: */
|
||||
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
|
||||
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
|
||||
--- SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp 1970-01-01 02:00:00.000000000 +0200
|
||||
+++ 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,719 @@
|
||||
+++ SDL-release-2.30.11-banan_os/src/video/banan_os/SDL_banan_os_video.cpp 2025-06-28 20:49:41.452498550 +0300
|
||||
@@ -0,0 +1,770 @@
|
||||
+/*
|
||||
+ Simple DirectMedia Layer
|
||||
+ 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 SDL2-2.3
|
|||
+struct banan_os_window
|
||||
+{
|
||||
+ BAN::UniqPtr<LibGUI::Window> window;
|
||||
+ OSMesaContext gl_context { nullptr };
|
||||
+ SDL_bool relative { SDL_FALSE };
|
||||
+ LibGUI::Texture framebuffer;
|
||||
+ OSMesaContext gl_context;
|
||||
+};
|
||||
+
|
||||
+struct banan_os_video_device_data
|
||||
|
@ -442,8 +442,6 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.3
|
|||
+{
|
||||
+ DUMP_FUNCTION();
|
||||
+
|
||||
+ // FIXME: support system cursors :)
|
||||
+
|
||||
+ auto* cursor = static_cast<SDL_Cursor*>(SDL_calloc(1, sizeof(SDL_Cursor)));
|
||||
+ if (cursor == nullptr) {
|
||||
+ SDL_OutOfMemory();
|
||||
|
@ -475,17 +473,12 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.3
|
|||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int BANAN_OS_SetRelativeMouseMode(SDL_bool enabled)
|
||||
+static int BANAN_OS_CaptureMouse(SDL_Window* window)
|
||||
+{
|
||||
+ DUMP_FUNCTION();
|
||||
+
|
||||
+ auto* window = SDL_GetMouseFocus();
|
||||
+ if (window == nullptr)
|
||||
+ return 0;
|
||||
+
|
||||
+ auto& ban_window = *static_cast<banan_os_window*>(window->driverdata);
|
||||
+ ban_window.window->set_mouse_relative(enabled);
|
||||
+ ban_window.relative = enabled;
|
||||
+ ban_window.window->set_mouse_capture(SDL_GetMouse()->capture_window == window);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
|
@ -496,11 +489,9 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.3
|
|||
+
|
||||
+ auto* mouse = SDL_GetMouse();
|
||||
+ mouse->ShowCursor = BANAN_OS_ShowCursor;
|
||||
+ mouse->SetRelativeMouseMode = BANAN_OS_SetRelativeMouseMode;
|
||||
+ mouse->CaptureMouse = BANAN_OS_CaptureMouse;
|
||||
+ mouse->CreateSystemCursor = BANAN_OS_CreateSystemCursor;
|
||||
+ mouse->FreeCursor = BANAN_OS_FreeCursor;
|
||||
+
|
||||
+ SDL_SetDefaultCursor(BANAN_OS_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW));
|
||||
+}
|
||||
+
|
||||
+static int BANAN_OS_VideoInit(_THIS)
|
||||
|
@ -597,16 +588,16 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.3
|
|||
+ );
|
||||
+
|
||||
+ ban_window->window->set_mouse_button_event_callback(
|
||||
+ [window, ban_window](LibGUI::EventPacket::MouseButtonEvent::event_t event) {
|
||||
+ [window](LibGUI::EventPacket::MouseButtonEvent::event_t event) {
|
||||
+ const int state = event.pressed ? SDL_PRESSED : SDL_RELEASED;
|
||||
+ SDL_SendMouseMotion(window, 0, ban_window->relative, event.x, event.y);
|
||||
+ SDL_SendMouseMotion(window, 0, SDL_FALSE, event.x, event.y);
|
||||
+ SDL_SendMouseButton(window, 0, state, BANAN_OS_mouse_button_to_sdl(event.button));
|
||||
+ }
|
||||
+ );
|
||||
+
|
||||
+ ban_window->window->set_mouse_move_event_callback(
|
||||
+ [window, ban_window](LibGUI::EventPacket::MouseMoveEvent::event_t event) {
|
||||
+ SDL_SendMouseMotion(window, 0, ban_window->relative, event.x, event.y);
|
||||
+ [window](LibGUI::EventPacket::MouseMoveEvent::event_t event) {
|
||||
+ SDL_SendMouseMotion(window, 0, SDL_FALSE, event.x, event.y);
|
||||
+ }
|
||||
+ );
|
||||
+
|
||||
|
@ -622,13 +613,13 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.3
|
|||
+ const size_t height = ban_window->window->height();
|
||||
+
|
||||
+ if (ban_window->gl_context) {
|
||||
+ ban_window->framebuffer = MUST(LibGUI::Texture::create(width, height, 0x000000));
|
||||
+ OSMesaMakeCurrent(
|
||||
+ ban_window->gl_context,
|
||||
+ ban_window->window->texture().pixels().data(),
|
||||
+ ban_window->framebuffer.pixels().data(),
|
||||
+ GL_UNSIGNED_BYTE,
|
||||
+ width, height
|
||||
+ );
|
||||
+ OSMesaPixelStore(OSMESA_Y_UP, 0);
|
||||
+ }
|
||||
+
|
||||
+ SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, width, height);
|
||||
|
@ -776,9 +767,11 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.3
|
|||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ ban_window.framebuffer = framebuffer_or_error.release_value();
|
||||
+
|
||||
+ *format = SDL_PIXELFORMAT_BGR888;
|
||||
+ *pixels = ban_window.window->texture().pixels().data();
|
||||
+ *pitch = ban_window.window->texture().width() * sizeof(uint32_t);
|
||||
+ *pixels = ban_window.framebuffer.pixels().data();
|
||||
+ *pitch = ban_window.framebuffer.width() * sizeof(uint32_t);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
|
@ -789,8 +782,25 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.3
|
|||
+
|
||||
+ auto& ban_window = *static_cast<banan_os_window*>(window->driverdata);
|
||||
+
|
||||
+ for (int i = 0; i < numrects; i++)
|
||||
+ ban_window.window->invalidate(rects[i].x, rects[i].y, rects[i].w, rects[i].h);
|
||||
+ int min_x = ban_window.window->width();
|
||||
+ int min_y = ban_window.window->height();
|
||||
+ 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;
|
||||
+}
|
||||
|
@ -798,6 +808,32 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.3
|
|||
+static void BANAN_OS_DestroyWindowFramebuffer(_THIS, SDL_Window* window)
|
||||
+{
|
||||
+ 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)
|
||||
|
@ -835,19 +871,25 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.3
|
|||
+
|
||||
+ 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);
|
||||
+ if (gl_context == nullptr) {
|
||||
+ dwarnln("OSMesaCreateContext");
|
||||
+ return nullptr;
|
||||
+ }
|
||||
+
|
||||
+ auto& fb = ban_window.window->texture();
|
||||
+ auto fb = framebuffer_or_error.release_value();
|
||||
+ if (!OSMesaMakeCurrent(gl_context, fb.pixels().data(), GL_UNSIGNED_BYTE, fb.width(), fb.height())) {
|
||||
+ OSMesaDestroyContext(gl_context);
|
||||
+ return nullptr;
|
||||
+ }
|
||||
+ OSMesaPixelStore(OSMESA_Y_UP, 0);
|
||||
+
|
||||
+ ban_window.framebuffer = BAN::move(fb);
|
||||
+ ban_window.gl_context = gl_context;
|
||||
+
|
||||
+ return gl_context;
|
||||
|
@ -872,10 +914,9 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.3
|
|||
+
|
||||
+ auto gl_context = static_cast<OSMesaContext>(context);
|
||||
+
|
||||
+ auto& fb = ban_window.window->texture();
|
||||
+ auto& fb = ban_window.framebuffer;
|
||||
+ if (!OSMesaMakeCurrent(gl_context, fb.pixels().data(), GL_UNSIGNED_BYTE, fb.width(), fb.height()))
|
||||
+ return -1;
|
||||
+ OSMesaPixelStore(OSMESA_Y_UP, 0);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
|
@ -890,6 +931,15 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.3
|
|||
+ glFinish();
|
||||
+
|
||||
+ 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();
|
||||
+
|
||||
+ return 0;
|
||||
|
@ -932,6 +982,7 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.3
|
|||
+ device->UpdateWindowFramebuffer = BANAN_OS_UpdateWindowFramebuffer;
|
||||
+ device->DestroyWindowFramebuffer = BANAN_OS_DestroyWindowFramebuffer;
|
||||
+
|
||||
+ device->WaitEventTimeout = BANAN_OS_WaitEventTimeout;
|
||||
+ device->PumpEvents = BANAN_OS_PumpEvents;
|
||||
+
|
||||
+ device->GL_LoadLibrary = BANAN_OS_GL_LoadLibrary;
|
||||
|
@ -955,9 +1006,9 @@ diff -ruN SDL-release-2.30.11/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.3
|
|||
+#endif /* SDL_VIDEO_DRIVER_BANAN_OS */
|
||||
+
|
||||
+/* vi: set ts=4 sw=4 expandtab: */
|
||||
diff -ruN SDL-release-2.30.11/src/video/SDL_sysvideo.h SDL2-2.30.11-banan_os/src/video/SDL_sysvideo.h
|
||||
diff -ruN SDL-release-2.30.11/src/video/SDL_sysvideo.h SDL-release-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
|
||||
+++ SDL2-2.30.11-banan_os/src/video/SDL_sysvideo.h 2025-08-03 14:04:09.895655165 +0300
|
||||
+++ SDL-release-2.30.11-banan_os/src/video/SDL_sysvideo.h 2025-06-24 18:55:08.546768590 +0300
|
||||
@@ -462,6 +462,7 @@
|
||||
extern VideoBootStrap WINDOWS_bootstrap;
|
||||
extern VideoBootStrap WINRT_bootstrap;
|
||||
|
@ -966,9 +1017,9 @@ diff -ruN SDL-release-2.30.11/src/video/SDL_sysvideo.h SDL2-2.30.11-banan_os/src
|
|||
extern VideoBootStrap PND_bootstrap;
|
||||
extern VideoBootStrap UIKIT_bootstrap;
|
||||
extern VideoBootStrap Android_bootstrap;
|
||||
diff -ruN SDL-release-2.30.11/src/video/SDL_video.c SDL2-2.30.11-banan_os/src/video/SDL_video.c
|
||||
diff -ruN SDL-release-2.30.11/src/video/SDL_video.c SDL-release-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
|
||||
+++ SDL2-2.30.11-banan_os/src/video/SDL_video.c 2025-08-03 14:04:09.896007237 +0300
|
||||
+++ SDL-release-2.30.11-banan_os/src/video/SDL_video.c 2025-06-24 19:37:36.342677687 +0300
|
||||
@@ -94,6 +94,9 @@
|
||||
#ifdef SDL_VIDEO_DRIVER_HAIKU
|
||||
&HAIKU_bootstrap,
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
#!/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/
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
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,9 +42,8 @@ fi
|
|||
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
|
||||
cp "$BANAN_TOOLCHAIN_DIR/meson-cross-file.in" "$MESON_CROSS_FILE"
|
||||
sed -i "s|ARCH|$BANAN_ARCH|" "$MESON_CROSS_FILE"
|
||||
sed -i "s|CMAKE|$BANAN_CMAKE|" "$MESON_CROSS_FILE"
|
||||
sed -i "s|SYSROOT|$BANAN_SYSROOT|" "$MESON_CROSS_FILE"
|
||||
sed -i "s/ARCH/$BANAN_ARCH/" "$MESON_CROSS_FILE"
|
||||
sed -i "s/SYSROOT/$BANAN_SYSROOT/" "$MESON_CROSS_FILE"
|
||||
fi
|
||||
|
||||
MAKE_BUILD_TARGETS=('all')
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
#!/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
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
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.
|
|
@ -1,12 +0,0 @@
|
|||
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;
|
|
@ -1,33 +0,0 @@
|
|||
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;
|
|
@ -1,13 +0,0 @@
|
|||
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))
|
|
@ -1,22 +0,0 @@
|
|||
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;
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
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;
|
|
@ -1,32 +0,0 @@
|
|||
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()
|
|
@ -1,34 +0,0 @@
|
|||
#!/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
|
||||
:
|
||||
}
|
|
@ -1,107 +0,0 @@
|
|||
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,6 +7,7 @@ DEPENDENCIES=('zlib' 'zstd' 'expat')
|
|||
CONFIGURE_OPTIONS=(
|
||||
'-Dprefix=/usr'
|
||||
'-Dosmesa=true'
|
||||
'-Dgallium-drivers=softpipe'
|
||||
'-Dvulkan-drivers=[]'
|
||||
'-Dplatforms=[]'
|
||||
'-Dglx=disabled'
|
||||
|
@ -14,50 +15,7 @@ CONFIGURE_OPTIONS=(
|
|||
)
|
||||
|
||||
configure() {
|
||||
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
|
||||
meson setup --reconfigure --cross-file "$MESON_CROSS_FILE" "${CONFIGURE_OPTIONS[@]}" build || exit 1
|
||||
}
|
||||
|
||||
build() {
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
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,7 +13,8 @@ CONFIGURE_OPTIONS=(
|
|||
'--with-shared'
|
||||
'--without-ada'
|
||||
'--without-manpages'
|
||||
CFLAGS='-std=c17'
|
||||
'--without-dlsym'
|
||||
'--without-cxx-binding'
|
||||
)
|
||||
|
||||
post_install() {
|
||||
|
|
|
@ -20,7 +20,7 @@ configure() {
|
|||
done
|
||||
popd
|
||||
|
||||
./waf configure -T release || exit 1
|
||||
./waf configure -T release --disable-gl || exit 1
|
||||
}
|
||||
|
||||
build() {
|
||||
|
@ -29,7 +29,6 @@ build() {
|
|||
|
||||
install() {
|
||||
./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
|
||||
#!/bin/Shell
|
||||
|
|
|
@ -1,20 +1,17 @@
|
|||
#!/bin/bash ../install.sh
|
||||
|
||||
NAME='zstd'
|
||||
VERSION='1.5.7'
|
||||
DOWNLOAD_URL="https://github.com/facebook/zstd/releases/download/v$VERSION/zstd-$VERSION.tar.gz#eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3"
|
||||
VERSION='1.5.6'
|
||||
DOWNLOAD_URL="https://github.com/facebook/zstd/releases/download/v$VERSION/zstd-$VERSION.tar.gz#8c29e06cf42aacc1eafc4077ae2ec6c6fcb96a626157e0593d5e82a34fd403c1"
|
||||
|
||||
configure() {
|
||||
$BANAN_CMAKE -B _build -S build/cmake -G Ninja \
|
||||
--toolchain $BANAN_TOOLCHAIN_DIR/Toolchain.txt \
|
||||
-DCMAKE_INSTALL_PREFIX=/usr \
|
||||
|| exit 1
|
||||
:
|
||||
}
|
||||
|
||||
build() {
|
||||
$BANAN_CMAKE --build _build ||exit 1
|
||||
make -C lib -j$(nproc) lib-nomt || exit 1
|
||||
}
|
||||
|
||||
install() {
|
||||
$BANAN_CMAKE --install _build ||exit 1
|
||||
make -C lib install "DESTDIR=$BANAN_SYSROOT" PREFIX=/usr || exit 1
|
||||
}
|
||||
|
|
|
@ -4,11 +4,13 @@ set -e
|
|||
export BANAN_SCRIPT_DIR=$(dirname $(realpath $0))
|
||||
source $BANAN_SCRIPT_DIR/config.sh
|
||||
|
||||
FAKEROOT_FILE="$BANAN_BUILD_DIR/fakeroot-context"
|
||||
|
||||
run_fakeroot() {
|
||||
if [ ! -f $BANAN_FAKEROOT ]; then
|
||||
touch $BANAN_FAKEROOT
|
||||
if [ ! -f $FAKEROOT_FILE ]; then
|
||||
touch $FAKEROOT_FILE
|
||||
fi
|
||||
fakeroot -i $BANAN_FAKEROOT -s $BANAN_FAKEROOT -- /bin/bash -c '$@' bash $@
|
||||
fakeroot -i $FAKEROOT_FILE -s $FAKEROOT_FILE -- /bin/bash -c '$@' bash $@
|
||||
}
|
||||
|
||||
make_build_dir () {
|
||||
|
@ -45,6 +47,11 @@ build_toolchain () {
|
|||
create_image () {
|
||||
build_target all
|
||||
build_target install
|
||||
|
||||
pushd $BANAN_SYSROOT >/dev/null
|
||||
run_fakeroot tar cf ${BANAN_SYSROOT_TAR} *
|
||||
popd >/dev/null
|
||||
|
||||
$BANAN_SCRIPT_DIR/image.sh "$1"
|
||||
}
|
||||
|
||||
|
|
|
@ -20,8 +20,7 @@ export BANAN_BUILD_DIR="$BANAN_ROOT_DIR/build"
|
|||
export BANAN_PORT_DIR="$BANAN_ROOT_DIR/ports"
|
||||
|
||||
export BANAN_SYSROOT="$BANAN_BUILD_DIR/sysroot"
|
||||
|
||||
export BANAN_FAKEROOT="$BANAN_BUILD_DIR/fakeroot-context"
|
||||
export BANAN_SYSROOT_TAR="$BANAN_SYSROOT.tar"
|
||||
|
||||
export BANAN_DISK_IMAGE_PATH="$BANAN_BUILD_DIR/banan-os.img"
|
||||
|
||||
|
|
|
@ -5,13 +5,8 @@ if [ -z $BANAN_DISK_IMAGE_PATH ]; then
|
|||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z $BANAN_SYSROOT ]; then
|
||||
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
|
||||
if [ -z $BANAN_SYSROOT_TAR ]; then
|
||||
echo "You must set the BANAN_SYSROOT_TAR environment variable" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
@ -39,33 +34,13 @@ fi
|
|||
|
||||
if sudo mount $ROOT_PARTITION $MOUNT_DIR; then
|
||||
if (($BANAN_INITRD)); then
|
||||
fakeroot -i $BANAN_FAKEROOT tar -C $BANAN_SYSROOT -cf $BANAN_SYSROOT.initrd .
|
||||
|
||||
sudo mkdir -p $MOUNT_DIR/boot
|
||||
sudo cp $BANAN_BUILD_DIR/kernel/banan-os.kernel $MOUNT_DIR/boot/banan-os.kernel
|
||||
sudo mv $BANAN_SYSROOT.initrd $MOUNT_DIR/boot/banan-os.initrd
|
||||
sudo cp $BANAN_SYSROOT_TAR $MOUNT_DIR/boot/banan-os.initrd
|
||||
else
|
||||
sudo rsync -rulHpt $BANAN_SYSROOT/ $MOUNT_DIR
|
||||
|
||||
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
|
||||
"
|
||||
cd $MOUNT_DIR
|
||||
sudo tar xf $BANAN_SYSROOT_TAR
|
||||
cd
|
||||
fi
|
||||
|
||||
sudo umount $MOUNT_DIR
|
||||
|
|
|
@ -1 +1 @@
|
|||
local/
|
||||
*/
|
||||
|
|
|
@ -8,10 +8,15 @@ if (NOT DEFINED ENV{BANAN_SYSROOT})
|
|||
endif ()
|
||||
set(BANAN_SYSROOT $ENV{BANAN_SYSROOT})
|
||||
|
||||
if (NOT DEFINED ENV{BANAN_TOOLCHAIN_PREFIX})
|
||||
message(FATAL_ERROR "environment variable BANAN_TOOLCHAIN_PREFIX not defined")
|
||||
if (NOT DEFINED ENV{BANAN_SYSROOT_TAR})
|
||||
message(FATAL_ERROR "environment variable BANAN_SYSROOT_TAR not defined")
|
||||
endif ()
|
||||
set(TOOLCHAIN_PREFIX $ENV{BANAN_TOOLCHAIN_PREFIX})
|
||||
set(BANAN_SYSROOT_TAR $ENV{BANAN_SYSROOT_TAR})
|
||||
|
||||
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_PROCESSOR ${BANAN_ARCH})
|
||||
|
|
|
@ -193,8 +193,6 @@ build_cmake() {
|
|||
|
||||
cp -r ./bin/* $BANAN_TOOLCHAIN_PREFIX/bin/
|
||||
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
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
include(Platform/banan-os-GNU)
|
||||
__banan_os_compiler_gnu(ASM)
|
|
@ -1,2 +0,0 @@
|
|||
include(Platform/banan-os-GNU)
|
||||
__banan_os_compiler_gnu(C)
|
|
@ -1,2 +0,0 @@
|
|||
include(Platform/banan-os-GNU)
|
||||
__banan_os_compiler_gnu(CXX)
|
|
@ -1,20 +0,0 @@
|
|||
# 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()
|
|
@ -1,2 +0,0 @@
|
|||
set(BANAN_OS 1)
|
||||
set(UNIX 1)
|
|
@ -1,9 +0,0 @@
|
|||
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,8 +11,7 @@ ar = 'ARCH-pc-banan_os-ar'
|
|||
ld = 'ARCH-pc-banan_os-ld'
|
||||
objcopy = 'ARCH-pc-banan_os-objcopy'
|
||||
strip = 'ARCH-pc-banan_os-strip'
|
||||
pkg-config = 'pkg-config'
|
||||
cmake = 'CMAKE'
|
||||
pkgconfig = 'pkg-config'
|
||||
|
||||
[properties]
|
||||
sys_root='SYSROOT'
|
||||
|
|
|
@ -20,7 +20,6 @@ set(LIBC_SOURCES
|
|||
malloc.cpp
|
||||
math.cpp
|
||||
netdb.cpp
|
||||
netinet/in.cpp
|
||||
poll.cpp
|
||||
printf_impl.cpp
|
||||
pthread.cpp
|
||||
|
@ -36,7 +35,6 @@ set(LIBC_SOURCES
|
|||
sys/banan-os.cpp
|
||||
sys/epoll.cpp
|
||||
sys/file.cpp
|
||||
sys/futex.cpp
|
||||
sys/ioctl.cpp
|
||||
sys/mman.cpp
|
||||
sys/resource.cpp
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
@ -110,54 +109,3 @@ void rewinddir(DIR* dirp)
|
|||
dirp->entry_index = 0;
|
||||
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,6 +1,8 @@
|
|||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
|
||||
extern uthread* _get_uthread();
|
||||
|
||||
int* __errno_location()
|
||||
{
|
||||
return &_get_uthread()->errno_;
|
||||
|
|
|
@ -1,213 +1,162 @@
|
|||
#include <BAN/StringView.h>
|
||||
#include <BAN/Vector.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <grp.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
static FILE* s_grent_fp = nullptr;
|
||||
static group s_grent_struct;
|
||||
static struct stat s_group_st;
|
||||
static char* s_group_mmap = nullptr;
|
||||
static int s_group_fd = -1;
|
||||
|
||||
static char* s_grent_buffer = nullptr;
|
||||
static size_t s_grent_buffer_size = 0;
|
||||
static struct group s_group;
|
||||
|
||||
void endgrent(void)
|
||||
id_t parse_id(BAN::StringView string)
|
||||
{
|
||||
if (s_grent_fp)
|
||||
fclose(s_grent_fp);
|
||||
s_grent_fp = nullptr;
|
||||
|
||||
if (s_grent_buffer)
|
||||
free(s_grent_buffer);
|
||||
s_grent_buffer = nullptr;
|
||||
}
|
||||
|
||||
void setgrent(void)
|
||||
{
|
||||
if (!s_grent_fp)
|
||||
return;
|
||||
fseek(s_grent_fp, 0, SEEK_SET);
|
||||
}
|
||||
|
||||
static int getgrent_impl(FILE* fp, struct group* grp, char* buffer, size_t bufsize, struct group** result)
|
||||
{
|
||||
for (;;)
|
||||
id_t id = 0;
|
||||
for (char c : string)
|
||||
{
|
||||
if (fgets(buffer, bufsize, fp) == nullptr)
|
||||
if (!isdigit(c))
|
||||
return -1;
|
||||
id = (id * 10) + (c - '0');
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
static bool open_group_file()
|
||||
{
|
||||
if (s_group_fd == -1)
|
||||
s_group_fd = open("/etc/group", O_RDONLY);
|
||||
if (s_group_fd == -1)
|
||||
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)
|
||||
{
|
||||
if (parts.size() != 4)
|
||||
return nullptr;
|
||||
|
||||
if (s_group.gr_name)
|
||||
{
|
||||
free(s_group.gr_name);
|
||||
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)
|
||||
{
|
||||
if (ferror(fp))
|
||||
return errno;
|
||||
*result = nullptr;
|
||||
return 0;
|
||||
for (size_t j = 0; j < i; j++)
|
||||
free(s_group.gr_mem[j]);
|
||||
free(s_group.gr_mem);
|
||||
s_group.gr_mem = nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
|
||||
struct group* getgrent(void)
|
||||
{
|
||||
if (s_grent_fp == nullptr)
|
||||
{
|
||||
s_grent_fp = fopen("/etc/group", "r");
|
||||
if (s_grent_fp == nullptr)
|
||||
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)
|
||||
{
|
||||
group* grp;
|
||||
setgrent();
|
||||
while ((grp = getgrent()))
|
||||
if (grp->gr_gid == gid)
|
||||
return grp;
|
||||
return nullptr;
|
||||
return &s_group;
|
||||
}
|
||||
|
||||
struct group* getgrnam(const char* name)
|
||||
{
|
||||
group* grp;
|
||||
setgrent();
|
||||
while ((grp = getgrent()))
|
||||
if (strcmp(grp->gr_name, name) == 0)
|
||||
return grp;
|
||||
if (s_group_mmap == nullptr || s_group_mmap == MAP_FAILED)
|
||||
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')
|
||||
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 && parts[0] == name)
|
||||
return fill_group(parts);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int getgrgid_r(gid_t gid, struct group* grp, char* buffer, size_t bufsize, struct group** result)
|
||||
struct group* getgrgid(gid_t gid)
|
||||
{
|
||||
FILE* fp = fopen("/etc/group", "r");
|
||||
if (fp == nullptr)
|
||||
return errno;
|
||||
if (s_group_mmap == nullptr || s_group_mmap == MAP_FAILED)
|
||||
if (!open_group_file())
|
||||
return nullptr;
|
||||
|
||||
int ret = 0;
|
||||
for (;;)
|
||||
off_t start = 0;
|
||||
off_t end = 0;
|
||||
while (start < s_group_st.st_size)
|
||||
{
|
||||
if ((ret = getgrent_impl(fp, grp, buffer, bufsize, result)))
|
||||
break;
|
||||
if (*result == nullptr)
|
||||
break;
|
||||
if (grp->gr_gid == gid)
|
||||
break;
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#include <stddef.h>
|
||||
#include <limits.h>
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
struct atexit_func_entry_t
|
||||
{
|
||||
|
@ -10,52 +8,19 @@ struct atexit_func_entry_t
|
|||
void* dso_handle;
|
||||
};
|
||||
|
||||
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 atexit_func_entry_t s_atexit_funcs[ATEXIT_MAX];
|
||||
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)
|
||||
{
|
||||
pthread_mutex_lock(&s_atexit_mutex);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (s_atexit_func_count >= ATEXIT_MAX)
|
||||
return -1;
|
||||
s_atexit_funcs[s_atexit_func_count++] = {
|
||||
.func = func,
|
||||
.arg = arg,
|
||||
.dso_handle = dso_handle,
|
||||
};
|
||||
|
||||
pthread_mutex_unlock(&s_atexit_mutex);
|
||||
return 0;
|
||||
|
||||
__cxa_atexit_error:
|
||||
pthread_mutex_unlock(&s_atexit_mutex);
|
||||
return -1;
|
||||
};
|
||||
|
||||
extern "C" void __cxa_finalize(void* dso_handle)
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
__BEGIN_DECLS
|
||||
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#define INET_ADDRSTRLEN 16
|
||||
#define INET6_ADDRSTRLEN 46
|
||||
|
|
|
@ -10,8 +10,6 @@ __BEGIN_DECLS
|
|||
#include <bits/types/pthread_attr_t.h>
|
||||
#include <bits/types/pthread_t.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef int pthread_once_t;
|
||||
|
||||
typedef unsigned pthread_key_t;
|
||||
|
@ -30,6 +28,17 @@ typedef struct
|
|||
unsigned lock_depth;
|
||||
} pthread_mutex_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int shared;
|
||||
} pthread_barrierattr_t;
|
||||
typedef struct
|
||||
{
|
||||
pthread_barrierattr_t attr;
|
||||
unsigned target;
|
||||
unsigned waiting;
|
||||
} pthread_barrier_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int clock;
|
||||
|
@ -38,7 +47,7 @@ typedef struct
|
|||
struct _pthread_cond_block
|
||||
{
|
||||
struct _pthread_cond_block* next;
|
||||
uint32_t futex;
|
||||
int signaled;
|
||||
};
|
||||
typedef struct
|
||||
{
|
||||
|
@ -47,20 +56,6 @@ typedef struct
|
|||
struct _pthread_cond_block* block_list;
|
||||
} 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
|
||||
{
|
||||
int shared;
|
||||
|
|
|
@ -13,16 +13,15 @@ __BEGIN_DECLS
|
|||
|
||||
struct group
|
||||
{
|
||||
char* gr_name; /* The name of the group. */
|
||||
char* gr_passwd;/* The password of the group */
|
||||
gid_t gr_gid; /* Numerical group ID. */
|
||||
char** gr_mem; /* Pointer to a null-terminated array of character pointers to member names. */
|
||||
char* gr_name; /* The name of the group. */
|
||||
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);
|
||||
struct group* getgrent(void);
|
||||
struct group* getgrgid(gid_t gid);
|
||||
int getgrgid_r(gid_t gid, struct group* grp, char* buffer, size_t bufsize, struct group** result);
|
||||
int getgrgit_r(gid_t gid, struct group* grp, char* buffer, size_t bufsize, struct group** result);
|
||||
struct group* getgrnam(const char* name);
|
||||
int getgrnam_r(const char* name, struct group* grp, char* buffer, size_t bufsize, struct group** result);
|
||||
void setgrent(void);
|
||||
|
|
|
@ -79,7 +79,7 @@ __BEGIN_DECLS
|
|||
#define LOGIN_NAME_MAX 256
|
||||
#define MQ_OPEN_MAX _POSIX_MQ_OPEN_MAX
|
||||
#define MQ_PRIO_MAX _POSIX_MQ_PRIO_MAX
|
||||
#define OPEN_MAX 128
|
||||
#define OPEN_MAX 64
|
||||
#define PAGESIZE PAGE_SIZE
|
||||
#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS
|
||||
#define PTHREAD_KEYS_MAX _POSIX_THREAD_KEYS_MAX
|
||||
|
|
|
@ -9,6 +9,7 @@ __BEGIN_DECLS
|
|||
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#define IPPORT_RESERVED 1024
|
||||
|
||||
|
|
|
@ -87,20 +87,6 @@ struct uthread
|
|||
#define _PTHREAD_ATFORK_CHILD 2
|
||||
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_attr_destroy(pthread_attr_t* attr);
|
||||
int pthread_attr_getdetachstate(const pthread_attr_t* attr, int* detachstate);
|
||||
|
|
|
@ -134,9 +134,8 @@ struct sigevent
|
|||
#define SA_NODEFER 0x040
|
||||
#define SS_ONSTACK 0x080
|
||||
#define SS_DISABLE 0x100
|
||||
|
||||
#define MINSIGSTKSZ 4096
|
||||
#define SIGSTKSZ 4096
|
||||
#define MINSIGSTKSZ 0x200
|
||||
#define SIGSTKSZ 0x400
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
|
|
@ -44,7 +44,6 @@ void _Exit(int status) __attribute__((__noreturn__));
|
|||
long a64l(const char* s);
|
||||
void abort(void) __attribute__((__noreturn__));
|
||||
int abs(int i);
|
||||
void* aligned_alloc(size_t alignment, size_t size);
|
||||
int atexit(void (*func)(void));
|
||||
double atof(const char* str);
|
||||
int atoi(const char* str);
|
||||
|
|
|
@ -1,45 +0,0 @@
|
|||
#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,7 +16,6 @@ __BEGIN_DECLS
|
|||
#define MAP_PRIVATE 0x02
|
||||
#define MAP_SHARED 0x04
|
||||
#define MAP_ANONYMOUS 0x08
|
||||
#define MAP_ANON MAP_ANONYMOUS
|
||||
|
||||
#define MS_ASYNC 0x01
|
||||
#define MS_INVALIDATE 0x02
|
||||
|
|
|
@ -25,7 +25,7 @@ __BEGIN_DECLS
|
|||
struct sockaddr
|
||||
{
|
||||
sa_family_t sa_family; /* Address family. */
|
||||
char sa_data[0]; /* Socket address (variable-length data). */
|
||||
char sa_data[]; /* Socket address (variable-length data). */
|
||||
};
|
||||
|
||||
struct sockaddr_storage
|
||||
|
|
|
@ -52,7 +52,6 @@ __BEGIN_DECLS
|
|||
O(SYS_SYNC, sync) \
|
||||
O(SYS_MMAP, mmap) \
|
||||
O(SYS_MUNMAP, munmap) \
|
||||
O(SYS_MPROTECT, mprotect) \
|
||||
O(SYS_TTY_CTRL, tty_ctrl) \
|
||||
O(SYS_POWEROFF, poweroff) \
|
||||
O(SYS_FCHMODAT, fchmodat) \
|
||||
|
@ -109,8 +108,6 @@ __BEGIN_DECLS
|
|||
O(SYS_EPOLL_CTL, epoll_ctl) \
|
||||
O(SYS_EPOLL_PWAIT2, epoll_pwait2) \
|
||||
O(SYS_FLOCK, flock) \
|
||||
O(SYS_GET_NPROCESSOR, get_nprocessor) \
|
||||
O(SYS_FUTEX, futex) \
|
||||
|
||||
enum Syscall
|
||||
{
|
||||
|
|
|
@ -342,10 +342,6 @@ enum
|
|||
#define _SC_MQ_PRIO_MAX _SC_MQ_PRIO_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,
|
||||
#define _SC_OPEN_MAX _SC_OPEN_MAX
|
||||
_SC_PAGE_SIZE,
|
||||
|
|
|
@ -338,14 +338,14 @@ void* calloc(size_t nmemb, size_t size)
|
|||
return ptr;
|
||||
}
|
||||
|
||||
void* aligned_alloc(size_t alignment, size_t size)
|
||||
int posix_memalign(void** memptr, size_t alignment, size_t size)
|
||||
{
|
||||
dprintln_if(DEBUG_MALLOC, "aligned_alloc({}, {})", alignment, size);
|
||||
dprintln_if(DEBUG_MALLOC, "posix_memalign({}, {})", alignment, size);
|
||||
|
||||
if (alignment < sizeof(void*) || alignment % sizeof(void*) || !BAN::Math::is_power_of_two(alignment / sizeof(void*)))
|
||||
{
|
||||
errno = EINVAL;
|
||||
return nullptr;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (alignment < s_malloc_default_align)
|
||||
|
@ -353,7 +353,7 @@ void* aligned_alloc(size_t alignment, size_t size)
|
|||
|
||||
void* unaligned = malloc(size + alignment + sizeof(malloc_node_t));
|
||||
if (unaligned == nullptr)
|
||||
return nullptr;
|
||||
return -1;
|
||||
|
||||
pthread_mutex_lock(&s_malloc_mutex);
|
||||
|
||||
|
@ -395,11 +395,6 @@ void* aligned_alloc(size_t alignment, size_t size)
|
|||
pthread_mutex_unlock(&s_malloc_mutex);
|
||||
|
||||
assert(((uintptr_t)node->data & (alignment - 1)) == 0);
|
||||
return node->data;
|
||||
}
|
||||
|
||||
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;
|
||||
*memptr = node->data;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
#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,7 +10,6 @@
|
|||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/futex.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
|
@ -55,6 +54,17 @@ extern "C" void _pthread_trampoline_cpp(void* arg)
|
|||
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)
|
||||
{
|
||||
if (uthread->dtv[0] == 0)
|
||||
|
@ -95,95 +105,58 @@ void pthread_cleanup_push(void (*routine)(void*), void* arg)
|
|||
uthread->cleanup_stack = cleanup;
|
||||
}
|
||||
|
||||
static thread_local struct
|
||||
{
|
||||
static thread_local struct {
|
||||
void* value;
|
||||
pthread_key_t key;
|
||||
} s_pthread_key_values[PTHREAD_KEYS_MAX] {};
|
||||
void (*destructor)(void*);
|
||||
} s_pthread_keys[PTHREAD_KEYS_MAX] {};
|
||||
static thread_local uint8_t s_pthread_keys_allocated[(PTHREAD_KEYS_MAX + 7) / 8];
|
||||
|
||||
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;
|
||||
static inline bool is_pthread_key_allocated(pthread_key_t key)
|
||||
{
|
||||
if (key >= PTHREAD_KEYS_MAX)
|
||||
return false;
|
||||
return s_pthread_keys_allocated[key / 8] & (1 << (key % 8));
|
||||
}
|
||||
|
||||
int pthread_key_create(pthread_key_t* key, void (*destructor)(void*))
|
||||
{
|
||||
int ret = EAGAIN;
|
||||
|
||||
pthread_spin_lock(&s_pthread_key_lock);
|
||||
for (size_t i = 0; i < PTHREAD_KEYS_MAX; i++)
|
||||
for (pthread_key_t i = 0; i < PTHREAD_KEYS_MAX; i++)
|
||||
{
|
||||
if (s_pthread_key_map[i])
|
||||
if (is_pthread_key_allocated(i))
|
||||
continue;
|
||||
s_pthread_key_destructors[i] = destructor;
|
||||
s_pthread_key_map[i] = *key = s_pthread_key_current++;
|
||||
ret = 0;
|
||||
break;
|
||||
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;
|
||||
}
|
||||
pthread_spin_unlock(&s_pthread_key_lock);
|
||||
|
||||
return ret;
|
||||
return EAGAIN;
|
||||
}
|
||||
|
||||
int pthread_key_delete(pthread_key_t key)
|
||||
{
|
||||
int ret = EINVAL;
|
||||
|
||||
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;
|
||||
s_pthread_key_destructors[i] = nullptr;
|
||||
s_pthread_key_map[i] = 0;
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
pthread_spin_unlock(&s_pthread_key_lock);
|
||||
|
||||
return ret;
|
||||
if (!is_pthread_key_allocated(key))
|
||||
return EINVAL;
|
||||
s_pthread_keys[key].value = nullptr;
|
||||
s_pthread_keys[key].destructor = nullptr;
|
||||
s_pthread_keys_allocated[key / 8] &= ~(1 << (key % 8));
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* pthread_getspecific(pthread_key_t key)
|
||||
{
|
||||
void* ret = nullptr;
|
||||
|
||||
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;
|
||||
if (!is_pthread_key_allocated(key))
|
||||
return nullptr;
|
||||
return s_pthread_keys[key].value;
|
||||
}
|
||||
|
||||
int pthread_setspecific(pthread_key_t key, const void* value)
|
||||
{
|
||||
int ret = EINVAL;
|
||||
|
||||
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 = const_cast<void*>(value);
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
pthread_spin_unlock(&s_pthread_key_lock);
|
||||
|
||||
return ret;
|
||||
if (!is_pthread_key_allocated(key))
|
||||
return EINVAL;
|
||||
s_pthread_keys[key].value = const_cast<void*>(value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_attr_destroy(pthread_attr_t* attr)
|
||||
|
@ -441,22 +414,15 @@ void pthread_exit(void* value_ptr)
|
|||
for (size_t iteration = 0; iteration < PTHREAD_DESTRUCTOR_ITERATIONS; iteration++)
|
||||
{
|
||||
bool called = false;
|
||||
for (size_t i = 0; i < PTHREAD_KEYS_MAX; i++)
|
||||
for (pthread_key_t i = 0; i < PTHREAD_KEYS_MAX; 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)
|
||||
if (!is_pthread_key_allocated(i))
|
||||
continue;
|
||||
destructor(value);
|
||||
if (!s_pthread_keys[i].value || !s_pthread_keys[i].destructor)
|
||||
continue;
|
||||
void* old_value = s_pthread_keys[i].value;
|
||||
s_pthread_keys[i].value = nullptr;
|
||||
s_pthread_keys[i].destructor(old_value);
|
||||
called = true;
|
||||
}
|
||||
if (!called)
|
||||
|
@ -476,14 +442,7 @@ int pthread_equal(pthread_t t1, pthread_t t2)
|
|||
int pthread_join(pthread_t thread, void** value_ptr)
|
||||
{
|
||||
pthread_testcancel();
|
||||
|
||||
errno = 0;
|
||||
while (syscall(SYS_PTHREAD_JOIN, thread, value_ptr) == -1 && errno == EINTR)
|
||||
{
|
||||
pthread_testcancel();
|
||||
errno = 0;
|
||||
}
|
||||
return errno;
|
||||
return syscall(SYS_PTHREAD_JOIN, thread, value_ptr);
|
||||
}
|
||||
|
||||
pthread_t pthread_self(void)
|
||||
|
@ -519,9 +478,6 @@ static pthread_mutex_t s_atfork_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|||
|
||||
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_atfork_t* list = nullptr;
|
||||
|
@ -1114,12 +1070,7 @@ int pthread_cond_broadcast(pthread_cond_t* cond)
|
|||
{
|
||||
pthread_spin_lock(&cond->lock);
|
||||
for (auto* block = cond->block_list; block; block = block->next)
|
||||
{
|
||||
BAN::atomic_store(block->futex, 1);
|
||||
|
||||
const int op = FUTEX_WAKE | (cond->attr.shared ? 0 : FUTEX_PRIVATE);
|
||||
futex(op, &block->futex, 1, nullptr);
|
||||
}
|
||||
BAN::atomic_store(block->signaled, 1);
|
||||
pthread_spin_unlock(&cond->lock);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1127,13 +1078,8 @@ int pthread_cond_broadcast(pthread_cond_t* cond)
|
|||
int pthread_cond_signal(pthread_cond_t* cond)
|
||||
{
|
||||
pthread_spin_lock(&cond->lock);
|
||||
if (auto* block = cond->block_list)
|
||||
{
|
||||
BAN::atomic_store(block->futex, 1);
|
||||
|
||||
const int op = FUTEX_WAKE | (cond->attr.shared ? 0 : FUTEX_PRIVATE);
|
||||
futex(op, &block->futex, 1, nullptr);
|
||||
}
|
||||
if (cond->block_list)
|
||||
BAN::atomic_store(cond->block_list->signaled, 1);
|
||||
pthread_spin_unlock(&cond->lock);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1148,26 +1094,35 @@ int pthread_cond_timedwait(pthread_cond_t* __restrict cond, pthread_mutex_t* __r
|
|||
{
|
||||
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_cond_block block = {
|
||||
.next = cond->block_list,
|
||||
.futex = 0,
|
||||
.signaled = 0,
|
||||
};
|
||||
cond->block_list = █
|
||||
pthread_spin_unlock(&cond->lock);
|
||||
|
||||
pthread_mutex_unlock(mutex);
|
||||
|
||||
while (BAN::atomic_load(block.futex) == 0)
|
||||
while (BAN::atomic_load(block.signaled) == 0)
|
||||
{
|
||||
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);
|
||||
if (has_timed_out(abstime, cond->attr.clock))
|
||||
return ETIMEDOUT;
|
||||
}
|
||||
sched_yield();
|
||||
}
|
||||
|
||||
pthread_spin_lock(&cond->lock);
|
||||
|
@ -1237,34 +1192,28 @@ int pthread_barrier_init(pthread_barrier_t* __restrict barrier, const pthread_ba
|
|||
attr = &default_attr;
|
||||
*barrier = {
|
||||
.attr = *attr,
|
||||
.lock = PTHREAD_MUTEX_INITIALIZER,
|
||||
.cond = PTHREAD_COND_INITIALIZER,
|
||||
.target = count,
|
||||
.waiting = 0,
|
||||
.generation = 0,
|
||||
};
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_barrier_wait(pthread_barrier_t* barrier)
|
||||
{
|
||||
pthread_mutex_lock(&barrier->lock);
|
||||
const unsigned index = BAN::atomic_add_fetch(barrier->waiting, 1);
|
||||
|
||||
const auto gen = barrier->generation;
|
||||
barrier->waiting++;
|
||||
// FIXME: this case should be handled, but should be relatively uncommon
|
||||
// so i'll just roll with the easy implementation
|
||||
ASSERT(index <= barrier->target);
|
||||
|
||||
if (barrier->waiting == barrier->target)
|
||||
if (index == barrier->target)
|
||||
{
|
||||
barrier->waiting = 0;
|
||||
barrier->generation++;
|
||||
pthread_cond_broadcast(&barrier->cond);
|
||||
pthread_mutex_unlock(&barrier->lock);
|
||||
BAN::atomic_store(barrier->waiting, 0);
|
||||
return PTHREAD_BARRIER_SERIAL_THREAD;
|
||||
}
|
||||
|
||||
while (barrier->generation == gen)
|
||||
pthread_cond_wait(&barrier->cond, &barrier->lock);
|
||||
pthread_mutex_unlock(&barrier->lock);
|
||||
while (BAN::atomic_load(barrier->waiting))
|
||||
sched_yield();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,142 +1,118 @@
|
|||
#include <BAN/Assert.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <pwd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static FILE* s_pwent_fp = nullptr;
|
||||
static passwd s_pwent_struct;
|
||||
|
||||
static char* s_pwent_buffer = nullptr;
|
||||
static size_t s_pwent_buffer_size = 0;
|
||||
static bool open_pwent()
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
return;
|
||||
fseek(s_pwent_fp, 0, SEEK_SET);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
fclose(s_pwent_fp);
|
||||
s_pwent_fp = nullptr;
|
||||
clear_pwent(s_pwent_struct);
|
||||
}
|
||||
|
||||
struct passwd* getpwent(void)
|
||||
{
|
||||
if (s_pwent_fp == nullptr)
|
||||
{
|
||||
s_pwent_fp = fopen("/etc/passwd", "r");
|
||||
if (s_pwent_fp == nullptr)
|
||||
if (!s_pwent_fp)
|
||||
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, ':');
|
||||
ASSERT((i < 6) ? end != nullptr : end == nullptr);
|
||||
if (!end)
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
return &s_pwent_struct;
|
||||
}
|
||||
|
||||
struct passwd* getpwnam(const char* name)
|
||||
|
@ -159,44 +135,9 @@ struct passwd* getpwuid(uid_t uid)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
int getpwuid_r(uid_t uid, struct passwd* pwd, char* buffer, size_t bufsize, struct passwd** result)
|
||||
void setpwent(void)
|
||||
{
|
||||
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 (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;
|
||||
if (!s_pwent_fp)
|
||||
return;
|
||||
fseek(s_pwent_fp, 0, SEEK_SET);
|
||||
}
|
||||
|
|
|
@ -542,9 +542,6 @@ int getc_unlocked(FILE* file)
|
|||
if (file->eof)
|
||||
return EOF;
|
||||
|
||||
if (file == stdin && file->buffer_type == _IOLBF && stdout->buffer_type == _IOLBF && stdout->buffer_idx)
|
||||
fflush(stdout);
|
||||
|
||||
// read characters from ungetc
|
||||
if (file->unget_buf_idx)
|
||||
{
|
||||
|
|
|
@ -570,45 +570,6 @@ int mblen(const char* s, size_t n)
|
|||
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 written = 0;
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
#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,11 +24,6 @@ int munmap(void* addr, size_t 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)
|
||||
{
|
||||
pthread_testcancel();
|
||||
|
@ -50,3 +45,8 @@ int mlock(const void*, size_t)
|
|||
{
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
int mprotect(void*, size_t, int)
|
||||
{
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
#include <BAN/Debug.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/syscall.h>
|
||||
|
@ -36,7 +33,7 @@ int listen(int socket, int backlog)
|
|||
|
||||
ssize_t recv(int socket, void* __restrict buffer, size_t length, int flags)
|
||||
{
|
||||
// cancellation point in recvfrom
|
||||
pthread_testcancel();
|
||||
return recvfrom(socket, buffer, length, flags, nullptr, nullptr);
|
||||
}
|
||||
|
||||
|
@ -56,7 +53,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)
|
||||
{
|
||||
// cancellation point in sendto
|
||||
pthread_testcancel();
|
||||
return sendto(socket, message, length, flags, nullptr, 0);
|
||||
}
|
||||
|
||||
|
@ -74,74 +71,6 @@ ssize_t sendto(int socket, const void* message, size_t length, int flags, const
|
|||
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)
|
||||
{
|
||||
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;
|
||||
for (int i = 0; i < iovcnt; i++)
|
||||
{
|
||||
uint8_t* base = static_cast<uint8_t*>(iov[i].iov_base);
|
||||
uint8_t* base = static_cast<uint8_t*>(iov->iov_base);
|
||||
|
||||
size_t nread = 0;
|
||||
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;
|
||||
for (int i = 0; i < iovcnt; i++)
|
||||
{
|
||||
const uint8_t* base = static_cast<const uint8_t*>(iov[i].iov_base);
|
||||
const uint8_t* base = static_cast<const uint8_t*>(iov->iov_base);
|
||||
|
||||
size_t nwrite = 0;
|
||||
while (nwrite < iov[i].iov_len)
|
||||
|
|
|
@ -787,19 +787,12 @@ char* getlogin(void)
|
|||
|
||||
char* ttyname(int fildes)
|
||||
{
|
||||
static char storage[TTY_NAME_MAX];
|
||||
if (ttyname_r(fildes, storage, sizeof(storage)) != 0)
|
||||
static char storage[_POSIX_TTY_NAME_MAX];
|
||||
if (syscall(SYS_TTYNAME, fildes, storage) == -1)
|
||||
return nullptr;
|
||||
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)
|
||||
{
|
||||
return syscall(SYS_ACCESS, path, amode);
|
||||
|
@ -882,35 +875,7 @@ size_t confstr(int name, char* buf, size_t len)
|
|||
return 0;
|
||||
}
|
||||
|
||||
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 pathconf(const char* path, int name);
|
||||
|
||||
long sysconf(int name)
|
||||
{
|
||||
|
@ -1050,9 +1015,6 @@ long sysconf(int name)
|
|||
case _SC_PAGE_SIZE:
|
||||
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_GETGR_R_SIZE_MAX: return 1024;
|
||||
case _SC_GETPW_R_SIZE_MAX: return 1024;
|
||||
|
|
|
@ -142,10 +142,10 @@ namespace LibGUI
|
|||
return on_socket_error(__FUNCTION__);
|
||||
}
|
||||
|
||||
void Window::set_mouse_relative(bool enabled)
|
||||
void Window::set_mouse_capture(bool captured)
|
||||
{
|
||||
WindowPacket::WindowSetMouseRelative packet;
|
||||
packet.enabled = enabled;
|
||||
WindowPacket::WindowSetMouseCapture packet;
|
||||
packet.captured = captured;
|
||||
|
||||
if (auto ret = packet.send_serialized(m_server_fd); ret.is_error())
|
||||
return on_socket_error(__FUNCTION__);
|
||||
|
|
|
@ -205,7 +205,7 @@ namespace LibGUI
|
|||
WindowInvalidate,
|
||||
WindowSetPosition,
|
||||
WindowSetAttributes,
|
||||
WindowSetMouseRelative,
|
||||
WindowSetMouseCapture,
|
||||
WindowSetSize,
|
||||
WindowSetMinSize,
|
||||
WindowSetMaxSize,
|
||||
|
@ -266,8 +266,8 @@ namespace LibGUI
|
|||
);
|
||||
|
||||
DEFINE_PACKET(
|
||||
WindowSetMouseRelative,
|
||||
bool, enabled
|
||||
WindowSetMouseCapture,
|
||||
bool, captured
|
||||
);
|
||||
|
||||
DEFINE_PACKET(
|
||||
|
|
|
@ -43,7 +43,7 @@ namespace LibGUI
|
|||
void invalidate(int32_t x, int32_t y, uint32_t width, uint32_t height);
|
||||
void invalidate() { return invalidate(0, 0, width(), height()); }
|
||||
|
||||
void set_mouse_relative(bool enabled);
|
||||
void set_mouse_capture(bool captured);
|
||||
void set_fullscreen(bool fullscreen);
|
||||
void set_title(BAN::StringView title);
|
||||
|
||||
|
|
|
@ -1200,32 +1200,21 @@ static void initialize_tls(MasterTLS master_tls)
|
|||
|
||||
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 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;
|
||||
uthread->dtv[0] = master_tls.module_count;
|
||||
for (size_t i = 0; i < s_loaded_file_count; i++)
|
||||
{
|
||||
const auto& elf = s_loaded_files[i];
|
||||
if (elf.tls_addr == nullptr)
|
||||
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)
|
||||
|
@ -1363,9 +1352,6 @@ void* __dlopen(const char* file, int mode)
|
|||
|
||||
// FIXME: RTLD_{LOCAL,GLOBAL}
|
||||
|
||||
if (file == nullptr)
|
||||
return &s_loaded_files[0];
|
||||
|
||||
char path_buffer[PATH_MAX];
|
||||
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());
|
||||
}
|
||||
|
||||
void WindowServer::on_window_set_mouse_relative(int fd, const LibGUI::WindowPacket::WindowSetMouseRelative& packet)
|
||||
void WindowServer::on_window_set_mouse_capture(int fd, const LibGUI::WindowPacket::WindowSetMouseCapture& packet)
|
||||
{
|
||||
if (m_is_mouse_relative && packet.enabled)
|
||||
if (m_is_mouse_captured && packet.captured)
|
||||
{
|
||||
ASSERT(m_focused_window);
|
||||
if (fd != m_focused_window->client_fd())
|
||||
dwarnln("client tried to set mouse relative while other window has it already");
|
||||
dwarnln("client tried to set mouse capture while other window has it already captured");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -221,11 +221,11 @@ void WindowServer::on_window_set_mouse_relative(int fd, const LibGUI::WindowPack
|
|||
return;
|
||||
}
|
||||
|
||||
if (packet.enabled == m_is_mouse_relative)
|
||||
if (packet.captured == m_is_mouse_captured)
|
||||
return;
|
||||
|
||||
set_focused_window(target_window);
|
||||
m_is_mouse_relative = packet.enabled;
|
||||
m_is_mouse_captured = packet.captured;
|
||||
invalidate(cursor_area());
|
||||
}
|
||||
|
||||
|
@ -490,7 +490,7 @@ void WindowServer::on_key_event(LibInput::KeyEvent event)
|
|||
|
||||
void WindowServer::on_mouse_button(LibInput::MouseButtonEvent event)
|
||||
{
|
||||
if (m_is_mouse_relative)
|
||||
if (m_is_mouse_captured)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (m_is_mouse_relative)
|
||||
if (m_is_mouse_captured)
|
||||
{
|
||||
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_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);
|
||||
}
|
||||
|
||||
|
@ -724,12 +724,6 @@ void WindowServer::on_mouse_move_abs(LibInput::MouseMoveAbsEvent event)
|
|||
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_y, out_max_y;
|
||||
|
||||
|
@ -773,9 +767,9 @@ void WindowServer::set_focused_window(BAN::RefPtr<Window> window)
|
|||
if (m_focused_window == window)
|
||||
return;
|
||||
|
||||
if (m_is_mouse_relative)
|
||||
if (m_is_mouse_captured)
|
||||
{
|
||||
m_is_mouse_relative = false;
|
||||
m_is_mouse_captured = false;
|
||||
invalidate(cursor_area());
|
||||
}
|
||||
|
||||
|
@ -909,7 +903,7 @@ void WindowServer::invalidate(Rectangle area)
|
|||
mark_pending_sync(dst_area);
|
||||
}
|
||||
|
||||
if (!m_is_mouse_relative)
|
||||
if (!m_is_mouse_captured)
|
||||
{
|
||||
auto cursor_area = this->cursor_area();
|
||||
cursor_area.x -= m_focused_window->client_x();
|
||||
|
@ -1146,7 +1140,7 @@ void WindowServer::invalidate(Rectangle area)
|
|||
}
|
||||
}
|
||||
|
||||
if (!m_is_mouse_relative)
|
||||
if (!m_is_mouse_captured)
|
||||
{
|
||||
if (const auto overlap = cursor_area().get_overlap(area); overlap.has_value())
|
||||
{
|
||||
|
@ -1361,8 +1355,8 @@ BAN::RefPtr<Window> WindowServer::find_window_with_fd(int fd) const
|
|||
|
||||
BAN::RefPtr<Window> WindowServer::find_hovered_window() const
|
||||
{
|
||||
for (size_t i = m_client_windows.size(); i > 0; i--)
|
||||
if (auto window = m_client_windows[i - 1]; window->client_area().contains(m_cursor))
|
||||
for (auto window : m_client_windows)
|
||||
if (window->full_area().contains(m_cursor))
|
||||
return window;
|
||||
return {};
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ public:
|
|||
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_attributes(int fd, const LibGUI::WindowPacket::WindowSetAttributes&);
|
||||
void on_window_set_mouse_relative(int fd, const LibGUI::WindowPacket::WindowSetMouseRelative&);
|
||||
void on_window_set_mouse_capture(int fd, const LibGUI::WindowPacket::WindowSetMouseCapture&);
|
||||
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_max_size(int fd, const LibGUI::WindowPacket::WindowSetMaxSize&);
|
||||
|
@ -112,7 +112,7 @@ private:
|
|||
uint8_t m_resize_quadrant { 0 };
|
||||
Position m_resize_start;
|
||||
|
||||
bool m_is_mouse_relative { false };
|
||||
bool m_is_mouse_captured { false };
|
||||
|
||||
bool m_deleted_window { 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()) \
|
||||
window_server.function(fd, ret.release_value()); \
|
||||
break
|
||||
WINDOW_PACKET_CASE(WindowCreate, on_window_create);
|
||||
WINDOW_PACKET_CASE(WindowInvalidate, on_window_invalidate);
|
||||
WINDOW_PACKET_CASE(WindowSetPosition, on_window_set_position);
|
||||
WINDOW_PACKET_CASE(WindowSetAttributes, on_window_set_attributes);
|
||||
WINDOW_PACKET_CASE(WindowSetMouseRelative, on_window_set_mouse_relative);
|
||||
WINDOW_PACKET_CASE(WindowSetSize, on_window_set_size);
|
||||
WINDOW_PACKET_CASE(WindowSetMinSize, on_window_set_min_size);
|
||||
WINDOW_PACKET_CASE(WindowSetMaxSize, on_window_set_max_size);
|
||||
WINDOW_PACKET_CASE(WindowSetFullscreen, on_window_set_fullscreen);
|
||||
WINDOW_PACKET_CASE(WindowSetTitle, on_window_set_title);
|
||||
WINDOW_PACKET_CASE(WindowSetCursor, on_window_set_cursor);
|
||||
WINDOW_PACKET_CASE(WindowCreate, on_window_create);
|
||||
WINDOW_PACKET_CASE(WindowInvalidate, on_window_invalidate);
|
||||
WINDOW_PACKET_CASE(WindowSetPosition, on_window_set_position);
|
||||
WINDOW_PACKET_CASE(WindowSetAttributes, on_window_set_attributes);
|
||||
WINDOW_PACKET_CASE(WindowSetMouseCapture, on_window_set_mouse_capture);
|
||||
WINDOW_PACKET_CASE(WindowSetSize, on_window_set_size);
|
||||
WINDOW_PACKET_CASE(WindowSetMinSize, on_window_set_min_size);
|
||||
WINDOW_PACKET_CASE(WindowSetMaxSize, on_window_set_max_size);
|
||||
WINDOW_PACKET_CASE(WindowSetFullscreen, on_window_set_fullscreen);
|
||||
WINDOW_PACKET_CASE(WindowSetTitle, on_window_set_title);
|
||||
WINDOW_PACKET_CASE(WindowSetCursor, on_window_set_cursor);
|
||||
#undef WINDOW_PACKET_CASE
|
||||
default:
|
||||
dprintln("unhandled packet type: {}", *reinterpret_cast<uint32_t*>(client_data.packet_buffer.data()));
|
||||
|
|
Loading…
Reference in New Issue