Compare commits
17 Commits
4af9699b22
...
5d62fa3f10
| Author | SHA1 | Date |
|---|---|---|
|
|
5d62fa3f10 | |
|
|
d3df00f0ba | |
|
|
34e84f8b07 | |
|
|
1143dc3cae | |
|
|
0299d4d44e | |
|
|
1d07151743 | |
|
|
a83fa6f4c6 | |
|
|
c30fc9d60f | |
|
|
311a68160c | |
|
|
343aef31c3 | |
|
|
3ac8f7e14f | |
|
|
0cef66d155 | |
|
|
9ffbb9fbf0 | |
|
|
c9a8f5b456 | |
|
|
4e3831e380 | |
|
|
cae2b3bd14 | |
|
|
5637b8602b |
|
|
@ -221,7 +221,7 @@ namespace Kernel
|
|||
ASSERT(!(pt[pte] & Flags::Present));
|
||||
pt[pte] = paddr | Flags::ReadWrite | Flags::Present;
|
||||
|
||||
invalidate(fast_page(), false);
|
||||
asm volatile("invlpg (%0)" :: "r"(fast_page()) : "memory");
|
||||
}
|
||||
|
||||
void PageTable::unmap_fast_page()
|
||||
|
|
@ -241,7 +241,7 @@ namespace Kernel
|
|||
ASSERT(pt[pte] & Flags::Present);
|
||||
pt[pte] = 0;
|
||||
|
||||
invalidate(fast_page(), false);
|
||||
asm volatile("invlpg (%0)" :: "r"(fast_page()) : "memory");
|
||||
}
|
||||
|
||||
BAN::ErrorOr<PageTable*> PageTable::create_userspace()
|
||||
|
|
@ -314,7 +314,8 @@ namespace Kernel
|
|||
.type = Processor::SMPMessage::Type::FlushTLB,
|
||||
.flush_tlb = {
|
||||
.vaddr = vaddr,
|
||||
.page_count = 1
|
||||
.page_count = 1,
|
||||
.page_table = vaddr < KERNEL_OFFSET ? this : nullptr,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -343,8 +344,12 @@ namespace Kernel
|
|||
uint64_t* pd = reinterpret_cast<uint64_t*>(P2V(pdpt[pdpte] & PAGE_ADDR_MASK));
|
||||
uint64_t* pt = reinterpret_cast<uint64_t*>(P2V(pd[pde] & PAGE_ADDR_MASK));
|
||||
|
||||
const paddr_t old_paddr = pt[pte] & PAGE_ADDR_MASK;
|
||||
|
||||
pt[pte] = 0;
|
||||
invalidate(vaddr, send_smp_message);
|
||||
|
||||
if (old_paddr != 0)
|
||||
invalidate(vaddr, send_smp_message);
|
||||
}
|
||||
|
||||
void PageTable::unmap_range(vaddr_t vaddr, size_t size)
|
||||
|
|
@ -361,7 +366,8 @@ namespace Kernel
|
|||
.type = Processor::SMPMessage::Type::FlushTLB,
|
||||
.flush_tlb = {
|
||||
.vaddr = vaddr,
|
||||
.page_count = page_count
|
||||
.page_count = page_count,
|
||||
.page_table = vaddr < KERNEL_OFFSET ? this : nullptr,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -417,9 +423,13 @@ namespace Kernel
|
|||
uwr_flags &= ~Flags::Present;
|
||||
|
||||
uint64_t* pt = reinterpret_cast<uint64_t*>(P2V(pd[pde] & PAGE_ADDR_MASK));
|
||||
|
||||
const paddr_t old_paddr = pt[pte] & PAGE_ADDR_MASK;
|
||||
|
||||
pt[pte] = paddr | uwr_flags | extra_flags;
|
||||
|
||||
invalidate(vaddr, send_smp_message);
|
||||
if (old_paddr != 0)
|
||||
invalidate(vaddr, send_smp_message);
|
||||
}
|
||||
|
||||
void PageTable::map_range_at(paddr_t paddr, vaddr_t vaddr, size_t size, flags_t flags, MemoryType memory_type)
|
||||
|
|
@ -438,7 +448,8 @@ namespace Kernel
|
|||
.type = Processor::SMPMessage::Type::FlushTLB,
|
||||
.flush_tlb = {
|
||||
.vaddr = vaddr,
|
||||
.page_count = page_count
|
||||
.page_count = page_count,
|
||||
.page_table = vaddr < KERNEL_OFFSET ? this : nullptr,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -523,6 +534,7 @@ namespace Kernel
|
|||
.flush_tlb = {
|
||||
.vaddr = vaddr,
|
||||
.page_count = bytes / PAGE_SIZE,
|
||||
.page_table = vaddr < KERNEL_OFFSET ? this : nullptr,
|
||||
}
|
||||
});
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -521,7 +521,7 @@ namespace Kernel
|
|||
ASSERT(!(pt[pte] & Flags::Present));
|
||||
pt[pte] = paddr | Flags::ReadWrite | Flags::Present;
|
||||
|
||||
invalidate(fast_page(), false);
|
||||
asm volatile("invlpg (%0)" :: "r"(fast_page()) : "memory");
|
||||
}
|
||||
|
||||
void PageTable::unmap_fast_page()
|
||||
|
|
@ -544,7 +544,7 @@ namespace Kernel
|
|||
ASSERT(pt[pte] & Flags::Present);
|
||||
pt[pte] = 0;
|
||||
|
||||
invalidate(fast_page(), false);
|
||||
asm volatile("invlpg (%0)" :: "r"(fast_page()) : "memory");
|
||||
}
|
||||
|
||||
BAN::ErrorOr<PageTable*> PageTable::create_userspace()
|
||||
|
|
@ -623,7 +623,8 @@ namespace Kernel
|
|||
.type = Processor::SMPMessage::Type::FlushTLB,
|
||||
.flush_tlb = {
|
||||
.vaddr = vaddr,
|
||||
.page_count = 1
|
||||
.page_count = 1,
|
||||
.page_table = vaddr < KERNEL_OFFSET ? this : nullptr,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -658,8 +659,12 @@ namespace Kernel
|
|||
uint64_t* pd = P2V(pdpt[pdpte] & s_page_addr_mask);
|
||||
uint64_t* pt = P2V(pd[pde] & s_page_addr_mask);
|
||||
|
||||
const paddr_t old_paddr = pt[pte] & PAGE_ADDR_MASK;
|
||||
|
||||
pt[pte] = 0;
|
||||
invalidate(vaddr, send_smp_message);
|
||||
|
||||
if (old_paddr != 0)
|
||||
invalidate(vaddr, send_smp_message);
|
||||
}
|
||||
|
||||
void PageTable::unmap_range(vaddr_t vaddr, size_t size)
|
||||
|
|
@ -676,7 +681,8 @@ namespace Kernel
|
|||
.type = Processor::SMPMessage::Type::FlushTLB,
|
||||
.flush_tlb = {
|
||||
.vaddr = vaddr,
|
||||
.page_count = page_count
|
||||
.page_count = page_count,
|
||||
.page_table = vaddr < KERNEL_OFFSET ? this : nullptr,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -742,9 +748,12 @@ namespace Kernel
|
|||
if (!(flags & Flags::Present))
|
||||
uwr_flags &= ~Flags::Present;
|
||||
|
||||
const paddr_t old_paddr = pt[pte] & PAGE_ADDR_MASK;
|
||||
|
||||
pt[pte] = paddr | uwr_flags | extra_flags;
|
||||
|
||||
invalidate(vaddr, send_smp_message);
|
||||
if (old_paddr != 0)
|
||||
invalidate(vaddr, send_smp_message);
|
||||
}
|
||||
|
||||
void PageTable::map_range_at(paddr_t paddr, vaddr_t vaddr, size_t size, flags_t flags, MemoryType memory_type)
|
||||
|
|
@ -765,7 +774,8 @@ namespace Kernel
|
|||
.type = Processor::SMPMessage::Type::FlushTLB,
|
||||
.flush_tlb = {
|
||||
.vaddr = vaddr,
|
||||
.page_count = page_count
|
||||
.page_count = page_count,
|
||||
.page_table = vaddr < KERNEL_OFFSET ? this : nullptr,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -840,6 +850,7 @@ namespace Kernel
|
|||
.flush_tlb = {
|
||||
.vaddr = vaddr,
|
||||
.page_count = bytes / PAGE_SIZE,
|
||||
.page_table = vaddr < KERNEL_OFFSET ? this : nullptr,
|
||||
}
|
||||
});
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@
|
|||
namespace Debug
|
||||
{
|
||||
void dump_stack_trace();
|
||||
void dump_stack_trace(uintptr_t ip, uintptr_t bp);
|
||||
void dump_qr_code();
|
||||
|
||||
void putchar(char);
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ namespace Kernel
|
|||
|
||||
BAN::ErrorOr<void> cleanup_indirect_block(uint32_t block, uint32_t depth);
|
||||
BAN::ErrorOr<void> cleanup_default_links();
|
||||
BAN::ErrorOr<void> cleanup_data_blocks();
|
||||
BAN::ErrorOr<void> cleanup_from_fs();
|
||||
|
||||
BAN::ErrorOr<void> sync();
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ namespace Kernel
|
|||
void map_kernel_memory();
|
||||
void prepare_fast_page();
|
||||
|
||||
static void invalidate(vaddr_t, bool send_smp_message);
|
||||
void invalidate(vaddr_t, bool send_smp_message);
|
||||
|
||||
static void map_fast_page(paddr_t);
|
||||
static void unmap_fast_page();
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include <kernel/ELF.h>
|
||||
#include <kernel/FS/Inode.h>
|
||||
#include <kernel/Lock/Mutex.h>
|
||||
#include <kernel/Lock/RWLock.h>
|
||||
#include <kernel/Memory/Heap.h>
|
||||
#include <kernel/Memory/MemoryRegion.h>
|
||||
#include <kernel/Memory/SharedMemoryObject.h>
|
||||
|
|
@ -218,8 +219,6 @@ namespace Kernel
|
|||
BAN::ErrorOr<long> sys_tcgetpgrp(int fd);
|
||||
BAN::ErrorOr<long> sys_tcsetpgrp(int fd, pid_t pgid);
|
||||
|
||||
BAN::ErrorOr<long> sys_termid(char*);
|
||||
|
||||
BAN::ErrorOr<long> sys_clock_gettime(clockid_t, timespec*);
|
||||
|
||||
BAN::ErrorOr<long> sys_load_keymap(const char* path);
|
||||
|
|
@ -274,17 +273,20 @@ namespace Kernel
|
|||
};
|
||||
|
||||
// Adds new region to the sorted array of mapped regions
|
||||
// You must hold writer end of m_mapped_region_lock when calling this.
|
||||
BAN::ErrorOr<void> add_mapped_region(BAN::UniqPtr<MemoryRegion>&&);
|
||||
// If address is contained by a region, returns the index of that.
|
||||
// Otherwise returns the address of the first region after this address.
|
||||
// You must hold reader end of m_mapped_region_lock when calling this.
|
||||
size_t find_mapped_region(vaddr_t) const;
|
||||
|
||||
BAN::ErrorOr<VirtualFileSystem::File> find_file(int fd, const char* path, int flags) const;
|
||||
BAN::ErrorOr<FileParent> find_parent_file(int fd, const char* path, int flags) const;
|
||||
BAN::ErrorOr<VirtualFileSystem::File> find_relative_parent(int fd, const char* path) const;
|
||||
|
||||
BAN::ErrorOr<void> validate_string_access(const char*);
|
||||
BAN::ErrorOr<void> validate_pointer_access(const void*, size_t, bool needs_write);
|
||||
BAN::ErrorOr<void> read_from_user(const void* user_addr, void* out, size_t size);
|
||||
BAN::ErrorOr<void> read_string_from_user(const char* user_addr, char* out, size_t max_size);
|
||||
BAN::ErrorOr<void> write_to_user(void* user_addr, const void* in, size_t size);
|
||||
BAN::ErrorOr<MemoryRegion*> validate_and_pin_pointer_access(const void*, size_t, bool needs_write);
|
||||
|
||||
uint64_t signal_pending_mask() const
|
||||
|
|
@ -329,6 +331,7 @@ namespace Kernel
|
|||
|
||||
OpenFileDescriptorSet m_open_file_descriptors;
|
||||
|
||||
mutable RWLock m_memory_region_lock;
|
||||
BAN::Vector<BAN::UniqPtr<MemoryRegion>> m_mapped_regions;
|
||||
|
||||
pid_t m_sid;
|
||||
|
|
@ -348,6 +351,7 @@ namespace Kernel
|
|||
|
||||
struct futex_t
|
||||
{
|
||||
Mutex mutex;
|
||||
ThreadBlocker blocker;
|
||||
uint32_t waiters { 0 };
|
||||
uint32_t to_wakeup { 0 };
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ namespace Kernel
|
|||
{
|
||||
uintptr_t vaddr;
|
||||
size_t page_count;
|
||||
void* page_table;
|
||||
} flush_tlb;
|
||||
SchedulerQueue::Node* new_thread;
|
||||
SchedulerQueue::Node* unblock_thread;
|
||||
|
|
@ -208,7 +209,7 @@ namespace Kernel
|
|||
static vaddr_t s_shared_page_vaddr;
|
||||
|
||||
ProcessorID m_id { 0 };
|
||||
uint8_t m_index { 0xFF };
|
||||
uint8_t m_index { 0 };
|
||||
|
||||
vaddr_t m_thread_syscall_stack;
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
namespace Kernel
|
||||
{
|
||||
|
||||
class MemoryBackedRegion;
|
||||
class Process;
|
||||
|
||||
class Thread
|
||||
|
|
@ -103,9 +104,7 @@ namespace Kernel
|
|||
vaddr_t kernel_stack_top() const { return m_kernel_stack->vaddr() + m_kernel_stack->size(); }
|
||||
VirtualRange& kernel_stack() { return *m_kernel_stack; }
|
||||
|
||||
vaddr_t userspace_stack_bottom() const { return is_userspace() ? m_userspace_stack->vaddr() : UINTPTR_MAX; }
|
||||
vaddr_t userspace_stack_top() const { return is_userspace() ? m_userspace_stack->vaddr() + m_userspace_stack->size() : 0; }
|
||||
VirtualRange& userspace_stack() { ASSERT(is_userspace()); return *m_userspace_stack; }
|
||||
MemoryBackedRegion& userspace_stack() { ASSERT(is_userspace() && m_userspace_stack); return *m_userspace_stack; }
|
||||
|
||||
static Thread& current();
|
||||
static pid_t current_tid();
|
||||
|
|
@ -129,7 +128,7 @@ namespace Kernel
|
|||
void set_gsbase(vaddr_t base) { m_gsbase = base; }
|
||||
vaddr_t get_gsbase() const { return m_gsbase; }
|
||||
|
||||
size_t virtual_page_count() const { return (m_kernel_stack ? (m_kernel_stack->size() / PAGE_SIZE) : 0) + (m_userspace_stack ? (m_userspace_stack->size() / PAGE_SIZE) : 0); }
|
||||
size_t virtual_page_count() const { return m_kernel_stack ? (m_kernel_stack->size() / PAGE_SIZE) : 0; }
|
||||
size_t physical_page_count() const { return virtual_page_count(); }
|
||||
|
||||
YieldRegisters& yield_registers() { return m_yield_registers; }
|
||||
|
|
@ -160,7 +159,7 @@ namespace Kernel
|
|||
BAN::UniqPtr<PageTable> m_keep_alive_page_table;
|
||||
|
||||
BAN::UniqPtr<VirtualRange> m_kernel_stack;
|
||||
BAN::UniqPtr<VirtualRange> m_userspace_stack;
|
||||
MemoryBackedRegion* m_userspace_stack { nullptr };
|
||||
const pid_t m_tid { 0 };
|
||||
State m_state { State::NotStarted };
|
||||
Process* m_process { nullptr };
|
||||
|
|
|
|||
|
|
@ -29,28 +29,33 @@ namespace Debug
|
|||
static uint8_t s_debug_ansi_state { 0 };
|
||||
|
||||
void dump_stack_trace()
|
||||
{
|
||||
dump_stack_trace(0, reinterpret_cast<uintptr_t>(__builtin_frame_address(0)));
|
||||
}
|
||||
|
||||
void dump_stack_trace(uintptr_t ip, uintptr_t bp)
|
||||
{
|
||||
using namespace Kernel;
|
||||
|
||||
struct stackframe
|
||||
{
|
||||
stackframe* bp;
|
||||
uintptr_t ip;
|
||||
void* ip;
|
||||
};
|
||||
|
||||
SpinLockGuard _(s_debug_lock);
|
||||
|
||||
stackframe* frame = (stackframe*)__builtin_frame_address(0);
|
||||
if (!frame)
|
||||
{
|
||||
dprintln("Could not get frame address");
|
||||
return;
|
||||
}
|
||||
uintptr_t first_ip = frame->ip;
|
||||
uintptr_t last_ip = 0;
|
||||
const stackframe* frame = reinterpret_cast<const stackframe*>(bp);
|
||||
|
||||
void* first_ip = frame->ip;
|
||||
void* last_ip = 0;
|
||||
bool first = true;
|
||||
|
||||
BAN::Formatter::print(Debug::putchar, "\e[36mStack trace:\r\n");
|
||||
|
||||
if (ip != 0)
|
||||
BAN::Formatter::print(Debug::putchar, " {}\r\n", reinterpret_cast<void*>(ip));
|
||||
|
||||
while (frame)
|
||||
{
|
||||
if (!PageTable::is_valid_pointer((vaddr_t)frame))
|
||||
|
|
|
|||
|
|
@ -128,16 +128,18 @@ namespace Kernel
|
|||
{
|
||||
auto& [inode, events] = *it;
|
||||
|
||||
#define REMOVE_IT_AND_CONTINUE() \
|
||||
#define REMOVE_IT() \
|
||||
({ \
|
||||
m_processing_events.remove(it); \
|
||||
if (event_count > 0) \
|
||||
break; \
|
||||
it = m_processing_events.begin(); \
|
||||
continue; \
|
||||
})
|
||||
|
||||
auto listen_it = m_listening_events.find(inode);
|
||||
if (listen_it == m_listening_events.end())
|
||||
REMOVE_IT_AND_CONTINUE();
|
||||
REMOVE_IT();
|
||||
auto& listen = listen_it->value;
|
||||
|
||||
{
|
||||
|
|
@ -149,7 +151,7 @@ namespace Kernel
|
|||
}
|
||||
|
||||
if (events == 0)
|
||||
REMOVE_IT_AND_CONTINUE();
|
||||
REMOVE_IT();
|
||||
|
||||
{
|
||||
LockGuard inode_locker(inode->m_mutex);
|
||||
|
|
@ -165,9 +167,9 @@ namespace Kernel
|
|||
}
|
||||
|
||||
if (events == 0)
|
||||
REMOVE_IT_AND_CONTINUE();
|
||||
REMOVE_IT();
|
||||
|
||||
#undef REMOVE_IT_AND_CONTINUE
|
||||
#undef REMOVE_IT
|
||||
|
||||
for (size_t fd = 0; fd < listen.events.size() && event_count < event_span.size(); fd++)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#include <BAN/ScopeGuard.h>
|
||||
#include <BAN/Sort.h>
|
||||
#include <kernel/FS/Ext2/FileSystem.h>
|
||||
#include <kernel/Lock/LockGuard.h>
|
||||
|
||||
|
|
@ -127,7 +128,7 @@ namespace Kernel
|
|||
{
|
||||
auto block_buffer = TRY(m_buffer_manager.get_buffer());
|
||||
|
||||
if (superblock().rev_level == Ext2::Enum::GOOD_OLD_REV)
|
||||
if ((superblock().rev_level == Ext2::Enum::GOOD_OLD_REV) || !(m_superblock.feature_ro_compat & Ext2::Enum::FEATURE_RO_COMPAT_SPARSE_SUPER))
|
||||
{
|
||||
// In revision 0 all blockgroups contain superblock backup
|
||||
TRY(m_superblock_backups.reserve(number_of_block_groups - 1));
|
||||
|
|
@ -148,6 +149,8 @@ namespace Kernel
|
|||
|
||||
// We don't really care if this succeeds or not
|
||||
(void)m_superblock_backups.shrink_to_fit();
|
||||
|
||||
BAN::sort::sort(m_superblock_backups.begin(), m_superblock_backups.end());
|
||||
}
|
||||
|
||||
for (uint32_t bg : m_superblock_backups)
|
||||
|
|
@ -488,14 +491,7 @@ namespace Kernel
|
|||
|
||||
TRY(read_block(bgd_location.block, bgd_buffer));
|
||||
|
||||
auto& bgd = *(Ext2::BlockGroupDescriptor*)(bgd_buffer.data() + bgd_location.offset);
|
||||
|
||||
const uint32_t inode_byte_offset = inode_index * superblock().inode_size;
|
||||
BlockLocation location
|
||||
{
|
||||
.block = inode_byte_offset / block_size + bgd.inode_table,
|
||||
.offset = inode_byte_offset % block_size
|
||||
};
|
||||
const auto bgd = bgd_buffer.span().slice(bgd_location.offset).as<Ext2::BlockGroupDescriptor>();
|
||||
|
||||
#if EXT2_VERIFY_INODE
|
||||
const uint32_t inode_bitmap_block = bgd.inode_bitmap;
|
||||
|
|
@ -503,14 +499,18 @@ namespace Kernel
|
|||
// NOTE: we can reuse the bgd_buffer since it is not needed anymore
|
||||
auto& inode_bitmap = bgd_buffer;
|
||||
|
||||
read_block(inode_bitmap_block, inode_bitmap.span());
|
||||
TRY(read_block(inode_bitmap_block, inode_bitmap));
|
||||
|
||||
const uint32_t byte = inode_index / 8;
|
||||
const uint32_t bit = inode_index % 8;
|
||||
ASSERT(inode_bitmap[byte] & (1 << bit));
|
||||
#endif
|
||||
|
||||
return location;
|
||||
const uint32_t inode_byte_offset = inode_index * superblock().inode_size;
|
||||
return BlockLocation {
|
||||
.block = inode_byte_offset / block_size + bgd.inode_table,
|
||||
.offset = inode_byte_offset % block_size
|
||||
};
|
||||
}
|
||||
|
||||
Ext2FS::BlockLocation Ext2FS::locate_block_group_descriptior(uint32_t group_index)
|
||||
|
|
@ -525,8 +525,7 @@ namespace Kernel
|
|||
// Block Group Descriptor table is in the block after superblock
|
||||
const uint32_t bgd_byte_offset = (superblock().first_data_block + 1) * block_size + sizeof(Ext2::BlockGroupDescriptor) * group_index;
|
||||
|
||||
return
|
||||
{
|
||||
return BlockLocation {
|
||||
.block = bgd_byte_offset / block_size,
|
||||
.offset = bgd_byte_offset % block_size
|
||||
};
|
||||
|
|
|
|||
|
|
@ -61,13 +61,13 @@ namespace Kernel
|
|||
const uint32_t inode_blocks_per_fs_block = blksize() / 512;
|
||||
const uint32_t indices_per_fs_block = blksize() / sizeof(uint32_t);
|
||||
|
||||
if (block == 0 && !allocate)
|
||||
return BAN::Optional<uint32_t>();
|
||||
|
||||
if (depth == 0)
|
||||
{
|
||||
if (block == 0)
|
||||
{
|
||||
if (!allocate)
|
||||
return BAN::Optional<uint32_t>();
|
||||
|
||||
block = TRY(m_fs.reserve_free_block(block_group()));
|
||||
m_inode.blocks += inode_blocks_per_fs_block;
|
||||
|
||||
|
|
@ -87,9 +87,6 @@ namespace Kernel
|
|||
TRY(m_fs.read_block(block, block_buffer));
|
||||
else
|
||||
{
|
||||
if (!allocate)
|
||||
return BAN::Optional<uint32_t>();
|
||||
|
||||
block = TRY(m_fs.reserve_free_block(block_group()));
|
||||
m_inode.blocks += inode_blocks_per_fs_block;
|
||||
|
||||
|
|
@ -171,8 +168,10 @@ namespace Kernel
|
|||
BAN::ErrorOr<void> Ext2Inode::set_link_target_impl(BAN::StringView target)
|
||||
{
|
||||
ASSERT(mode().iflnk());
|
||||
if (m_inode.size < sizeof(m_inode.block) && target.size() < sizeof(m_inode.block))
|
||||
if (target.size() < sizeof(m_inode.block))
|
||||
{
|
||||
if (m_inode.size >= sizeof(m_inode.block))
|
||||
TRY(cleanup_data_blocks());
|
||||
memset(m_inode.block, 0, sizeof(m_inode.block));
|
||||
memcpy(m_inode.block, target.data(), target.size());
|
||||
m_inode.size = target.size();
|
||||
|
|
@ -412,10 +411,8 @@ namespace Kernel
|
|||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Ext2Inode::cleanup_from_fs()
|
||||
BAN::ErrorOr<void> Ext2Inode::cleanup_data_blocks()
|
||||
{
|
||||
ASSERT(m_inode.links_count == 0);
|
||||
|
||||
if (mode().iflnk() && (size_t)size() < sizeof(m_inode.block))
|
||||
goto done;
|
||||
|
||||
|
|
@ -436,12 +433,16 @@ done:
|
|||
// mark blocks as deleted
|
||||
memset(m_inode.block, 0x00, sizeof(m_inode.block));
|
||||
|
||||
// FIXME: this is only required since fs does not get
|
||||
// deleting inode from its cache
|
||||
TRY(sync());
|
||||
|
||||
TRY(m_fs.delete_inode(ino()));
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Ext2Inode::cleanup_from_fs()
|
||||
{
|
||||
ASSERT(m_inode.links_count == 0);
|
||||
TRY(cleanup_data_blocks());
|
||||
TRY(m_fs.delete_inode(ino()));
|
||||
return {};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -277,7 +277,11 @@ namespace Kernel
|
|||
#endif
|
||||
if (isr == ISR::PageFault)
|
||||
PageTable::current().debug_dump();
|
||||
Debug::dump_stack_trace();
|
||||
#if ARCH(x86_64)
|
||||
Debug::dump_stack_trace(interrupt_stack->ip, regs->rbp);
|
||||
#elif ARCH(i686)
|
||||
Debug::dump_stack_trace(interrupt_stack->ip, regs->ebp);
|
||||
#endif
|
||||
|
||||
Debug::s_debug_lock.unlock(InterruptState::Disabled);
|
||||
|
||||
|
|
|
|||
|
|
@ -148,12 +148,12 @@ namespace Kernel
|
|||
if (m_preallocated)
|
||||
return false;
|
||||
|
||||
SpinLockGuard _(m_lock);
|
||||
|
||||
const size_t index = (vaddr - this->vaddr()) / PAGE_SIZE;
|
||||
if (m_paddrs[index])
|
||||
return false;
|
||||
|
||||
SpinLockGuard _(m_lock);
|
||||
|
||||
m_paddrs[index] = Heap::get().take_free_page();
|
||||
if (m_paddrs[index] == 0)
|
||||
return BAN::Error::from_errno(ENOMEM);
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -60,8 +60,13 @@ namespace Kernel
|
|||
Kernel::panic("Trying to initialize invalid processor {}", id.m_id);
|
||||
|
||||
if (id == s_bsp_id)
|
||||
{
|
||||
for (auto& processor : s_processors)
|
||||
{
|
||||
processor.m_id = PROCESSOR_NONE;
|
||||
processor.m_index = 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
auto& processor = s_processors[id.m_id];
|
||||
|
||||
|
|
@ -370,6 +375,8 @@ namespace Kernel
|
|||
switch (message->type)
|
||||
{
|
||||
case SMPMessage::Type::FlushTLB:
|
||||
if (message->flush_tlb.page_table && message->flush_tlb.page_table != processor.m_current_page_table)
|
||||
break;
|
||||
for (size_t i = 0; i < message->flush_tlb.page_count; i++)
|
||||
asm volatile("invlpg (%0)" :: "r"(message->flush_tlb.vaddr + i * PAGE_SIZE) : "memory");
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -256,16 +256,16 @@ namespace Kernel
|
|||
fis_command.fis_type = FIS_TYPE_REGISTER_H2D;
|
||||
fis_command.c = 1;
|
||||
|
||||
bool need_extended = lba >= (1 << 28) || sector_count > 0xFF;
|
||||
ASSERT (!need_extended || (m_command_set & ATA_COMMANDSET_LBA48_SUPPORTED));
|
||||
const bool needs_extended = lba >= (1 << 24) || sector_count > 0xFF;
|
||||
ASSERT (!needs_extended || (m_command_set & ATA_COMMANDSET_LBA48_SUPPORTED));
|
||||
|
||||
switch (command)
|
||||
{
|
||||
case Command::Read:
|
||||
fis_command.command = need_extended ? ATA_COMMAND_READ_DMA_EXT : ATA_COMMAND_READ_DMA;
|
||||
fis_command.command = needs_extended ? ATA_COMMAND_READ_DMA_EXT : ATA_COMMAND_READ_DMA;
|
||||
break;
|
||||
case Command::Write:
|
||||
fis_command.command = need_extended ? ATA_COMMAND_WRITE_DMA_EXT : ATA_COMMAND_WRITE_DMA;
|
||||
fis_command.command = needs_extended ? ATA_COMMAND_WRITE_DMA_EXT : ATA_COMMAND_WRITE_DMA;
|
||||
break;
|
||||
default:
|
||||
ASSERT_NOT_REACHED();
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#include <kernel/InterruptController.h>
|
||||
#include <kernel/InterruptStack.h>
|
||||
#include <kernel/Memory/kmalloc.h>
|
||||
#include <kernel/Memory/MemoryBackedRegion.h>
|
||||
#include <kernel/Process.h>
|
||||
#include <kernel/Scheduler.h>
|
||||
#include <kernel/Thread.h>
|
||||
|
|
@ -218,13 +219,16 @@ namespace Kernel
|
|||
true, true
|
||||
));
|
||||
|
||||
thread->m_userspace_stack = TRY(VirtualRange::create_to_vaddr_range(
|
||||
auto userspace_stack = TRY(MemoryBackedRegion::create(
|
||||
page_table,
|
||||
stack_addr_start, USERSPACE_END,
|
||||
userspace_stack_size,
|
||||
{ stack_addr_start, USERSPACE_END },
|
||||
MemoryRegion::Type::PRIVATE,
|
||||
PageTable::Flags::UserSupervisor | PageTable::Flags::ReadWrite | PageTable::Flags::Present,
|
||||
false, true
|
||||
O_RDWR
|
||||
));
|
||||
thread->m_userspace_stack = userspace_stack.ptr();
|
||||
TRY(process->add_mapped_region(BAN::move(userspace_stack)));
|
||||
|
||||
thread_deleter.disable();
|
||||
|
||||
|
|
@ -319,16 +323,18 @@ namespace Kernel
|
|||
{
|
||||
auto* thread = TRY(create_userspace(m_process, m_process->page_table()));
|
||||
|
||||
save_sse();
|
||||
if (Processor::get_current_sse_thread() == this)
|
||||
save_sse();
|
||||
memcpy(thread->m_sse_storage, m_sse_storage, sizeof(m_sse_storage));
|
||||
|
||||
TRY(thread->userspace_stack().allocate_page_for_demand_paging(thread->userspace_stack_top() - PAGE_SIZE));
|
||||
PageTable::with_fast_page(thread->userspace_stack().paddr_of(thread->userspace_stack_top() - PAGE_SIZE), [=] {
|
||||
PageTable::fast_page_as<void*>(PAGE_SIZE - sizeof(uintptr_t)) = arg;
|
||||
});
|
||||
TRY(thread->userspace_stack().copy_data_to_region(
|
||||
thread->m_userspace_stack->size() - sizeof(void*),
|
||||
reinterpret_cast<const uint8_t*>(&arg),
|
||||
sizeof(void*)
|
||||
));
|
||||
|
||||
const vaddr_t entry_addr = reinterpret_cast<vaddr_t>(entry);
|
||||
thread->setup_exec(entry_addr, thread->userspace_stack_top() - sizeof(uintptr_t));
|
||||
thread->setup_exec(entry_addr, thread->userspace_stack().vaddr() + thread->userspace_stack().size() - sizeof(void*));
|
||||
|
||||
return thread;
|
||||
}
|
||||
|
|
@ -346,14 +352,18 @@ namespace Kernel
|
|||
thread->m_is_userspace = true;
|
||||
|
||||
thread->m_kernel_stack = TRY(m_kernel_stack->clone(new_process->page_table()));
|
||||
thread->m_userspace_stack = TRY(m_userspace_stack->clone(new_process->page_table()));
|
||||
|
||||
const auto stack_index = new_process->find_mapped_region(m_userspace_stack->vaddr());
|
||||
thread->m_userspace_stack = static_cast<MemoryBackedRegion*>(new_process->m_mapped_regions[stack_index].ptr());
|
||||
ASSERT(thread->m_userspace_stack->vaddr() == m_userspace_stack->vaddr());
|
||||
|
||||
thread->m_fsbase = m_fsbase;
|
||||
thread->m_gsbase = m_gsbase;
|
||||
|
||||
thread->m_state = State::NotStarted;
|
||||
|
||||
save_sse();
|
||||
if (Processor::get_current_sse_thread() == this)
|
||||
save_sse();
|
||||
memcpy(thread->m_sse_storage, m_sse_storage, sizeof(m_sse_storage));
|
||||
|
||||
thread->m_yield_registers = {};
|
||||
|
|
@ -397,29 +407,18 @@ namespace Kernel
|
|||
if (needed_size > m_userspace_stack->size())
|
||||
return BAN::Error::from_errno(ENOBUFS);
|
||||
|
||||
vaddr_t vaddr = userspace_stack_top() - needed_size;
|
||||
vaddr_t vaddr = userspace_stack().vaddr() + userspace_stack().size() - needed_size;
|
||||
|
||||
const size_t page_count = BAN::Math::div_round_up<size_t>(needed_size, PAGE_SIZE);
|
||||
for (size_t i = 0; i < page_count; i++)
|
||||
TRY(m_userspace_stack->allocate_page_for_demand_paging(vaddr + i * PAGE_SIZE));
|
||||
TRY(m_userspace_stack->allocate_page_containing(vaddr + i * PAGE_SIZE, true));
|
||||
|
||||
const auto stack_copy_buf =
|
||||
[this](BAN::ConstByteSpan buffer, vaddr_t vaddr) -> void
|
||||
{
|
||||
ASSERT(vaddr + buffer.size() <= userspace_stack_top());
|
||||
|
||||
size_t bytes_copied = 0;
|
||||
while (bytes_copied < buffer.size())
|
||||
{
|
||||
const size_t to_copy = BAN::Math::min<size_t>(buffer.size() - bytes_copied, PAGE_SIZE - (vaddr % PAGE_SIZE));
|
||||
|
||||
PageTable::with_fast_page(userspace_stack().paddr_of(vaddr & PAGE_ADDR_MASK), [=]() {
|
||||
memcpy(PageTable::fast_page_as_ptr(vaddr % PAGE_SIZE), buffer.data() + bytes_copied, to_copy);
|
||||
});
|
||||
|
||||
vaddr += to_copy;
|
||||
bytes_copied += to_copy;
|
||||
}
|
||||
ASSERT(vaddr >= m_userspace_stack->vaddr());
|
||||
ASSERT(vaddr + buffer.size() <= m_userspace_stack->vaddr() + m_userspace_stack->size());
|
||||
MUST(m_userspace_stack->copy_data_to_region(vaddr - m_userspace_stack->vaddr(), buffer.data(), buffer.size()));
|
||||
};
|
||||
|
||||
const auto stack_push_buf =
|
||||
|
|
@ -471,7 +470,7 @@ namespace Kernel
|
|||
stack_push_str(envp[i]);
|
||||
}
|
||||
|
||||
setup_exec(entry, userspace_stack_top() - needed_size);
|
||||
setup_exec(entry, m_userspace_stack->vaddr() + m_userspace_stack->size() - needed_size);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
From 2b3a0198640c23a7f8f8247ed1edae309c11e15f Mon Sep 17 00:00:00 2001
|
||||
From 49d1ca61e6249c3bc3284a6b55578b4ddd7b13ac Mon Sep 17 00:00:00 2001
|
||||
From: Oskari Alaranta <oskari.alaranta@bananymous.com>
|
||||
Date: Thu, 31 Jul 2025 22:15:43 +0300
|
||||
Subject: [PATCH 1/2] add support for banan-os
|
||||
Date: Tue, 13 Jan 2026 20:49:19 +0200
|
||||
Subject: [PATCH] add support for banan-os
|
||||
|
||||
---
|
||||
engine/common/net_http.c | 4 +++-
|
||||
engine/common/net_ws.c | 17 +++++++++++++++++
|
||||
engine/common/whereami.c | 16 ++++++++++++++++
|
||||
engine/platform/posix/lib_posix.c | 2 ++
|
||||
public/build.c | 2 ++
|
||||
public/build.h | 3 +++
|
||||
public/buildenums.h | 3 +++
|
||||
7 files changed, 46 insertions(+), 1 deletion(-)
|
||||
engine/common/net_http.c | 4 +++-
|
||||
engine/common/net_ws.c | 6 ++++++
|
||||
engine/common/whereami.c | 2 +-
|
||||
engine/platform/posix/net.h | 4 ++++
|
||||
public/build.c | 2 ++
|
||||
public/build.h | 3 +++
|
||||
public/buildenums.h | 3 +++
|
||||
7 files changed, 22 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/engine/common/net_http.c b/engine/common/net_http.c
|
||||
index ff6fd41b..ebb5bbad 100644
|
||||
|
|
@ -36,23 +36,10 @@ index ff6fd41b..ebb5bbad 100644
|
|||
res = fcntl( file->socket, F_GETFL, 0 );
|
||||
|
||||
diff --git a/engine/common/net_ws.c b/engine/common/net_ws.c
|
||||
index 7ee4cba0..e93a2410 100644
|
||||
index 7ee4cba0..b44d5cf1 100644
|
||||
--- a/engine/common/net_ws.c
|
||||
+++ b/engine/common/net_ws.c
|
||||
@@ -1364,7 +1364,12 @@ static qboolean NET_QueuePacket( netsrc_t sock, netadr_t *from, byte *data, size
|
||||
byte buf[NET_MAX_FRAGMENT];
|
||||
int ret, protocol;
|
||||
int net_socket;
|
||||
+#ifdef XASH_BANAN_OS
|
||||
+ socklen_t addr_len;
|
||||
+#else
|
||||
WSAsize_t addr_len;
|
||||
+#endif
|
||||
+
|
||||
struct sockaddr_storage addr = { 0 };
|
||||
|
||||
*length = 0;
|
||||
@@ -1617,7 +1622,11 @@ static int NET_IPSocket( const char *net_iface, int port, int family )
|
||||
@@ -1617,7 +1617,11 @@ static int NET_IPSocket( const char *net_iface, int port, int family )
|
||||
if( family == AF_INET6 )
|
||||
pfamily = PF_INET6;
|
||||
|
||||
|
|
@ -64,7 +51,7 @@ index 7ee4cba0..e93a2410 100644
|
|||
{
|
||||
err = WSAGetLastError();
|
||||
if( err != WSAEAFNOSUPPORT )
|
||||
@@ -1625,6 +1634,7 @@ static int NET_IPSocket( const char *net_iface, int port, int family )
|
||||
@@ -1625,6 +1629,7 @@ static int NET_IPSocket( const char *net_iface, int port, int family )
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
|
||||
|
|
@ -72,7 +59,7 @@ index 7ee4cba0..e93a2410 100644
|
|||
if( NET_IsSocketError( ioctlsocket( net_socket, FIONBIO, (void*)&_true )))
|
||||
{
|
||||
struct timeval timeout;
|
||||
@@ -1634,6 +1644,7 @@ static int NET_IPSocket( const char *net_iface, int port, int family )
|
||||
@@ -1634,6 +1639,7 @@ static int NET_IPSocket( const char *net_iface, int port, int family )
|
||||
timeout.tv_sec = timeout.tv_usec = 0;
|
||||
setsockopt( net_socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout));
|
||||
}
|
||||
|
|
@ -80,81 +67,34 @@ index 7ee4cba0..e93a2410 100644
|
|||
|
||||
// make it broadcast capable
|
||||
if( NET_IsSocketError( setsockopt( net_socket, SOL_SOCKET, SO_BROADCAST, (char *)&_true, sizeof( _true ))))
|
||||
@@ -1686,6 +1697,7 @@ static int NET_IPSocket( const char *net_iface, int port, int family )
|
||||
optval = 0x10; // IPTOS_LOWDELAY
|
||||
Con_Printf( "Enabling LOWDELAY TOS option\n" );
|
||||
|
||||
+#ifdef IP_TOS
|
||||
if( NET_IsSocketError( setsockopt( net_socket, IPPROTO_IP, IP_TOS, (const char *)&optval, sizeof( optval ))))
|
||||
{
|
||||
err = WSAGetLastError();
|
||||
@@ -1694,6 +1706,7 @@ static int NET_IPSocket( const char *net_iface, int port, int family )
|
||||
closesocket( net_socket );
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
+#endif
|
||||
}
|
||||
|
||||
if( Sys_CheckParm( "-loopback" ))
|
||||
@@ -1801,7 +1814,11 @@ static void NET_DetermineLocalAddress( void )
|
||||
char hostname[512];
|
||||
char buff[512];
|
||||
struct sockaddr_storage address;
|
||||
+#ifdef XASH_BANAN_OS
|
||||
+ socklen_t namelen;
|
||||
+#else
|
||||
WSAsize_t namelen;
|
||||
+#endif
|
||||
const char *net_addr_string;
|
||||
|
||||
memset( &net_local, 0, sizeof( netadr_t ));
|
||||
diff --git a/engine/common/whereami.c b/engine/common/whereami.c
|
||||
index 31726774..5b7ff504 100644
|
||||
index 31726774..69a6cb9f 100644
|
||||
--- a/engine/common/whereami.c
|
||||
+++ b/engine/common/whereami.c
|
||||
@@ -851,6 +851,22 @@ int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length)
|
||||
return -1;
|
||||
@@ -175,7 +175,7 @@ int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length)
|
||||
return length;
|
||||
}
|
||||
|
||||
+#elif defined(__banan_os__)
|
||||
+
|
||||
+/* Not possible on this platform */
|
||||
+
|
||||
+WAI_FUNCSPEC
|
||||
+int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length)
|
||||
+{
|
||||
+ return -1;
|
||||
+}
|
||||
+
|
||||
+WAI_FUNCSPEC
|
||||
+int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length)
|
||||
+{
|
||||
+ return -1;
|
||||
+}
|
||||
+
|
||||
#else
|
||||
-#elif defined(__linux__) || defined(__CYGWIN__) || defined(__sun) || defined(__serenity__) || defined(WAI_USE_PROC_SELF_EXE)
|
||||
+#elif defined(__linux__) || defined(__CYGWIN__) || defined(__sun) || defined(__serenity__) || defined(__banan_os__) || defined(WAI_USE_PROC_SELF_EXE)
|
||||
|
||||
#error unsupported platform
|
||||
diff --git a/engine/platform/posix/lib_posix.c b/engine/platform/posix/lib_posix.c
|
||||
index 23d1c3b1..a5a84fe1 100644
|
||||
--- a/engine/platform/posix/lib_posix.c
|
||||
+++ b/engine/platform/posix/lib_posix.c
|
||||
@@ -208,6 +208,7 @@ const char *COM_NameForFunction( void *hInstance, void *function )
|
||||
return Loader_GetFuncName_int(wm, function);
|
||||
else
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
diff --git a/engine/platform/posix/net.h b/engine/platform/posix/net.h
|
||||
index 58532927..6ab3cd1f 100644
|
||||
--- a/engine/platform/posix/net.h
|
||||
+++ b/engine/platform/posix/net.h
|
||||
@@ -90,6 +90,10 @@ static int ioctl_stub( int d, unsigned long r, ... )
|
||||
#define closesocket close
|
||||
#endif
|
||||
+#ifndef XASH_BANAN_OS
|
||||
// NOTE: dladdr() is a glibc extension
|
||||
{
|
||||
Dl_info info = {0};
|
||||
@@ -215,6 +216,7 @@ const char *COM_NameForFunction( void *hInstance, void *function )
|
||||
if( ret && info.dli_sname )
|
||||
return COM_GetPlatformNeutralName( info.dli_sname );
|
||||
}
|
||||
#define SOCKET int
|
||||
+#if XASH_BANAN_OS
|
||||
+typedef socklen_t WSAsize_t;
|
||||
+#else
|
||||
typedef int WSAsize_t;
|
||||
+#endif
|
||||
#ifdef XASH_ALLOW_SAVERESTORE_OFFSETS
|
||||
return COM_OffsetNameForFunction( function );
|
||||
#else
|
||||
|
||||
#endif // NET_H
|
||||
diff --git a/public/build.c b/public/build.c
|
||||
index 6c85bbaf..460b4040 100644
|
||||
--- a/public/build.c
|
||||
|
|
@ -211,5 +151,5 @@ index 4dc327d3..57585f73 100644
|
|||
#error
|
||||
#endif
|
||||
--
|
||||
2.50.1
|
||||
2.52.0
|
||||
|
||||
|
|
|
|||
|
|
@ -1,25 +0,0 @@
|
|||
From b8c6ea53b4a8119f299fb6b5e4684c30795037a7 Mon Sep 17 00:00:00 2001
|
||||
From: Oskari Alaranta <oskari.alaranta@bananymous.com>
|
||||
Date: Thu, 31 Jul 2025 22:36:28 +0300
|
||||
Subject: [PATCH] Don't export have libbacktrace
|
||||
|
||||
This doesnt work :)
|
||||
---
|
||||
3rdparty/libbacktrace/wscript | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
diff --git a/3rdparty/libbacktrace/wscript b/3rdparty/libbacktrace/wscript
|
||||
index 2e076a56..98aca8d5 100644
|
||||
--- a/3rdparty/libbacktrace/wscript
|
||||
+++ b/3rdparty/libbacktrace/wscript
|
||||
@@ -180,7 +180,6 @@ def build(bld):
|
||||
features = 'frandomseed' if bld.env.HAVE_FRANDOM_SEED else '',
|
||||
use = 'EXTRAFLAGS lzma z zstd',
|
||||
includes = '. libbacktrace/',
|
||||
- export_defines = 'HAVE_LIBBACKTRACE=1',
|
||||
export_includes = 'libbacktrace/'
|
||||
)
|
||||
|
||||
--
|
||||
2.50.1
|
||||
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
From 1e1fb9caff45f0cb05e89bfe452a7ff2abb558ff Mon Sep 17 00:00:00 2001
|
||||
From: Oskari Alaranta <oskari.alaranta@bananymous.com>
|
||||
Date: Thu, 31 Jul 2025 22:17:48 +0300
|
||||
Subject: [PATCH] include alloca on banan-os
|
||||
|
||||
This detection does not work :(
|
||||
---
|
||||
lib/os.h | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/lib/os.h b/lib/os.h
|
||||
index 9ded7358..66b56704 100644
|
||||
--- a/lib/os.h
|
||||
+++ b/lib/os.h
|
||||
@@ -62,7 +62,7 @@ void *_alloca(size_t size);
|
||||
|
||||
#endif /* _V_IFDEFJAIL_H_ */
|
||||
|
||||
-#ifdef HAVE_ALLOCA_H
|
||||
+#if defined(HAVE_ALLOCA_H) || defined(__banan_os__)
|
||||
# include <alloca.h>
|
||||
#endif
|
||||
|
||||
--
|
||||
2.50.1
|
||||
|
||||
|
|
@ -9,7 +9,6 @@ __BEGIN_DECLS
|
|||
O(SYS_EXIT, exit) \
|
||||
O(SYS_READ, read) \
|
||||
O(SYS_WRITE, write) \
|
||||
O(SYS_TERMID, termid) \
|
||||
O(SYS_CLOSE, close) \
|
||||
O(SYS_OPENAT, openat) \
|
||||
O(SYS_SEEK, seek) \
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ char* ctermid(char* buffer)
|
|||
{
|
||||
static char s_buffer[L_ctermid];
|
||||
char* target = buffer ? buffer : s_buffer;
|
||||
syscall(SYS_TERMID, target);
|
||||
strcpy(buffer, "/dev/tty");
|
||||
return target;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ int clock_gettime(clockid_t clock_id, struct timespec* tp)
|
|||
if (clock_id == CLOCK_REALTIME)
|
||||
tp->tv_sec += sgettime.realtime_seconds;
|
||||
|
||||
return monotonic_ns;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@
|
|||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/banan-os.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
|
|
@ -67,6 +67,18 @@ namespace LibGUI
|
|||
return BAN::Error::from_errno(errno);
|
||||
BAN::ScopeGuard server_closer([server_fd] { close(server_fd); });
|
||||
|
||||
int epoll_fd = epoll_create1(EPOLL_CLOEXEC);
|
||||
if (epoll_fd == -1)
|
||||
return BAN::Error::from_errno(errno);
|
||||
BAN::ScopeGuard epoll_closer([epoll_fd] { close(epoll_fd); });
|
||||
|
||||
epoll_event epoll_event {
|
||||
.events = EPOLLIN,
|
||||
.data = { .fd = server_fd },
|
||||
};
|
||||
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, server_fd, &epoll_event) == -1)
|
||||
return BAN::Error::from_errno(errno);
|
||||
|
||||
if (fcntl(server_fd, F_SETFD, fcntl(server_fd, F_GETFD) | FD_CLOEXEC) == -1)
|
||||
return BAN::Error::from_errno(errno);
|
||||
|
||||
|
|
@ -100,7 +112,7 @@ namespace LibGUI
|
|||
TRY(create_packet.title.append(title));
|
||||
TRY(create_packet.send_serialized(server_fd));
|
||||
|
||||
auto window = TRY(BAN::UniqPtr<Window>::create(server_fd, attributes));
|
||||
auto window = TRY(BAN::UniqPtr<Window>::create(server_fd, epoll_fd, attributes));
|
||||
|
||||
bool resized = false;
|
||||
window->set_resize_window_event_callback([&]() { resized = true; });
|
||||
|
|
@ -109,6 +121,7 @@ namespace LibGUI
|
|||
window->set_resize_window_event_callback({});
|
||||
|
||||
server_closer.disable();
|
||||
epoll_closer.disable();
|
||||
|
||||
return window;
|
||||
}
|
||||
|
|
@ -261,6 +274,7 @@ namespace LibGUI
|
|||
{
|
||||
munmap(m_framebuffer_smo, m_width * m_height * 4);
|
||||
close(m_server_fd);
|
||||
close(m_epoll_fd);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Window::handle_resize_event(const EventPacket::ResizeWindowEvent& event)
|
||||
|
|
@ -289,10 +303,8 @@ namespace LibGUI
|
|||
|
||||
void Window::wait_events()
|
||||
{
|
||||
fd_set fds;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(m_server_fd, &fds);
|
||||
select(m_server_fd + 1, &fds, nullptr, nullptr, nullptr);
|
||||
epoll_event dummy;
|
||||
epoll_wait(m_epoll_fd, &dummy, 1, -1);
|
||||
}
|
||||
|
||||
void Window::poll_events()
|
||||
|
|
@ -300,13 +312,8 @@ namespace LibGUI
|
|||
#define TRY_OR_BREAK(...) ({ auto&& e = (__VA_ARGS__); if (e.is_error()) break; e.release_value(); })
|
||||
for (;;)
|
||||
{
|
||||
fd_set fds;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(m_server_fd, &fds);
|
||||
timeval timeout { .tv_sec = 0, .tv_usec = 0 };
|
||||
select(m_server_fd + 1, &fds, nullptr, nullptr, &timeout);
|
||||
|
||||
if (!FD_ISSET(m_server_fd, &fds))
|
||||
epoll_event event;
|
||||
if (epoll_wait(m_epoll_fd, &event, 1, 0) == 0)
|
||||
break;
|
||||
|
||||
auto packet_or_error = recv_packet(m_server_fd);
|
||||
|
|
|
|||
|
|
@ -81,8 +81,9 @@ namespace LibGUI
|
|||
int server_fd() const { return m_server_fd; }
|
||||
|
||||
private:
|
||||
Window(int server_fd, Attributes attributes)
|
||||
Window(int server_fd, int epoll_fd, Attributes attributes)
|
||||
: m_server_fd(server_fd)
|
||||
, m_epoll_fd(epoll_fd)
|
||||
, m_attributes(attributes)
|
||||
{ }
|
||||
|
||||
|
|
@ -93,6 +94,7 @@ namespace LibGUI
|
|||
|
||||
private:
|
||||
const int m_server_fd;
|
||||
const int m_epoll_fd;
|
||||
|
||||
bool m_handling_socket_error { false };
|
||||
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@
|
|||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/un.h>
|
||||
|
|
@ -119,12 +119,24 @@ int main()
|
|||
if (server_fd == -1)
|
||||
return 1;
|
||||
|
||||
struct ClientInfo
|
||||
const int epoll_fd = epoll_create1(0);
|
||||
if (epoll_fd == -1)
|
||||
{
|
||||
int fd;
|
||||
};
|
||||
dwarnln("failed to create epoll: {}", strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
BAN::Vector<ClientInfo> clients;
|
||||
{
|
||||
epoll_event event {
|
||||
.events = EPOLLIN,
|
||||
.data = { .fd = server_fd },
|
||||
};
|
||||
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, server_fd, &event) == -1)
|
||||
{
|
||||
dwarnln("failed to add server socket to epoll: {}", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
dprintln("AudioServer started");
|
||||
|
||||
|
|
@ -132,67 +144,70 @@ int main()
|
|||
|
||||
for (;;)
|
||||
{
|
||||
fd_set fds;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(server_fd, &fds);
|
||||
|
||||
int max_fd = server_fd;
|
||||
for (const auto& client : clients)
|
||||
{
|
||||
max_fd = BAN::Math::max(max_fd, client.fd);
|
||||
FD_SET(client.fd, &fds);
|
||||
}
|
||||
|
||||
const uint64_t current_ms = get_current_ms();
|
||||
next_update_ms = current_ms + audio_server->update();
|
||||
|
||||
const uint64_t timeout_ms = next_update_ms - current_ms;
|
||||
|
||||
timeval timeout {
|
||||
.tv_sec = static_cast<time_t>(timeout_ms / 1000),
|
||||
.tv_usec = static_cast<suseconds_t>((timeout_ms % 1000) * 1000)
|
||||
};
|
||||
if (select(max_fd + 1, &fds, nullptr, nullptr, &timeout) == -1)
|
||||
epoll_event events[16];
|
||||
int event_count = epoll_wait(epoll_fd, events, 16, timeout_ms);
|
||||
if (event_count == -1 && errno != EINTR)
|
||||
{
|
||||
dwarnln("select: {}", strerror(errno));
|
||||
dwarnln("epoll_wait: {}", strerror(errno));
|
||||
break;
|
||||
}
|
||||
|
||||
if (FD_ISSET(server_fd, &fds))
|
||||
for (int i = 0; i < event_count; i++)
|
||||
{
|
||||
const int client_fd = accept(server_fd, nullptr, nullptr);
|
||||
if (client_fd == -1)
|
||||
if (events[i].data.fd == server_fd)
|
||||
{
|
||||
dwarnln("accept: {}", strerror(errno));
|
||||
ASSERT(events[i].events & EPOLLIN);
|
||||
|
||||
const int client_fd = accept(server_fd, nullptr, nullptr);
|
||||
if (client_fd == -1)
|
||||
{
|
||||
dwarnln("accept: {}", strerror(errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
epoll_event event {
|
||||
.events = EPOLLIN,
|
||||
.data = { .fd = client_fd },
|
||||
};
|
||||
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, client_fd, &event) == -1)
|
||||
{
|
||||
dwarnln("Failed to add client to epoll: {}", strerror(errno));
|
||||
close(client_fd);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (auto ret = audio_server->on_new_client(client_fd); ret.is_error())
|
||||
{
|
||||
dwarnln("Failed to initialize client: {}", ret.error());
|
||||
epoll_ctl(epoll_fd, EPOLL_CTL_DEL, client_fd, nullptr);
|
||||
close(client_fd);
|
||||
continue;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (auto ret = clients.emplace_back(client_fd); ret.is_error())
|
||||
const int client_fd = events[i].data.fd;
|
||||
|
||||
if (events[i].events & EPOLLHUP)
|
||||
{
|
||||
dwarnln("Failed to add client: {}", ret.error());
|
||||
audio_server->on_client_disconnect(client_fd);
|
||||
epoll_ctl(epoll_fd, EPOLL_CTL_DEL, client_fd, nullptr);
|
||||
close(client_fd);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (auto ret = audio_server->on_new_client(client_fd); ret.is_error())
|
||||
{
|
||||
dwarnln("Failed to initialize client: {}", ret.error());
|
||||
clients.pop_back();
|
||||
close(client_fd);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < clients.size(); i++)
|
||||
{
|
||||
auto& client = clients[i];
|
||||
if (!FD_ISSET(client.fd, &fds))
|
||||
continue;
|
||||
ASSERT(events[i].events & EPOLLIN);
|
||||
|
||||
LibAudio::Packet packet;
|
||||
const ssize_t nrecv = recv(client.fd, &packet, sizeof(packet), 0);
|
||||
const ssize_t nrecv = recv(client_fd, &packet, sizeof(packet), 0);
|
||||
|
||||
if (nrecv < static_cast<ssize_t>(sizeof(packet)) || !audio_server->on_client_packet(client.fd, packet))
|
||||
if (nrecv < static_cast<ssize_t>(sizeof(packet)) || !audio_server->on_client_packet(client_fd, packet))
|
||||
{
|
||||
if (nrecv == 0)
|
||||
;
|
||||
|
|
@ -201,10 +216,9 @@ int main()
|
|||
else if (nrecv < static_cast<ssize_t>(sizeof(packet)))
|
||||
dwarnln("client sent only {} bytes, {} expected", nrecv, sizeof(packet));
|
||||
|
||||
audio_server->on_client_disconnect(client.fd);
|
||||
close(client.fd);
|
||||
clients.remove(i--);
|
||||
continue;
|
||||
audio_server->on_client_disconnect(client_fd);
|
||||
epoll_ctl(epoll_fd, EPOLL_CTL_DEL, client_fd, nullptr);
|
||||
close(client_fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1460,28 +1460,17 @@ void WindowServer::remove_client_fd(int fd)
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_deleted_window = true;
|
||||
}
|
||||
|
||||
int WindowServer::get_client_fds(fd_set& fds) const
|
||||
WindowServer::ClientData& WindowServer::get_client_data(int fd)
|
||||
{
|
||||
int max_fd = 0;
|
||||
for (const auto& [fd, _] : m_client_data)
|
||||
{
|
||||
FD_SET(fd, &fds);
|
||||
max_fd = BAN::Math::max(max_fd, fd);
|
||||
}
|
||||
return max_fd;
|
||||
}
|
||||
auto it = m_client_data.find(fd);
|
||||
if (it != m_client_data.end())
|
||||
return it->value;
|
||||
|
||||
void WindowServer::for_each_client_fd(const BAN::Function<BAN::Iteration(int, ClientData&)>& callback)
|
||||
{
|
||||
m_deleted_window = false;
|
||||
for (auto& [fd, cliend_data] : m_client_data)
|
||||
{
|
||||
if (m_deleted_window)
|
||||
break;
|
||||
callback(fd, cliend_data);
|
||||
}
|
||||
dwarnln("could not find client {}", fd);
|
||||
for (auto& [client_fd, _] : m_client_data)
|
||||
dwarnln(" {}", client_fd);
|
||||
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,8 +15,6 @@
|
|||
#include <LibInput/KeyEvent.h>
|
||||
#include <LibInput/MouseEvent.h>
|
||||
|
||||
#include <sys/select.h>
|
||||
|
||||
class WindowServer
|
||||
{
|
||||
public:
|
||||
|
|
@ -58,8 +56,7 @@ public:
|
|||
|
||||
void add_client_fd(int fd);
|
||||
void remove_client_fd(int fd);
|
||||
int get_client_fds(fd_set& fds) const;
|
||||
void for_each_client_fd(const BAN::Function<BAN::Iteration(int, ClientData&)>& callback);
|
||||
ClientData& get_client_data(int fd);
|
||||
|
||||
bool is_stopped() const { return m_is_stopped; }
|
||||
|
||||
|
|
@ -114,7 +111,6 @@ private:
|
|||
|
||||
bool m_is_mouse_relative { false };
|
||||
|
||||
bool m_deleted_window { false };
|
||||
bool m_is_stopped { false };
|
||||
bool m_is_bouncing_window = false;
|
||||
|
||||
|
|
|
|||
|
|
@ -9,9 +9,9 @@
|
|||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/banan-os.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
|
|
@ -157,10 +157,29 @@ int main()
|
|||
return 1;
|
||||
}
|
||||
|
||||
int epoll_fd = epoll_create1(EPOLL_CLOEXEC);
|
||||
if (epoll_fd == -1)
|
||||
{
|
||||
dwarnln("epoll_create1: {}", strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
{
|
||||
epoll_event event {
|
||||
.events = EPOLLIN,
|
||||
.data = { .fd = server_fd },
|
||||
};
|
||||
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, server_fd, &event) == -1)
|
||||
{
|
||||
dwarnln("epoll_ctl server: {}", strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (tty_ctrl(STDIN_FILENO, TTY_CMD_UNSET, TTY_FLAG_ENABLE_INPUT) == -1)
|
||||
{
|
||||
perror("tty_ctrl");
|
||||
exit(1);
|
||||
dwarnln("tty_ctrl: {}", strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
atexit([]() { tty_ctrl(STDIN_FILENO, TTY_CMD_SET, TTY_FLAG_ENABLE_INPUT); });
|
||||
|
|
@ -188,11 +207,37 @@ int main()
|
|||
|
||||
int keyboard_fd = open("/dev/keyboard", O_RDONLY | O_CLOEXEC);
|
||||
if (keyboard_fd == -1)
|
||||
perror("open");
|
||||
dwarnln("open keyboard: {}", strerror(errno));
|
||||
else
|
||||
{
|
||||
epoll_event event {
|
||||
.events = EPOLLIN,
|
||||
.data = { .fd = keyboard_fd },
|
||||
};
|
||||
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, keyboard_fd, &event) == -1)
|
||||
{
|
||||
dwarnln("epoll_ctl keyboard: {}", strerror(errno));
|
||||
close(keyboard_fd);
|
||||
keyboard_fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
int mouse_fd = open("/dev/mouse", O_RDONLY | O_CLOEXEC);
|
||||
if (mouse_fd == -1)
|
||||
perror("open");
|
||||
dwarnln("open mouse: {}", strerror(errno));
|
||||
else
|
||||
{
|
||||
epoll_event event {
|
||||
.events = EPOLLIN,
|
||||
.data = { .fd = mouse_fd },
|
||||
};
|
||||
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, mouse_fd, &event) == -1)
|
||||
{
|
||||
dwarnln("epoll_ctl mouse: {}", strerror(errno));
|
||||
close(mouse_fd);
|
||||
mouse_fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
dprintln("Window server started");
|
||||
|
||||
|
|
@ -208,11 +253,11 @@ int main()
|
|||
{
|
||||
timespec current_ts;
|
||||
clock_gettime(CLOCK_MONOTONIC, ¤t_ts);
|
||||
return (current_ts.tv_sec * 1'000'000) + (current_ts.tv_nsec / 1'000);
|
||||
return (current_ts.tv_sec * 1'000'000) + (current_ts.tv_nsec / 1000);
|
||||
};
|
||||
|
||||
constexpr uint64_t sync_interval_us = 1'000'000 / 60;
|
||||
uint64_t last_sync_us = 0;
|
||||
uint64_t last_sync_us = get_current_us() - sync_interval_us;
|
||||
while (!window_server.is_stopped())
|
||||
{
|
||||
const auto current_us = get_current_us();
|
||||
|
|
@ -222,168 +267,182 @@ int main()
|
|||
last_sync_us += sync_interval_us;
|
||||
}
|
||||
|
||||
int max_fd = server_fd;
|
||||
|
||||
fd_set fds;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(server_fd, &fds);
|
||||
if (keyboard_fd != -1)
|
||||
{
|
||||
FD_SET(keyboard_fd, &fds);
|
||||
max_fd = BAN::Math::max(max_fd, keyboard_fd);
|
||||
}
|
||||
if (mouse_fd != -1)
|
||||
{
|
||||
FD_SET(mouse_fd, &fds);
|
||||
max_fd = BAN::Math::max(max_fd, mouse_fd);
|
||||
}
|
||||
max_fd = BAN::Math::max(max_fd, window_server.get_client_fds(fds));
|
||||
|
||||
timeval select_timeout {};
|
||||
timespec timeout = {};
|
||||
if (auto current_us = get_current_us(); current_us - last_sync_us < sync_interval_us)
|
||||
select_timeout.tv_usec = sync_interval_us - (current_us - last_sync_us);
|
||||
timeout.tv_nsec = (sync_interval_us - (current_us - last_sync_us)) * 1000;
|
||||
|
||||
int nselect = select(max_fd + 1, &fds, nullptr, nullptr, &select_timeout);
|
||||
if (nselect == 0)
|
||||
continue;
|
||||
if (nselect == -1)
|
||||
epoll_event events[16];
|
||||
int epoll_events = epoll_pwait2(epoll_fd, events, 16, &timeout, nullptr);
|
||||
if (epoll_events == -1 && errno != EINTR)
|
||||
{
|
||||
dwarnln("select: {}", strerror(errno));
|
||||
dwarnln("epoll_pwait2: {}", strerror(errno));
|
||||
break;
|
||||
}
|
||||
|
||||
if (FD_ISSET(server_fd, &fds))
|
||||
for (int i = 0; i < epoll_events; i++)
|
||||
{
|
||||
int window_fd = accept4(server_fd, nullptr, nullptr, SOCK_NONBLOCK | SOCK_CLOEXEC);
|
||||
if (window_fd == -1)
|
||||
if (events[i].data.fd == server_fd)
|
||||
{
|
||||
dwarnln("accept: {}", strerror(errno));
|
||||
continue;
|
||||
}
|
||||
window_server.add_client_fd(window_fd);
|
||||
}
|
||||
ASSERT(events[i].events & EPOLLIN);
|
||||
|
||||
if (keyboard_fd != -1 && FD_ISSET(keyboard_fd, &fds))
|
||||
{
|
||||
LibInput::RawKeyEvent event;
|
||||
if (read(keyboard_fd, &event, sizeof(event)) == -1)
|
||||
{
|
||||
perror("read");
|
||||
continue;
|
||||
}
|
||||
window_server.on_key_event(LibInput::KeyboardLayout::get().key_event_from_raw(event));
|
||||
}
|
||||
|
||||
if (mouse_fd != -1 && FD_ISSET(mouse_fd, &fds))
|
||||
{
|
||||
LibInput::MouseEvent event;
|
||||
if (read(mouse_fd, &event, sizeof(event)) == -1)
|
||||
{
|
||||
perror("read");
|
||||
continue;
|
||||
}
|
||||
switch (event.type)
|
||||
{
|
||||
case LibInput::MouseEventType::MouseButtonEvent:
|
||||
window_server.on_mouse_button(event.button_event);
|
||||
break;
|
||||
case LibInput::MouseEventType::MouseMoveEvent:
|
||||
window_server.on_mouse_move(event.move_event);
|
||||
break;
|
||||
case LibInput::MouseEventType::MouseMoveAbsEvent:
|
||||
window_server.on_mouse_move_abs(event.move_abs_event);
|
||||
break;
|
||||
case LibInput::MouseEventType::MouseScrollEvent:
|
||||
window_server.on_mouse_scroll(event.scroll_event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
window_server.for_each_client_fd(
|
||||
[&](int fd, WindowServer::ClientData& client_data) -> BAN::Iteration
|
||||
{
|
||||
if (!FD_ISSET(fd, &fds))
|
||||
return BAN::Iteration::Continue;
|
||||
|
||||
if (client_data.packet_buffer.empty())
|
||||
int window_fd = accept4(server_fd, nullptr, nullptr, SOCK_NONBLOCK | SOCK_CLOEXEC);
|
||||
if (window_fd == -1)
|
||||
{
|
||||
uint32_t packet_size;
|
||||
const ssize_t nrecv = recv(fd, &packet_size, sizeof(uint32_t), 0);
|
||||
if (nrecv < 0)
|
||||
dwarnln("recv: {}", strerror(errno));
|
||||
if (nrecv > 0 && nrecv != sizeof(uint32_t))
|
||||
dwarnln("could not read packet size with a single recv call, closing connection...");
|
||||
if (nrecv != sizeof(uint32_t))
|
||||
{
|
||||
window_server.remove_client_fd(fd);
|
||||
return BAN::Iteration::Continue;
|
||||
}
|
||||
|
||||
if (packet_size < 4)
|
||||
{
|
||||
dwarnln("client sent invalid packet, closing connection...");
|
||||
return BAN::Iteration::Continue;
|
||||
}
|
||||
|
||||
// this is a bit harsh, but i don't want to work on skipping streaming packets
|
||||
if (client_data.packet_buffer.resize(packet_size).is_error())
|
||||
{
|
||||
dwarnln("could not allocate memory for client packet, closing connection...");
|
||||
window_server.remove_client_fd(fd);
|
||||
return BAN::Iteration::Continue;
|
||||
}
|
||||
|
||||
client_data.packet_buffer_nread = 0;
|
||||
return BAN::Iteration::Continue;
|
||||
dwarnln("accept: {}", strerror(errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
const ssize_t nrecv = recv(
|
||||
fd,
|
||||
client_data.packet_buffer.data() + client_data.packet_buffer_nread,
|
||||
client_data.packet_buffer.size() - client_data.packet_buffer_nread,
|
||||
0
|
||||
);
|
||||
epoll_event event {
|
||||
.events = EPOLLIN,
|
||||
.data = { .fd = window_fd },
|
||||
};
|
||||
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, window_fd, &event) == -1)
|
||||
{
|
||||
dwarnln("epoll_ctl: {}", strerror(errno));
|
||||
close(window_fd);
|
||||
continue;
|
||||
}
|
||||
|
||||
window_server.add_client_fd(window_fd);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (events[i].data.fd == keyboard_fd)
|
||||
{
|
||||
ASSERT(events[i].events & EPOLLIN);
|
||||
|
||||
LibInput::RawKeyEvent event;
|
||||
if (read(keyboard_fd, &event, sizeof(event)) == -1)
|
||||
{
|
||||
dwarnln("read keyboard: {}", strerror(errno));
|
||||
continue;
|
||||
}
|
||||
window_server.on_key_event(LibInput::KeyboardLayout::get().key_event_from_raw(event));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (events[i].data.fd == mouse_fd)
|
||||
{
|
||||
ASSERT(events[i].events & EPOLLIN);
|
||||
|
||||
LibInput::MouseEvent event;
|
||||
if (read(mouse_fd, &event, sizeof(event)) == -1)
|
||||
{
|
||||
dwarnln("read mouse: {}", strerror(errno));
|
||||
continue;
|
||||
}
|
||||
switch (event.type)
|
||||
{
|
||||
case LibInput::MouseEventType::MouseButtonEvent:
|
||||
window_server.on_mouse_button(event.button_event);
|
||||
break;
|
||||
case LibInput::MouseEventType::MouseMoveEvent:
|
||||
window_server.on_mouse_move(event.move_event);
|
||||
break;
|
||||
case LibInput::MouseEventType::MouseMoveAbsEvent:
|
||||
window_server.on_mouse_move_abs(event.move_abs_event);
|
||||
break;
|
||||
case LibInput::MouseEventType::MouseScrollEvent:
|
||||
window_server.on_mouse_scroll(event.scroll_event);
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
const int client_fd = events[i].data.fd;
|
||||
if (events[i].events & EPOLLHUP)
|
||||
{
|
||||
epoll_ctl(epoll_fd, EPOLL_CTL_DEL, client_fd, nullptr);
|
||||
window_server.remove_client_fd(client_fd);
|
||||
continue;
|
||||
}
|
||||
|
||||
ASSERT(events[i].events & EPOLLIN);
|
||||
|
||||
auto& client_data = window_server.get_client_data(client_fd);
|
||||
|
||||
if (client_data.packet_buffer.empty())
|
||||
{
|
||||
uint32_t packet_size;
|
||||
const ssize_t nrecv = recv(client_fd, &packet_size, sizeof(uint32_t), 0);
|
||||
if (nrecv < 0)
|
||||
dwarnln("recv: {}", strerror(errno));
|
||||
if (nrecv <= 0)
|
||||
dwarnln("recv 1: {}", strerror(errno));
|
||||
if (nrecv > 0 && nrecv != sizeof(uint32_t))
|
||||
dwarnln("could not read packet size with a single recv call, closing connection...");
|
||||
if (nrecv != sizeof(uint32_t))
|
||||
{
|
||||
window_server.remove_client_fd(fd);
|
||||
return BAN::Iteration::Continue;
|
||||
epoll_ctl(epoll_fd, EPOLL_CTL_DEL, client_fd, nullptr);
|
||||
window_server.remove_client_fd(client_fd);
|
||||
break;
|
||||
}
|
||||
|
||||
client_data.packet_buffer_nread += nrecv;
|
||||
if (client_data.packet_buffer_nread < client_data.packet_buffer.size())
|
||||
return BAN::Iteration::Continue;
|
||||
|
||||
ASSERT(client_data.packet_buffer.size() >= sizeof(uint32_t));
|
||||
|
||||
switch (*reinterpret_cast<LibGUI::PacketType*>(client_data.packet_buffer.data()))
|
||||
if (packet_size < 4)
|
||||
{
|
||||
#define WINDOW_PACKET_CASE(enum, function) \
|
||||
case LibGUI::PacketType::enum: \
|
||||
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);
|
||||
#undef WINDOW_PACKET_CASE
|
||||
default:
|
||||
dprintln("unhandled packet type: {}", *reinterpret_cast<uint32_t*>(client_data.packet_buffer.data()));
|
||||
dwarnln("client sent invalid packet, closing connection...");
|
||||
epoll_ctl(epoll_fd, EPOLL_CTL_DEL, client_fd, nullptr);
|
||||
window_server.remove_client_fd(client_fd);
|
||||
break;
|
||||
}
|
||||
|
||||
// this is a bit harsh, but i don't want to work on skipping streaming packets
|
||||
if (client_data.packet_buffer.resize(packet_size).is_error())
|
||||
{
|
||||
dwarnln("could not allocate memory for client packet, closing connection...");
|
||||
epoll_ctl(epoll_fd, EPOLL_CTL_DEL, client_fd, nullptr);
|
||||
window_server.remove_client_fd(client_fd);
|
||||
break;
|
||||
}
|
||||
|
||||
client_data.packet_buffer.clear();
|
||||
client_data.packet_buffer_nread = 0;
|
||||
return BAN::Iteration::Continue;
|
||||
continue;
|
||||
}
|
||||
);
|
||||
|
||||
const ssize_t nrecv = recv(
|
||||
client_fd,
|
||||
client_data.packet_buffer.data() + client_data.packet_buffer_nread,
|
||||
client_data.packet_buffer.size() - client_data.packet_buffer_nread,
|
||||
0
|
||||
);
|
||||
if (nrecv < 0)
|
||||
dwarnln("recv 2: {}", strerror(errno));
|
||||
if (nrecv <= 0)
|
||||
{
|
||||
epoll_ctl(epoll_fd, EPOLL_CTL_DEL, client_fd, nullptr);
|
||||
window_server.remove_client_fd(client_fd);
|
||||
break;
|
||||
}
|
||||
|
||||
client_data.packet_buffer_nread += nrecv;
|
||||
if (client_data.packet_buffer_nread < client_data.packet_buffer.size())
|
||||
continue;
|
||||
|
||||
ASSERT(client_data.packet_buffer.size() >= sizeof(uint32_t));
|
||||
|
||||
switch (*reinterpret_cast<LibGUI::PacketType*>(client_data.packet_buffer.data()))
|
||||
{
|
||||
#define WINDOW_PACKET_CASE(enum, function) \
|
||||
case LibGUI::PacketType::enum: \
|
||||
if (auto ret = LibGUI::WindowPacket::enum::deserialize(client_data.packet_buffer.span()); !ret.is_error()) \
|
||||
window_server.function(client_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);
|
||||
#undef WINDOW_PACKET_CASE
|
||||
default:
|
||||
dprintln("unhandled packet type: {}", *reinterpret_cast<uint32_t*>(client_data.packet_buffer.data()));
|
||||
}
|
||||
|
||||
client_data.packet_buffer.clear();
|
||||
client_data.packet_buffer_nread = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue