Compare commits
31 Commits
77796dd317
...
e19414a64e
| Author | SHA1 | Date | |
|---|---|---|---|
| e19414a64e | |||
| 98fd86477a | |||
| 16a442f473 | |||
| becfa228fe | |||
| c0ce647c74 | |||
| 05250083b9 | |||
| bb170ba613 | |||
| c79e412215 | |||
| 585e021c7f | |||
| 43d03eb4a9 | |||
| 2a6792b44a | |||
| 954898b14d | |||
| d266d2ca88 | |||
| c72f2f9b31 | |||
| 62e2f4896a | |||
| 9ccdebcd96 | |||
| fe533c2e62 | |||
| ee5c225954 | |||
| 8fccb74542 | |||
| bc8ecbd6fa | |||
| 60484b286f | |||
| 12158d9208 | |||
| 5c94c30e1b | |||
| 81d8ab3d79 | |||
| 6a58c716bd | |||
| c295af9bd5 | |||
| d5ee98708b | |||
| f6679eb4b5 | |||
| ed3924722e | |||
| 4ef03eac97 | |||
| 7ce68b0488 |
@@ -98,7 +98,8 @@ namespace BAN
|
||||
|
||||
struct EntryHash
|
||||
{
|
||||
constexpr bool operator()(const Key& a)
|
||||
template<detail::HashMapFindable<Key, HASH, COMP> U>
|
||||
constexpr bool operator()(const U& a)
|
||||
{
|
||||
return HASH()(a);
|
||||
}
|
||||
@@ -110,7 +111,8 @@ namespace BAN
|
||||
|
||||
struct EntryComp
|
||||
{
|
||||
constexpr bool operator()(const Entry& a, const Key& b)
|
||||
template<detail::HashMapFindable<Key, HASH, COMP> U>
|
||||
constexpr bool operator()(const Entry& a, const U& b)
|
||||
{
|
||||
return COMP()(a.key, b);
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ signal_trampoline:
|
||||
addl $24, %esp
|
||||
|
||||
// restore sigmask
|
||||
movl $83, %eax // SYS_SIGPROCMASK
|
||||
movl $79, %eax // SYS_SIGPROCMASK
|
||||
movl $3, %ebx // SIG_SETMASK
|
||||
leal 72(%esp), %ecx // set
|
||||
xorl %edx, %edx // oset
|
||||
|
||||
@@ -61,7 +61,7 @@ signal_trampoline:
|
||||
addq $40, %rsp
|
||||
|
||||
// restore sigmask
|
||||
movq $83, %rdi // SYS_SIGPROCMASK
|
||||
movq $79, %rdi // SYS_SIGPROCMASK
|
||||
movq $3, %rsi // SIG_SETMASK
|
||||
leaq 192(%rsp), %rdx // set
|
||||
xorq %r10, %r10 // oset
|
||||
|
||||
@@ -99,7 +99,8 @@ namespace Kernel
|
||||
BAN::ErrorOr<uint32_t> reserve_free_block(uint32_t primary_bgd);
|
||||
BAN::ErrorOr<void> release_block(uint32_t block);
|
||||
|
||||
BAN::HashMap<ino_t, BAN::RefPtr<Ext2Inode>>& inode_cache() { return m_inode_cache; }
|
||||
BAN::ErrorOr<BAN::RefPtr<Ext2Inode>> open_inode(ino_t);
|
||||
void remove_from_cache(ino_t);
|
||||
|
||||
const Ext2::Superblock& superblock() const { return m_superblock; }
|
||||
|
||||
@@ -155,6 +156,7 @@ namespace Kernel
|
||||
BAN::RefPtr<Inode> m_root_inode;
|
||||
BAN::Vector<uint32_t> m_superblock_backups;
|
||||
|
||||
Mutex m_inode_cache_lock;
|
||||
BAN::HashMap<ino_t, BAN::RefPtr<Ext2Inode>> m_inode_cache;
|
||||
|
||||
BlockBufferManager m_buffer_manager;
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace Kernel
|
||||
BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode_no_lock(BAN::StringView);
|
||||
|
||||
/* needs write end of the lock when allocate is true*/
|
||||
BAN::ErrorOr<BAN::Optional<uint32_t>> block_from_indirect_block_no_lock(uint32_t& block, uint32_t index, uint32_t depth, bool allocate);
|
||||
BAN::ErrorOr<BAN::Optional<uint32_t>> block_from_indirect_block_no_lock(uint32_t block, uint32_t index, uint32_t depth, bool allocate);
|
||||
BAN::ErrorOr<BAN::Optional<uint32_t>> fs_block_of_data_block_index_no_lock(uint32_t data_block_index, bool allocate);
|
||||
|
||||
/* needs write end of the lock */
|
||||
@@ -71,7 +71,13 @@ namespace Kernel
|
||||
private:
|
||||
Ext2Inode(Ext2FS& fs, Ext2::Inode inode, uint32_t ino);
|
||||
|
||||
static BAN::ErrorOr<BAN::RefPtr<Ext2Inode>> create(Ext2FS&, uint32_t);
|
||||
BAN::Optional<uint32_t> block_cache_find(uint32_t block, uint32_t index) const;
|
||||
void block_cache_remove(uint32_t block, uint32_t index);
|
||||
void block_cache_add(uint32_t block, uint32_t index, uint32_t target);
|
||||
|
||||
BAN::RefPtr<Inode> dir_cache_find(BAN::StringView) const;
|
||||
void dir_cache_remove(BAN::StringView);
|
||||
void dir_cache_add(BAN::StringView, BAN::RefPtr<Inode>);
|
||||
|
||||
private:
|
||||
struct ScopedSync
|
||||
@@ -107,6 +113,27 @@ namespace Kernel
|
||||
const uint32_t m_og_faddr;
|
||||
const Ext2::Osd2 m_og_osd2;
|
||||
|
||||
struct BlockCacheEntry
|
||||
{
|
||||
mutable uint32_t freq;
|
||||
uint32_t block;
|
||||
uint32_t index;
|
||||
uint32_t target;
|
||||
};
|
||||
mutable SpinLock m_block_cache_lock;
|
||||
BAN::Array<BlockCacheEntry, 8> m_block_cache;
|
||||
|
||||
struct DirCacheEntry
|
||||
{
|
||||
mutable size_t freq { 0 };
|
||||
BAN::RefPtr<Inode> inode;
|
||||
size_t name_len { 0 };
|
||||
char name[256];
|
||||
};
|
||||
static constexpr size_t dir_cache_size = 32;
|
||||
mutable RWLock m_dir_cache_lock;
|
||||
BAN::Vector<DirCacheEntry> m_dir_cache;
|
||||
|
||||
friend class Ext2FS;
|
||||
friend class BAN::RefPtr<Ext2Inode>;
|
||||
};
|
||||
|
||||
@@ -13,6 +13,8 @@ namespace Kernel
|
||||
static void initialize();
|
||||
static ProcFileSystem& get();
|
||||
|
||||
void post_scheduler_initialize();
|
||||
|
||||
BAN::ErrorOr<void> on_process_create(Process&);
|
||||
void on_process_delete(Process&);
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ namespace Kernel
|
||||
class ProcROInode final : public TmpInode
|
||||
{
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::RefPtr<ProcROInode>> create_new(size_t (*callback)(off_t, BAN::ByteSpan), TmpFileSystem&, mode_t, uid_t, gid_t);
|
||||
static BAN::ErrorOr<BAN::RefPtr<ProcROInode>> create_new(BAN::ErrorOr<size_t> (*callback)(off_t, BAN::ByteSpan, void*), TmpFileSystem&, void*, mode_t, uid_t, gid_t);
|
||||
~ProcROInode() = default;
|
||||
|
||||
protected:
|
||||
@@ -92,10 +92,11 @@ namespace Kernel
|
||||
virtual bool has_hungup_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
ProcROInode(size_t (*callback)(off_t, BAN::ByteSpan), TmpFileSystem&, const TmpInodeInfo&);
|
||||
ProcROInode(BAN::ErrorOr<size_t> (*callback)(off_t, BAN::ByteSpan, void*), TmpFileSystem&, void*, const TmpInodeInfo&);
|
||||
|
||||
private:
|
||||
size_t (*m_callback)(off_t, BAN::ByteSpan);
|
||||
BAN::ErrorOr<size_t> (*m_callback)(off_t, BAN::ByteSpan, void*);
|
||||
void* m_argument;
|
||||
};
|
||||
|
||||
class ProcSymlinkInode final : public TmpInode
|
||||
|
||||
@@ -92,8 +92,9 @@ namespace Kernel
|
||||
MountPoint* mount_from_root_inode(BAN::RefPtr<Inode>);
|
||||
|
||||
private:
|
||||
Mutex m_mutex;
|
||||
BAN::RefPtr<FileSystem> m_root_fs;
|
||||
|
||||
Mutex m_mount_point_lock;
|
||||
BAN::Vector<MountPoint> m_mount_points;
|
||||
|
||||
friend class BAN::RefPtr<VirtualFileSystem>;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <kernel/Lock/Mutex.h>
|
||||
#include <kernel/Lock/LockGuard.h>
|
||||
#include <kernel/Lock/SpinLock.h>
|
||||
#include <kernel/Lock/SpinLockAsMutex.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
@@ -15,15 +15,18 @@ namespace Kernel
|
||||
|
||||
void rd_lock()
|
||||
{
|
||||
LockGuard _(m_mutex);
|
||||
SpinLockGuard _(m_lock);
|
||||
while (m_writers_waiting > 0 || m_writer != -1)
|
||||
m_thread_blocker.block_indefinite(&m_mutex);
|
||||
{
|
||||
SpinLockGuardAsMutex smutex(_);
|
||||
m_thread_blocker.block_indefinite(&smutex);
|
||||
}
|
||||
m_readers_active++;
|
||||
}
|
||||
|
||||
void rd_unlock()
|
||||
{
|
||||
LockGuard _(m_mutex);
|
||||
SpinLockGuard _(m_lock);
|
||||
if (--m_readers_active == 0)
|
||||
m_thread_blocker.unblock();
|
||||
}
|
||||
@@ -36,11 +39,14 @@ namespace Kernel
|
||||
return;
|
||||
}
|
||||
|
||||
LockGuard _(m_mutex);
|
||||
SpinLockGuard _(m_lock);
|
||||
|
||||
m_writers_waiting++;
|
||||
while (m_readers_active > 0 || m_writer != -1)
|
||||
m_thread_blocker.block_indefinite(&m_mutex);
|
||||
{
|
||||
SpinLockGuardAsMutex smutex(_);
|
||||
m_thread_blocker.block_indefinite(&smutex);
|
||||
}
|
||||
m_writers_waiting--;
|
||||
|
||||
m_writer = Thread::current_tid();
|
||||
@@ -51,13 +57,13 @@ namespace Kernel
|
||||
{
|
||||
if (--m_writer_depth != 0)
|
||||
return;
|
||||
LockGuard _(m_mutex);
|
||||
SpinLockGuard _(m_lock);
|
||||
m_writer = -1;
|
||||
m_thread_blocker.unblock();
|
||||
}
|
||||
|
||||
private:
|
||||
Mutex m_mutex;
|
||||
SpinLock m_lock;
|
||||
ThreadBlocker m_thread_blocker;
|
||||
uint32_t m_readers_active { 0 };
|
||||
uint32_t m_writers_waiting { 0 };
|
||||
|
||||
@@ -65,6 +65,9 @@ namespace Kernel
|
||||
}
|
||||
virtual BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span<const BAN::ConstByteSpan> payload) = 0;
|
||||
|
||||
private:
|
||||
BAN::ErrorOr<long> ioctl_impl(int, void*) override;
|
||||
|
||||
private:
|
||||
const Type m_type;
|
||||
char m_name[10];
|
||||
|
||||
@@ -58,6 +58,8 @@ namespace Kernel
|
||||
BAN::ErrorOr<size_t> recvmsg(int socket, msghdr& message, int flags);
|
||||
BAN::ErrorOr<size_t> sendmsg(int socket, const msghdr& message, int flags);
|
||||
|
||||
int get_max_open_fd() const;
|
||||
|
||||
BAN::ErrorOr<VirtualFileSystem::File> file_of(int) const;
|
||||
BAN::ErrorOr<BAN::String> path_of(int) const;
|
||||
BAN::ErrorOr<BAN::RefPtr<Inode>> inode_of(int);
|
||||
|
||||
@@ -57,6 +57,12 @@ namespace Kernel
|
||||
};
|
||||
};
|
||||
|
||||
struct LoadStats
|
||||
{
|
||||
uint64_t ns_idle;
|
||||
uint64_t ns_total;
|
||||
};
|
||||
|
||||
public:
|
||||
static Processor& create(ProcessorID id);
|
||||
static Processor& initialize();
|
||||
@@ -72,9 +78,6 @@ namespace Kernel
|
||||
static void set_smp_enabled() { s_is_smp_enabled = true; }
|
||||
static void wait_until_processors_ready();
|
||||
|
||||
static void toggle_should_print_cpu_load() { s_should_print_cpu_load = !s_should_print_cpu_load; }
|
||||
static bool get_should_print_cpu_load() { return s_should_print_cpu_load; }
|
||||
|
||||
static ProcessorID bsp_id() { return s_bsp_id; }
|
||||
static bool current_is_bsp() { return current_id() == bsp_id(); }
|
||||
|
||||
@@ -116,6 +119,8 @@ namespace Kernel
|
||||
static void* get_current_page_table() { return read_gs_sized<void*>(offsetof(Processor, m_current_page_table)); }
|
||||
static void set_current_page_table(void* page_table) { write_gs_sized<void*>(offsetof(Processor, m_current_page_table), page_table); }
|
||||
|
||||
static LoadStats get_load_stats(size_t index);
|
||||
|
||||
static void yield();
|
||||
static Scheduler& scheduler() { return *read_gs_sized<Scheduler*>(offsetof(Processor, m_scheduler)); }
|
||||
|
||||
@@ -187,7 +192,6 @@ namespace Kernel
|
||||
static ProcessorID s_bsp_id;
|
||||
static BAN::Atomic<uint8_t> s_processor_count;
|
||||
static BAN::Atomic<bool> s_is_smp_enabled;
|
||||
static BAN::Atomic<bool> s_should_print_cpu_load;
|
||||
static paddr_t s_shared_page_paddr;
|
||||
static vaddr_t s_shared_page_vaddr;
|
||||
|
||||
@@ -207,10 +211,9 @@ namespace Kernel
|
||||
|
||||
Scheduler* m_scheduler { nullptr };
|
||||
|
||||
uint64_t m_start_ns { 0 };
|
||||
uint64_t m_idle_ns { 0 };
|
||||
uint64_t m_last_update_ns { 0 };
|
||||
uint64_t m_next_update_ns { 0 };
|
||||
BAN::Atomic<bool> m_load_stat_lock;
|
||||
uint64_t m_load_start_ns { 0 };
|
||||
LoadStats m_load_stats {};
|
||||
|
||||
BAN::Atomic<SMPMessage*> m_smp_pending { nullptr };
|
||||
BAN::Atomic<SMPMessage*> m_smp_free { nullptr };
|
||||
|
||||
@@ -356,52 +356,8 @@ namespace Kernel
|
||||
|
||||
void do_msync(uint32_t first_pixel, uint32_t pixel_count)
|
||||
{
|
||||
if (!Processor::get_should_print_cpu_load())
|
||||
return m_framebuffer->sync_pixels_linear(first_pixel, pixel_count);
|
||||
|
||||
const uint32_t fb_width = m_framebuffer->width();
|
||||
|
||||
// If we are here (in FramebufferMemoryRegion), our terminal driver is FramebufferTerminalDriver
|
||||
ASSERT(g_terminal_driver->has_font());
|
||||
const auto& font = g_terminal_driver->font();
|
||||
|
||||
const uint32_t x = first_pixel % fb_width;
|
||||
const uint32_t y = first_pixel / fb_width;
|
||||
|
||||
const uint32_t load_w = 16 * font.width();
|
||||
const uint32_t load_h = Processor::count() * font.height();
|
||||
|
||||
if (y >= load_h || x + pixel_count <= fb_width - load_w)
|
||||
return m_framebuffer->sync_pixels_linear(first_pixel, pixel_count);
|
||||
|
||||
if (x >= fb_width - load_w && x + pixel_count <= fb_width)
|
||||
return;
|
||||
|
||||
if (x < fb_width - load_w)
|
||||
m_framebuffer->sync_pixels_linear(first_pixel, fb_width - load_w - x);
|
||||
|
||||
if (x + pixel_count > fb_width)
|
||||
{
|
||||
const uint32_t past_last_pixel = first_pixel + pixel_count;
|
||||
|
||||
first_pixel = (y + 1) * fb_width;
|
||||
pixel_count = past_last_pixel - first_pixel;
|
||||
|
||||
const uint32_t cpu_load_end = load_h * fb_width;
|
||||
|
||||
while (pixel_count && first_pixel < cpu_load_end)
|
||||
{
|
||||
m_framebuffer->sync_pixels_linear(first_pixel, BAN::Math::min(pixel_count, fb_width - load_w));
|
||||
|
||||
const uint32_t advance = BAN::Math::min(pixel_count, fb_width);
|
||||
pixel_count -= advance;
|
||||
first_pixel += advance;
|
||||
}
|
||||
|
||||
if (pixel_count)
|
||||
m_framebuffer->sync_pixels_linear(first_pixel, pixel_count);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
BAN::RefPtr<FramebufferDevice> m_framebuffer;
|
||||
|
||||
@@ -167,10 +167,36 @@ namespace Kernel
|
||||
|
||||
BAN::ErrorOr<void> Ext2FS::initialize_root_inode()
|
||||
{
|
||||
m_root_inode = TRY(Ext2Inode::create(*this, Ext2::Enum::ROOT_INO));
|
||||
m_root_inode = TRY(open_inode(Ext2::Enum::ROOT_INO));
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<BAN::RefPtr<Ext2Inode>> Ext2FS::open_inode(ino_t ino)
|
||||
{
|
||||
LockGuard _(m_inode_cache_lock);
|
||||
|
||||
auto it = m_inode_cache.find(ino);
|
||||
if (it != m_inode_cache.end())
|
||||
return it->value;
|
||||
|
||||
auto inode_location = TRY(locate_inode(ino));
|
||||
|
||||
auto block_buffer = TRY(get_block_buffer());
|
||||
TRY(read_block(inode_location.block, block_buffer));
|
||||
|
||||
auto& inode = block_buffer.span().slice(inode_location.offset).as<Ext2::Inode>();
|
||||
|
||||
auto result = TRY(BAN::RefPtr<Ext2Inode>::create(*this, inode, ino));
|
||||
TRY(m_inode_cache.insert(ino, result));
|
||||
return result;
|
||||
}
|
||||
|
||||
void Ext2FS::remove_from_cache(ino_t ino)
|
||||
{
|
||||
LockGuard _(m_inode_cache_lock);
|
||||
m_inode_cache.remove(ino);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<uint32_t> Ext2FS::create_inode(const Ext2::Inode& ext2_inode)
|
||||
{
|
||||
auto bgd_buffer = TRY(m_buffer_manager.get_buffer());
|
||||
|
||||
@@ -42,24 +42,6 @@ namespace Kernel
|
||||
return (m_ino - 1) / m_fs.superblock().blocks_per_group;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<BAN::RefPtr<Ext2Inode>> Ext2Inode::create(Ext2FS& fs, uint32_t inode_ino)
|
||||
{
|
||||
auto it = fs.inode_cache().find(inode_ino);
|
||||
if (it != fs.inode_cache().end())
|
||||
return it->value;
|
||||
|
||||
auto inode_location = TRY(fs.locate_inode(inode_ino));
|
||||
|
||||
auto block_buffer = TRY(fs.get_block_buffer());
|
||||
TRY(fs.read_block(inode_location.block, block_buffer));
|
||||
|
||||
auto& inode = block_buffer.span().slice(inode_location.offset).as<Ext2::Inode>();
|
||||
|
||||
auto result = TRY(BAN::RefPtr<Ext2Inode>::create(fs, inode, inode_ino));
|
||||
TRY(fs.inode_cache().insert(inode_ino, result));
|
||||
return result;
|
||||
}
|
||||
|
||||
Ext2Inode::~Ext2Inode()
|
||||
{
|
||||
if (m_nlink > 0)
|
||||
@@ -89,57 +71,53 @@ namespace Kernel
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<BAN::Optional<uint32_t>> Ext2Inode::block_from_indirect_block_no_lock(uint32_t& block, uint32_t index, uint32_t depth, bool allocate)
|
||||
BAN::ErrorOr<BAN::Optional<uint32_t>> Ext2Inode::block_from_indirect_block_no_lock(uint32_t block, uint32_t index, uint32_t depth, bool allocate)
|
||||
{
|
||||
const uint32_t indices_per_fs_block = blksize() / sizeof(uint32_t);
|
||||
|
||||
if (block == 0 && !allocate)
|
||||
return BAN::Optional<uint32_t>();
|
||||
ASSERT(block != 0);
|
||||
|
||||
if (depth == 0)
|
||||
{
|
||||
if (block == 0)
|
||||
{
|
||||
block = TRY(m_fs.reserve_free_block(block_group()));
|
||||
m_blocks++;
|
||||
|
||||
auto block_buffer = TRY(m_fs.get_block_buffer());
|
||||
memset(block_buffer.data(), 0x00, block_buffer.size());
|
||||
TRY(m_fs.write_block(block, block_buffer));
|
||||
}
|
||||
|
||||
return BAN::Optional<uint32_t>(block);
|
||||
}
|
||||
|
||||
auto block_buffer = TRY(m_fs.get_block_buffer());
|
||||
uint32_t local_index = index;
|
||||
for (uint32_t i = 1; i < depth; i++)
|
||||
local_index /= indices_per_fs_block;
|
||||
local_index %= indices_per_fs_block;
|
||||
|
||||
bool needs_write = false;
|
||||
uint32_t next_block = 0;
|
||||
|
||||
if (block != 0)
|
||||
TRY(m_fs.read_block(block, block_buffer));
|
||||
else
|
||||
if (auto cached = block_cache_find(block, local_index); cached.has_value())
|
||||
next_block = cached.value();
|
||||
|
||||
if (next_block == 0)
|
||||
{
|
||||
block = TRY(m_fs.reserve_free_block(block_group()));
|
||||
auto block_buffer = TRY(m_fs.get_block_buffer());
|
||||
TRY(m_fs.read_block(block, block_buffer));
|
||||
auto block_span = block_buffer.span().as_span<uint32_t>();
|
||||
|
||||
next_block = block_span[local_index];
|
||||
|
||||
if (next_block == 0)
|
||||
{
|
||||
if (!allocate)
|
||||
return BAN::Optional<uint32_t>();
|
||||
|
||||
auto zero_buffer = TRY(m_fs.get_block_buffer());
|
||||
memset(zero_buffer.data(), 0, zero_buffer.size());
|
||||
|
||||
next_block = TRY(m_fs.reserve_free_block(block_group()));
|
||||
TRY(m_fs.write_block(next_block, zero_buffer));
|
||||
m_blocks++;
|
||||
|
||||
memset(block_buffer.data(), 0, block_buffer.size());
|
||||
|
||||
needs_write = true;
|
||||
block_span[local_index] = next_block;
|
||||
TRY(m_fs.write_block(block, block_buffer));
|
||||
}
|
||||
|
||||
uint32_t divisor = 1;
|
||||
for (uint32_t i = 1; i < depth; i++)
|
||||
divisor *= indices_per_fs_block;
|
||||
block_cache_add(block, local_index, next_block);
|
||||
}
|
||||
|
||||
uint32_t& new_block = block_buffer.span().as_span<uint32_t>()[(index / divisor) % indices_per_fs_block];
|
||||
const auto old_block = new_block;
|
||||
|
||||
const auto result = TRY(block_from_indirect_block_no_lock(new_block, index, depth - 1, allocate));
|
||||
|
||||
if (needs_write || old_block != new_block)
|
||||
TRY(m_fs.write_block(block, block_buffer));
|
||||
|
||||
return result;
|
||||
return block_from_indirect_block_no_lock(next_block, index, depth - 1, allocate);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<BAN::Optional<uint32_t>> Ext2Inode::fs_block_of_data_block_index_no_lock(uint32_t data_block_index, bool allocate)
|
||||
@@ -166,16 +144,29 @@ namespace Kernel
|
||||
}
|
||||
data_block_index -= 12;
|
||||
|
||||
if (data_block_index < indices_per_block)
|
||||
return block_from_indirect_block_no_lock(m_ext2_blocks.block[12], data_block_index, 1, allocate);
|
||||
uint32_t depth_block_count = indices_per_block;
|
||||
for (size_t i = 0; i < 3; i++)
|
||||
{
|
||||
if (data_block_index < depth_block_count)
|
||||
{
|
||||
auto& block = m_ext2_blocks.block[12 + i];
|
||||
if (block == 0)
|
||||
{
|
||||
if (!allocate)
|
||||
return BAN::Optional<uint32_t>();
|
||||
|
||||
auto zero_buffer = TRY(m_fs.get_block_buffer());
|
||||
memset(zero_buffer.data(), 0, zero_buffer.size());
|
||||
|
||||
block = TRY(m_fs.reserve_free_block(block_group()));
|
||||
TRY(m_fs.write_block(block, zero_buffer));
|
||||
m_blocks++;
|
||||
}
|
||||
return block_from_indirect_block_no_lock(block, data_block_index, i + 1, allocate);
|
||||
}
|
||||
data_block_index -= indices_per_block;
|
||||
|
||||
if (data_block_index < indices_per_block * indices_per_block)
|
||||
return block_from_indirect_block_no_lock(m_ext2_blocks.block[13], data_block_index, 2, allocate);
|
||||
data_block_index -= indices_per_block * indices_per_block;
|
||||
|
||||
if (data_block_index < indices_per_block * indices_per_block * indices_per_block)
|
||||
return block_from_indirect_block_no_lock(m_ext2_blocks.block[14], data_block_index, 3, allocate);
|
||||
depth_block_count *= indices_per_block;
|
||||
}
|
||||
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
@@ -542,7 +533,7 @@ done:
|
||||
|
||||
const uint32_t new_ino = TRY(m_fs.create_inode(initialize_new_inode_info(mode, uid, gid)));
|
||||
|
||||
auto inode_or_error = Ext2Inode::create(m_fs, new_ino);
|
||||
auto inode_or_error = m_fs.open_inode(new_ino);
|
||||
if (inode_or_error.is_error())
|
||||
{
|
||||
TRY(m_fs.delete_inode(new_ino));
|
||||
@@ -568,7 +559,7 @@ done:
|
||||
|
||||
const uint32_t new_ino = TRY(m_fs.create_inode(initialize_new_inode_info(mode, uid, gid)));
|
||||
|
||||
auto inode_or_error = Ext2Inode::create(m_fs, new_ino);
|
||||
auto inode_or_error = m_fs.open_inode(new_ino);
|
||||
if (inode_or_error.is_error())
|
||||
{
|
||||
TRY(m_fs.delete_inode(new_ino));
|
||||
@@ -814,7 +805,7 @@ needs_new_block:
|
||||
}
|
||||
else if (entry_name == ".."_sv)
|
||||
{
|
||||
auto parent = TRY(Ext2Inode::create(m_fs, entry.inode));
|
||||
auto parent = TRY(m_fs.open_inode(entry.inode));
|
||||
parent->m_nlink--;
|
||||
TRY(parent->sync_inode_no_lock());
|
||||
}
|
||||
@@ -860,7 +851,7 @@ needs_new_block:
|
||||
auto& entry = block_buffer.span().slice(offset).as<Ext2::LinkedDirectoryEntry>();
|
||||
if (entry.inode && name == BAN::StringView(entry.name, entry.name_len))
|
||||
{
|
||||
auto inode = TRY(Ext2Inode::create(m_fs, entry.inode));
|
||||
auto inode = TRY(m_fs.open_inode(entry.inode));
|
||||
if (cleanup_directory && inode->mode().ifdir())
|
||||
{
|
||||
if (!TRY(inode->is_directory_empty_no_lock()))
|
||||
@@ -878,11 +869,7 @@ needs_new_block:
|
||||
// NOTE: If this was the last link to inode we must
|
||||
// remove it from inode cache to trigger cleanup
|
||||
if (inode->nlink() == 0)
|
||||
{
|
||||
auto& cache = m_fs.inode_cache();
|
||||
if (cache.contains(inode->ino()))
|
||||
cache.remove(inode->ino());
|
||||
}
|
||||
m_fs.remove_from_cache(inode->ino());
|
||||
|
||||
// FIXME: This should expand the last inode if exists
|
||||
entry.inode = 0;
|
||||
@@ -892,6 +879,8 @@ needs_new_block:
|
||||
}
|
||||
}
|
||||
|
||||
dir_cache_remove(name);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -948,6 +937,9 @@ needs_new_block:
|
||||
{
|
||||
ASSERT(mode().ifdir());
|
||||
|
||||
if (auto cached = dir_cache_find(file_name))
|
||||
return cached;
|
||||
|
||||
auto block_buffer = TRY(m_fs.get_block_buffer());
|
||||
|
||||
for (uint32_t i = 0; i < max_used_data_block_count(); i++)
|
||||
@@ -963,11 +955,129 @@ needs_new_block:
|
||||
auto& entry = entry_span.as<const Ext2::LinkedDirectoryEntry>();
|
||||
BAN::StringView entry_name(entry.name, entry.name_len);
|
||||
if (entry.inode && entry_name == file_name)
|
||||
return BAN::RefPtr<Inode>(TRY(Ext2Inode::create(m_fs, entry.inode)));
|
||||
{
|
||||
auto inode = BAN::RefPtr<Inode>(TRY(m_fs.open_inode(entry.inode)));
|
||||
dir_cache_add(file_name, inode);
|
||||
return inode;
|
||||
}
|
||||
entry_span = entry_span.slice(entry.rec_len);
|
||||
}
|
||||
}
|
||||
|
||||
return BAN::Error::from_errno(ENOENT);
|
||||
}
|
||||
|
||||
BAN::Optional<uint32_t> Ext2Inode::block_cache_find(uint32_t block, uint32_t index) const
|
||||
{
|
||||
SpinLockGuard _(m_block_cache_lock);
|
||||
for (const auto& cache : m_block_cache)
|
||||
{
|
||||
if (cache.block != block || cache.index != index)
|
||||
continue;
|
||||
cache.freq++;
|
||||
return cache.target;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void Ext2Inode::block_cache_remove(uint32_t block, uint32_t index)
|
||||
{
|
||||
SpinLockGuard _(m_block_cache_lock);
|
||||
for (auto& cache : m_block_cache)
|
||||
{
|
||||
if (cache.block != block || cache.index != index)
|
||||
continue;
|
||||
cache = {};
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void Ext2Inode::block_cache_add(uint32_t block, uint32_t index, uint32_t target)
|
||||
{
|
||||
SpinLockGuard _(m_block_cache_lock);
|
||||
|
||||
size_t min_freq = BAN::numeric_limits<size_t>::max();
|
||||
size_t min_index = 0;
|
||||
for (size_t i = 0; i < m_block_cache.size(); i++)
|
||||
{
|
||||
const auto& cache = m_block_cache[i];
|
||||
if (cache.block == block && cache.index == index)
|
||||
{
|
||||
ASSERT(cache.target == target);
|
||||
cache.freq++;
|
||||
return;
|
||||
}
|
||||
if (cache.freq < min_freq)
|
||||
{
|
||||
min_freq = cache.freq;
|
||||
min_index = i;
|
||||
}
|
||||
}
|
||||
|
||||
m_block_cache[min_index] = {
|
||||
.freq = 1,
|
||||
.block = block,
|
||||
.index = index,
|
||||
.target = target,
|
||||
};
|
||||
}
|
||||
|
||||
BAN::RefPtr<Inode> Ext2Inode::dir_cache_find(BAN::StringView name) const
|
||||
{
|
||||
RWLockRDGuard _(m_dir_cache_lock);
|
||||
for (const auto& cache : m_dir_cache)
|
||||
{
|
||||
if (!cache.inode || name != BAN::StringView(cache.name, cache.name_len))
|
||||
continue;
|
||||
BAN::atomic_add_fetch(cache.freq, 1);
|
||||
return cache.inode;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void Ext2Inode::dir_cache_remove(BAN::StringView name)
|
||||
{
|
||||
RWLockWRGuard _(m_dir_cache_lock);
|
||||
for (auto& cache : m_dir_cache)
|
||||
{
|
||||
if (!cache.inode || name != BAN::StringView(cache.name, cache.name_len))
|
||||
continue;
|
||||
cache.freq = 0;
|
||||
cache.inode = {};
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void Ext2Inode::dir_cache_add(BAN::StringView name, BAN::RefPtr<Inode> inode)
|
||||
{
|
||||
RWLockWRGuard _(m_dir_cache_lock);
|
||||
|
||||
if (m_dir_cache.empty() && m_dir_cache.resize(dir_cache_size).is_error())
|
||||
return;
|
||||
|
||||
size_t min_freq = BAN::numeric_limits<size_t>::max();
|
||||
size_t min_index = 0;
|
||||
for (size_t i = 0; i < m_dir_cache.size(); i++)
|
||||
{
|
||||
const auto& cache = m_dir_cache[i];
|
||||
if (cache.inode && name == BAN::StringView(cache.name, cache.name_len))
|
||||
{
|
||||
ASSERT(cache.inode == inode);
|
||||
cache.freq++;
|
||||
return;
|
||||
}
|
||||
if (cache.freq < min_freq)
|
||||
{
|
||||
min_freq = cache.freq;
|
||||
min_index = i;
|
||||
}
|
||||
}
|
||||
|
||||
auto& cache = m_dir_cache[min_index];
|
||||
cache.freq = 1;
|
||||
cache.inode = inode;
|
||||
cache.name_len = name.size();
|
||||
memcpy(cache.name, name.data(), name.size());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,22 +16,23 @@ namespace Kernel
|
||||
MUST(s_instance->TmpFileSystem::initialize(0555, 0, 0));
|
||||
|
||||
auto meminfo_inode = MUST(ProcROInode::create_new(
|
||||
[](off_t offset, BAN::ByteSpan buffer) -> size_t
|
||||
[](off_t offset, BAN::ByteSpan buffer, void*) -> BAN::ErrorOr<size_t>
|
||||
{
|
||||
ASSERT(offset >= 0);
|
||||
if ((size_t)offset >= sizeof(full_meminfo_t))
|
||||
return 0;
|
||||
|
||||
full_meminfo_t meminfo;
|
||||
meminfo.page_size = PAGE_SIZE;
|
||||
meminfo.free_pages = Heap::get().free_pages();
|
||||
meminfo.used_pages = Heap::get().used_pages();
|
||||
const full_meminfo_t meminfo {
|
||||
.page_size = PAGE_SIZE,
|
||||
.free_pages = Heap::get().free_pages(),
|
||||
.used_pages = Heap::get().used_pages(),
|
||||
};
|
||||
|
||||
size_t bytes = BAN::Math::min<size_t>(sizeof(full_meminfo_t) - offset, buffer.size());
|
||||
memcpy(buffer.data(), (uint8_t*)&meminfo + offset, bytes);
|
||||
return bytes;
|
||||
},
|
||||
*s_instance, 0444, 0, 0
|
||||
*s_instance, nullptr, 0444, 0, 0
|
||||
));
|
||||
MUST(static_cast<TmpDirectoryInode*>(s_instance->root_inode().ptr())->link_inode(*meminfo_inode, "meminfo"_sv));
|
||||
|
||||
@@ -48,6 +49,35 @@ namespace Kernel
|
||||
MUST(static_cast<TmpDirectoryInode*>(s_instance->root_inode().ptr())->link_inode(*self_inode, "self"_sv));
|
||||
}
|
||||
|
||||
void ProcFileSystem::post_scheduler_initialize()
|
||||
{
|
||||
MUST(s_instance->root_inode()->create_directory("cpu"_sv, Inode::Mode::IFDIR | 0555, 0, 0));
|
||||
auto cpu_directory = MUST(s_instance->root_inode()->find_inode("cpu"_sv));
|
||||
|
||||
for (size_t i = 0; i < Processor::count(); i++)
|
||||
{
|
||||
auto cpu_inode = MUST(ProcROInode::create_new(
|
||||
[](off_t offset, BAN::ByteSpan buffer, void* index_ptr) -> BAN::ErrorOr<size_t>
|
||||
{
|
||||
ASSERT(offset >= 0);
|
||||
|
||||
const size_t index = reinterpret_cast<uintptr_t>(index_ptr);
|
||||
const auto load_stats = Processor::get_load_stats(index);
|
||||
|
||||
auto string = TRY(BAN::String::formatted("{} {}", load_stats.ns_idle, load_stats.ns_total));
|
||||
if (static_cast<size_t>(offset) >= string.size())
|
||||
return 0;
|
||||
|
||||
const size_t bytes = BAN::Math::min<size_t>(string.size() - offset, buffer.size());
|
||||
memcpy(buffer.data(), string.data() + offset, bytes);
|
||||
return bytes;
|
||||
},
|
||||
*s_instance, reinterpret_cast<void*>(i), 0444, 0, 0
|
||||
));
|
||||
MUST(cpu_directory->link_inode(MUST(BAN::String::formatted("{}", i)), cpu_inode));
|
||||
}
|
||||
}
|
||||
|
||||
ProcFileSystem& ProcFileSystem::get()
|
||||
{
|
||||
ASSERT(s_instance);
|
||||
|
||||
@@ -95,19 +95,20 @@ namespace Kernel
|
||||
return (m_process.*m_callback)();
|
||||
}
|
||||
|
||||
BAN::ErrorOr<BAN::RefPtr<ProcROInode>> ProcROInode::create_new(size_t (*callback)(off_t, BAN::ByteSpan), TmpFileSystem& fs, mode_t mode, uid_t uid, gid_t gid)
|
||||
BAN::ErrorOr<BAN::RefPtr<ProcROInode>> ProcROInode::create_new(BAN::ErrorOr<size_t> (*callback)(off_t, BAN::ByteSpan, void*), TmpFileSystem& fs, void* argument, mode_t mode, uid_t uid, gid_t gid)
|
||||
{
|
||||
auto inode_info = create_inode_info(Mode::IFREG | mode, uid, gid);
|
||||
|
||||
auto* inode_ptr = new ProcROInode(callback, fs, inode_info);
|
||||
auto* inode_ptr = new ProcROInode(callback, fs, argument, inode_info);
|
||||
if (inode_ptr == nullptr)
|
||||
return BAN::Error::from_errno(ENOMEM);
|
||||
return BAN::RefPtr<ProcROInode>::adopt(inode_ptr);
|
||||
}
|
||||
|
||||
ProcROInode::ProcROInode(size_t (*callback)(off_t, BAN::ByteSpan), TmpFileSystem& fs, const TmpInodeInfo& inode_info)
|
||||
ProcROInode::ProcROInode(BAN::ErrorOr<size_t> (*callback)(off_t, BAN::ByteSpan, void*), TmpFileSystem& fs, void* argument, const TmpInodeInfo& inode_info)
|
||||
: TmpInode(fs, MUST(fs.allocate_inode(inode_info)), inode_info)
|
||||
, m_callback(callback)
|
||||
, m_argument(argument)
|
||||
{
|
||||
m_mode |= Inode::Mode::IFREG;
|
||||
}
|
||||
@@ -116,7 +117,7 @@ namespace Kernel
|
||||
{
|
||||
if (offset < 0)
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
return m_callback(offset, buffer);
|
||||
return TRY(m_callback(offset, buffer, m_argument));
|
||||
}
|
||||
|
||||
BAN::ErrorOr<BAN::RefPtr<ProcSymlinkInode>> ProcSymlinkInode::create_new(BAN::ErrorOr<BAN::String> (*callback)(void*), void (*destructor)(void*), void* data, TmpFileSystem& fs, mode_t mode, uid_t uid, gid_t gid)
|
||||
|
||||
@@ -210,14 +210,14 @@ namespace Kernel
|
||||
if (!file.inode->mode().ifdir())
|
||||
return BAN::Error::from_errno(ENOTDIR);
|
||||
|
||||
LockGuard _(m_mutex);
|
||||
LockGuard _(m_mount_point_lock);
|
||||
TRY(m_mount_points.emplace_back(file_system, BAN::move(file)));
|
||||
return {};
|
||||
}
|
||||
|
||||
VirtualFileSystem::MountPoint* VirtualFileSystem::mount_from_host_inode(BAN::RefPtr<Inode> inode)
|
||||
{
|
||||
LockGuard _(m_mutex);
|
||||
LockGuard _(m_mount_point_lock);
|
||||
for (MountPoint& mount : m_mount_points)
|
||||
if (*mount.host.inode == *inode)
|
||||
return &mount;
|
||||
@@ -226,53 +226,52 @@ namespace Kernel
|
||||
|
||||
VirtualFileSystem::MountPoint* VirtualFileSystem::mount_from_root_inode(BAN::RefPtr<Inode> inode)
|
||||
{
|
||||
LockGuard _(m_mutex);
|
||||
LockGuard _(m_mount_point_lock);
|
||||
for (MountPoint& mount : m_mount_points)
|
||||
if (*mount.target->root_inode() == *inode)
|
||||
return &mount;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wstack-usage="
|
||||
BAN::ErrorOr<VirtualFileSystem::File> VirtualFileSystem::file_from_relative_path(BAN::RefPtr<Inode> root_inode, const File& parent, const Credentials& credentials, BAN::StringView path, int flags)
|
||||
{
|
||||
LockGuard _(m_mutex);
|
||||
|
||||
auto inode = parent.inode;
|
||||
ASSERT(inode);
|
||||
|
||||
BAN::String canonical_path;
|
||||
TRY(canonical_path.append(parent.canonical_path));
|
||||
if (!canonical_path.empty() && canonical_path.back() == '/')
|
||||
canonical_path.pop_back();
|
||||
ASSERT(canonical_path.empty() || canonical_path.back() != '/');
|
||||
char canonical_buf[PATH_MAX];
|
||||
size_t canonical_len = parent.canonical_path.size();
|
||||
if (!parent.canonical_path.empty() && parent.canonical_path.back() == '/')
|
||||
canonical_len--;
|
||||
memcpy(canonical_buf, parent.canonical_path.data(), canonical_len);
|
||||
ASSERT(canonical_len == 0 || canonical_buf[canonical_len - 1] != '/');
|
||||
|
||||
BAN::Vector<BAN::String> path_parts;
|
||||
|
||||
const auto append_string_view_in_reverse =
|
||||
[&path_parts](BAN::StringView path) -> BAN::ErrorOr<void>
|
||||
{
|
||||
auto split_path = TRY(path.split('/'));
|
||||
TRY(path_parts.reserve(path_parts.size() + split_path.size()));
|
||||
for (size_t i = split_path.size(); i > 0; i--)
|
||||
{
|
||||
TRY(path_parts.emplace_back());
|
||||
TRY(path_parts.back().append(split_path[i - 1]));
|
||||
}
|
||||
return {};
|
||||
};
|
||||
TRY(append_string_view_in_reverse(path));
|
||||
char path_storage[PATH_MAX];
|
||||
|
||||
size_t link_depth = 0;
|
||||
|
||||
while (!path_parts.empty())
|
||||
for (;;)
|
||||
{
|
||||
BAN::String path_part = BAN::move(path_parts.back());
|
||||
path_parts.pop_back();
|
||||
const auto path_part = [&path] {
|
||||
size_t off = 0;
|
||||
while (off < path.size() && path[off] == '/')
|
||||
off++;
|
||||
|
||||
if (path_part.empty() || path_part == "."_sv)
|
||||
size_t len = 0;
|
||||
while (off + len < path.size() && path[off + len] != '/')
|
||||
len++;
|
||||
|
||||
const auto result = path.substring(off, len);
|
||||
path = path.substring(off + len);
|
||||
return result;
|
||||
}();
|
||||
|
||||
if (path_part.empty())
|
||||
break;
|
||||
if (path_part == "."_sv)
|
||||
continue;
|
||||
|
||||
auto orig = inode;
|
||||
auto orig_inode = inode;
|
||||
|
||||
// resolve file name
|
||||
{
|
||||
@@ -289,26 +288,26 @@ namespace Kernel
|
||||
|
||||
if (path_part == ".."_sv)
|
||||
{
|
||||
if (!canonical_path.empty())
|
||||
{
|
||||
ASSERT(canonical_path.front() == '/');
|
||||
while (canonical_path.back() != '/')
|
||||
canonical_path.pop_back();
|
||||
canonical_path.pop_back();
|
||||
}
|
||||
while (canonical_len && canonical_buf[canonical_len - 1] != '/')
|
||||
canonical_len--;
|
||||
if (canonical_len)
|
||||
canonical_len--;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (auto* mount_point = mount_from_host_inode(inode))
|
||||
inode = mount_point->target->root_inode();
|
||||
TRY(canonical_path.push_back('/'));
|
||||
TRY(canonical_path.append(path_part));
|
||||
if (canonical_len + 1 + path_part.size() > sizeof(canonical_buf))
|
||||
return BAN::Error::from_errno(ENAMETOOLONG);
|
||||
canonical_buf[canonical_len++] = '/';
|
||||
memcpy(canonical_buf + canonical_len, path_part.data(), path_part.size());
|
||||
canonical_len += path_part.size();
|
||||
}
|
||||
}
|
||||
|
||||
if (!inode->mode().iflnk())
|
||||
continue;
|
||||
if ((flags & O_NOFOLLOW) && path_parts.empty())
|
||||
if ((flags & O_NOFOLLOW) && !path.find([](char ch) { return ch != '/'; }).has_value())
|
||||
continue;
|
||||
|
||||
// resolve symbolic links
|
||||
@@ -320,21 +319,26 @@ namespace Kernel
|
||||
if (link_target.front() == '/')
|
||||
{
|
||||
inode = root_inode;
|
||||
canonical_path.clear();
|
||||
canonical_len = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
inode = orig;
|
||||
inode = orig_inode;
|
||||
|
||||
while (canonical_path.back() != '/')
|
||||
canonical_path.pop_back();
|
||||
canonical_path.pop_back();
|
||||
while (canonical_len && canonical_buf[canonical_len - 1] != '/')
|
||||
canonical_len--;
|
||||
if (canonical_len)
|
||||
canonical_len--;
|
||||
}
|
||||
|
||||
TRY(append_string_view_in_reverse(link_target.sv()));
|
||||
if (link_target.size() + path.size() > sizeof(path_storage))
|
||||
return BAN::Error::from_errno(ENAMETOOLONG);
|
||||
memcpy(path_storage, link_target.data(), link_target.size());
|
||||
memcpy(path_storage + link_target.size(), path.data(), path.size());
|
||||
path = BAN::StringView(path_storage, link_target.size() + path.size());
|
||||
|
||||
link_depth++;
|
||||
if (link_depth > 100)
|
||||
if (link_depth > SYMLOOP_MAX)
|
||||
return BAN::Error::from_errno(ELOOP);
|
||||
}
|
||||
}
|
||||
@@ -342,17 +346,14 @@ namespace Kernel
|
||||
if (!inode->can_access(credentials, flags))
|
||||
return BAN::Error::from_errno(EACCES);
|
||||
|
||||
if (canonical_path.empty())
|
||||
TRY(canonical_path.push_back('/'));
|
||||
if (canonical_len == 0)
|
||||
canonical_buf[canonical_len++] = '/';
|
||||
|
||||
File file;
|
||||
file.inode = inode;
|
||||
file.canonical_path = BAN::move(canonical_path);
|
||||
BAN::String canonical_path;
|
||||
TRY(canonical_path.append(BAN::StringView(canonical_buf, canonical_len)));
|
||||
|
||||
if (file.canonical_path.empty())
|
||||
TRY(file.canonical_path.push_back('/'));
|
||||
|
||||
return file;
|
||||
return File(BAN::move(inode), BAN::move(canonical_path));
|
||||
}
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
}
|
||||
|
||||
@@ -256,6 +256,18 @@ namespace Kernel
|
||||
|
||||
break;
|
||||
}
|
||||
case ISR::GeneralProtectionFault:
|
||||
{
|
||||
const uint8_t* ip = reinterpret_cast<const uint8_t*>(interrupt_stack->ip);
|
||||
for (const auto& safe_user : s_safe_user_page_faults)
|
||||
{
|
||||
if (ip < safe_user.ip_start || ip >= safe_user.ip_end)
|
||||
continue;
|
||||
interrupt_stack->ip = reinterpret_cast<vaddr_t>(safe_user.ip_fault);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ISR::DeviceNotAvailable:
|
||||
{
|
||||
if (pid == 0 || !Thread::current().is_userspace())
|
||||
|
||||
@@ -197,9 +197,6 @@ namespace Kernel
|
||||
}
|
||||
else switch (key_event.keycode)
|
||||
{
|
||||
case LibInput::keycode_function(1):
|
||||
Processor::toggle_should_print_cpu_load();
|
||||
break;
|
||||
case LibInput::keycode_function(11):
|
||||
DevFileSystem::get().initiate_disk_cache_drop();
|
||||
break;
|
||||
|
||||
@@ -93,7 +93,7 @@ namespace Kernel
|
||||
|
||||
void SharedFileData::sync_no_lock(size_t page_index)
|
||||
{
|
||||
if (pages[page_index] == 0 || BAN::atomic_load(writers[page_index]) == 0)
|
||||
if (pages[page_index] == 0 || BAN::atomic_load(writers[page_index]) > 0)
|
||||
return;
|
||||
|
||||
uint8_t page_buffer[PAGE_SIZE];
|
||||
@@ -108,8 +108,9 @@ namespace Kernel
|
||||
|
||||
BAN::ErrorOr<void> FileBackedRegion::msync(vaddr_t address, size_t size, int flags)
|
||||
{
|
||||
if (flags != MS_SYNC)
|
||||
dprintln("async file backed mmap msync");
|
||||
// TODO: maybe do something with the flags :)
|
||||
(void)flags;
|
||||
|
||||
if (m_type != Type::SHARED)
|
||||
return {};
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
#include <kernel/FS/DevFS/FileSystem.h>
|
||||
#include <kernel/Networking/NetworkInterface.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <net/if.h>
|
||||
#include <sys/sysmacros.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -25,7 +27,7 @@ namespace Kernel
|
||||
}
|
||||
|
||||
NetworkInterface::NetworkInterface(Type type)
|
||||
: CharacterDevice(0400, 0, 0)
|
||||
: CharacterDevice(0664, 0, 0)
|
||||
, m_type(type)
|
||||
{
|
||||
m_rdev = get_rdev(type);
|
||||
@@ -43,4 +45,95 @@ namespace Kernel
|
||||
}
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> NetworkInterface::ioctl_impl(int request, void* arg)
|
||||
{
|
||||
if (arg == nullptr)
|
||||
{
|
||||
dprintln("No argument provided");
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
}
|
||||
|
||||
auto* ifreq = reinterpret_cast<struct ifreq*>(arg);
|
||||
|
||||
switch (request)
|
||||
{
|
||||
case SIOCGIFADDR:
|
||||
{
|
||||
auto& ifru_addr = *reinterpret_cast<sockaddr_in*>(&ifreq->ifr_ifru.ifru_addr);
|
||||
ifru_addr.sin_family = AF_INET;
|
||||
ifru_addr.sin_addr.s_addr = get_ipv4_address().raw;
|
||||
return 0;
|
||||
}
|
||||
case SIOCSIFADDR:
|
||||
{
|
||||
auto& ifru_addr = *reinterpret_cast<const sockaddr_in*>(&ifreq->ifr_ifru.ifru_addr);
|
||||
if (ifru_addr.sin_family != AF_INET)
|
||||
return BAN::Error::from_errno(EADDRNOTAVAIL);
|
||||
set_ipv4_address(BAN::IPv4Address { ifru_addr.sin_addr.s_addr });
|
||||
dprintln("IPv4 address set to {}", get_ipv4_address());
|
||||
return 0;
|
||||
}
|
||||
case SIOCGIFNETMASK:
|
||||
{
|
||||
auto& ifru_netmask = *reinterpret_cast<sockaddr_in*>(&ifreq->ifr_ifru.ifru_netmask);
|
||||
ifru_netmask.sin_family = AF_INET;
|
||||
ifru_netmask.sin_addr.s_addr = get_netmask().raw;
|
||||
return 0;
|
||||
}
|
||||
case SIOCSIFNETMASK:
|
||||
{
|
||||
auto& ifru_netmask = *reinterpret_cast<const sockaddr_in*>(&ifreq->ifr_ifru.ifru_netmask);
|
||||
if (ifru_netmask.sin_family != AF_INET)
|
||||
return BAN::Error::from_errno(EADDRNOTAVAIL);
|
||||
set_netmask(BAN::IPv4Address { ifru_netmask.sin_addr.s_addr });
|
||||
dprintln("Netmask set to {}", get_netmask());
|
||||
return 0;
|
||||
}
|
||||
case SIOCGIFGWADDR:
|
||||
{
|
||||
auto& ifru_gwaddr = *reinterpret_cast<sockaddr_in*>(&ifreq->ifr_ifru.ifru_gwaddr);
|
||||
ifru_gwaddr.sin_family = AF_INET;
|
||||
ifru_gwaddr.sin_addr.s_addr = get_gateway().raw;
|
||||
return 0;
|
||||
}
|
||||
case SIOCSIFGWADDR:
|
||||
{
|
||||
auto& ifru_gwaddr = *reinterpret_cast<const sockaddr_in*>(&ifreq->ifr_ifru.ifru_gwaddr);
|
||||
if (ifru_gwaddr.sin_family != AF_INET)
|
||||
return BAN::Error::from_errno(EADDRNOTAVAIL);
|
||||
set_gateway(BAN::IPv4Address { ifru_gwaddr.sin_addr.s_addr });
|
||||
dprintln("Gateway set to {}", get_gateway());
|
||||
return 0;
|
||||
}
|
||||
case SIOCGIFHWADDR:
|
||||
{
|
||||
auto mac_address = get_mac_address();
|
||||
ifreq->ifr_ifru.ifru_hwaddr.sa_family = AF_INET;
|
||||
memcpy(ifreq->ifr_ifru.ifru_hwaddr.sa_data, &mac_address, sizeof(mac_address));
|
||||
return 0;
|
||||
}
|
||||
case SIOCGIFNAME:
|
||||
{
|
||||
auto& ifrn_name = ifreq->ifr_ifrn.ifrn_name;
|
||||
ASSERT(name().size() < sizeof(ifrn_name));
|
||||
memcpy(ifrn_name, name().data(), name().size());
|
||||
ifrn_name[name().size()] = '\0';
|
||||
return 0;
|
||||
}
|
||||
case SIOCGIFFLAGS:
|
||||
{
|
||||
int flags = 0;
|
||||
if (link_up())
|
||||
flags |= IFF_UP | IFF_RUNNING;
|
||||
if (m_type == Type::Loopback)
|
||||
flags |= IFF_LOOPBACK;
|
||||
ifreq->ifr_ifru.ifru_flags = flags;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return CharacterDevice::ioctl_impl(request, arg);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -110,83 +110,20 @@ namespace Kernel
|
||||
|
||||
BAN::ErrorOr<long> NetworkSocket::ioctl_impl(int request, void* arg)
|
||||
{
|
||||
if (!arg)
|
||||
{
|
||||
dprintln("No argument provided");
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
}
|
||||
|
||||
auto interface = TRY(this->interface(nullptr, 0));
|
||||
auto* ifreq = reinterpret_cast<struct ifreq*>(arg);
|
||||
|
||||
switch (request)
|
||||
{
|
||||
case SIOCGIFADDR:
|
||||
{
|
||||
auto& ifru_addr = *reinterpret_cast<sockaddr_in*>(&ifreq->ifr_ifru.ifru_addr);
|
||||
ifru_addr.sin_family = AF_INET;
|
||||
ifru_addr.sin_addr.s_addr = interface->get_ipv4_address().raw;
|
||||
return 0;
|
||||
}
|
||||
case SIOCSIFADDR:
|
||||
{
|
||||
auto& ifru_addr = *reinterpret_cast<const sockaddr_in*>(&ifreq->ifr_ifru.ifru_addr);
|
||||
if (ifru_addr.sin_family != AF_INET)
|
||||
return BAN::Error::from_errno(EADDRNOTAVAIL);
|
||||
interface->set_ipv4_address(BAN::IPv4Address { ifru_addr.sin_addr.s_addr });
|
||||
dprintln("IPv4 address set to {}", interface->get_ipv4_address());
|
||||
return 0;
|
||||
}
|
||||
case SIOCGIFNETMASK:
|
||||
{
|
||||
auto& ifru_netmask = *reinterpret_cast<sockaddr_in*>(&ifreq->ifr_ifru.ifru_netmask);
|
||||
ifru_netmask.sin_family = AF_INET;
|
||||
ifru_netmask.sin_addr.s_addr = interface->get_netmask().raw;
|
||||
return 0;
|
||||
}
|
||||
case SIOCSIFNETMASK:
|
||||
{
|
||||
auto& ifru_netmask = *reinterpret_cast<const sockaddr_in*>(&ifreq->ifr_ifru.ifru_netmask);
|
||||
if (ifru_netmask.sin_family != AF_INET)
|
||||
return BAN::Error::from_errno(EADDRNOTAVAIL);
|
||||
interface->set_netmask(BAN::IPv4Address { ifru_netmask.sin_addr.s_addr });
|
||||
dprintln("Netmask set to {}", interface->get_netmask());
|
||||
return 0;
|
||||
}
|
||||
case SIOCGIFGWADDR:
|
||||
{
|
||||
auto& ifru_gwaddr = *reinterpret_cast<sockaddr_in*>(&ifreq->ifr_ifru.ifru_gwaddr);
|
||||
ifru_gwaddr.sin_family = AF_INET;
|
||||
ifru_gwaddr.sin_addr.s_addr = interface->get_gateway().raw;
|
||||
return 0;
|
||||
}
|
||||
case SIOCSIFGWADDR:
|
||||
{
|
||||
auto& ifru_gwaddr = *reinterpret_cast<const sockaddr_in*>(&ifreq->ifr_ifru.ifru_gwaddr);
|
||||
if (ifru_gwaddr.sin_family != AF_INET)
|
||||
return BAN::Error::from_errno(EADDRNOTAVAIL);
|
||||
interface->set_gateway(BAN::IPv4Address { ifru_gwaddr.sin_addr.s_addr });
|
||||
dprintln("Gateway set to {}", interface->get_gateway());
|
||||
return 0;
|
||||
}
|
||||
case SIOCGIFHWADDR:
|
||||
{
|
||||
auto mac_address = interface->get_mac_address();
|
||||
ifreq->ifr_ifru.ifru_hwaddr.sa_family = AF_INET;
|
||||
memcpy(ifreq->ifr_ifru.ifru_hwaddr.sa_data, &mac_address, sizeof(mac_address));
|
||||
return 0;
|
||||
}
|
||||
case SIOCGIFNAME:
|
||||
{
|
||||
auto& ifrn_name = ifreq->ifr_ifrn.ifrn_name;
|
||||
ASSERT(interface->name().size() < sizeof(ifrn_name));
|
||||
memcpy(ifrn_name, interface->name().data(), interface->name().size());
|
||||
ifrn_name[interface->name().size()] = '\0';
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
return TRY(interface(nullptr, 0))->ioctl(request, arg);
|
||||
}
|
||||
|
||||
return Socket::ioctl_impl(request, arg);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> NetworkSocket::getsockname_impl(sockaddr* address, socklen_t* address_len)
|
||||
|
||||
@@ -853,6 +853,15 @@ namespace Kernel
|
||||
return inode->sendmsg(message, flags | (is_nonblock ? MSG_DONTWAIT : 0));
|
||||
}
|
||||
|
||||
int OpenFileDescriptorSet::get_max_open_fd() const
|
||||
{
|
||||
LockGuard _(m_mutex);
|
||||
for (int fd = m_open_files.size() - 1; fd > 0; fd--)
|
||||
if (m_open_files[fd])
|
||||
return fd;
|
||||
return -1;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<VirtualFileSystem::File> OpenFileDescriptorSet::file_of(int fd) const
|
||||
{
|
||||
LockGuard _(m_mutex);
|
||||
|
||||
@@ -1862,25 +1862,22 @@ namespace Kernel
|
||||
sys_pselect_t arguments;
|
||||
TRY(read_from_user(user_arguments, &arguments, sizeof(sys_pselect_t)));
|
||||
|
||||
MemoryRegion* readfd_region = nullptr;
|
||||
MemoryRegion* writefd_region = nullptr;
|
||||
MemoryRegion* errorfd_region = nullptr;
|
||||
const int max_nfds = BAN::Math::min(m_open_file_descriptors.get_max_open_fd(), FD_SETSIZE) + 1;
|
||||
if (arguments.nfds > max_nfds)
|
||||
arguments.nfds = max_nfds;
|
||||
|
||||
BAN::ScopeGuard _([&] {
|
||||
if (readfd_region)
|
||||
readfd_region->unpin();
|
||||
if (writefd_region)
|
||||
writefd_region->unpin();
|
||||
if (errorfd_region)
|
||||
errorfd_region->unpin();
|
||||
});
|
||||
const auto init_fd_set = [](fd_set* user, fd_set* target) -> BAN::ErrorOr<void> {
|
||||
if (user == nullptr)
|
||||
FD_ZERO(target);
|
||||
else
|
||||
TRY(read_from_user(user, target, sizeof(fd_set)));
|
||||
return {};
|
||||
};
|
||||
|
||||
if (arguments.readfds)
|
||||
readfd_region = TRY(validate_and_pin_pointer_access(arguments.readfds, sizeof(fd_set), true));
|
||||
if (arguments.writefds)
|
||||
writefd_region = TRY(validate_and_pin_pointer_access(arguments.writefds, sizeof(fd_set), true));
|
||||
if (arguments.errorfds)
|
||||
errorfd_region = TRY(validate_and_pin_pointer_access(arguments.errorfds, sizeof(fd_set), true));
|
||||
fd_set rfds, wfds, efds;
|
||||
TRY(init_fd_set(arguments.readfds, &rfds));
|
||||
TRY(init_fd_set(arguments.writefds, &wfds));
|
||||
TRY(init_fd_set(arguments.errorfds, &efds));
|
||||
|
||||
const auto old_sigmask = Thread::current().m_signal_block_mask;
|
||||
if (arguments.sigmask)
|
||||
@@ -1902,36 +1899,39 @@ namespace Kernel
|
||||
timeout.tv_nsec;
|
||||
}
|
||||
|
||||
fd_set ret_rfds, ret_wfds, ret_efds;
|
||||
FD_ZERO(&ret_rfds);
|
||||
FD_ZERO(&ret_wfds);
|
||||
FD_ZERO(&ret_efds);
|
||||
|
||||
{
|
||||
fd_set rfds, wfds, efds;
|
||||
FD_ZERO(&rfds);
|
||||
FD_ZERO(&wfds);
|
||||
FD_ZERO(&efds);
|
||||
|
||||
size_t return_value = 0;
|
||||
for (int fd = 0; fd < arguments.nfds; fd++)
|
||||
{
|
||||
auto inode_or_error = m_open_file_descriptors.inode_of(fd);
|
||||
if (inode_or_error.is_error())
|
||||
const bool wantr = FD_ISSET(fd, &rfds);
|
||||
const bool wantw = FD_ISSET(fd, &wfds);
|
||||
const bool wante = FD_ISSET(fd, &efds);
|
||||
if (!wantr && !wantw && !wante)
|
||||
continue;
|
||||
|
||||
auto inode = inode_or_error.release_value();
|
||||
if (arguments.readfds && FD_ISSET(fd, arguments.readfds) && inode->can_read())
|
||||
{ FD_SET(fd, &rfds); return_value++; }
|
||||
if (arguments.writefds && FD_ISSET(fd, arguments.writefds) && inode->can_write())
|
||||
{ FD_SET(fd, &wfds); return_value++; }
|
||||
if (arguments.errorfds && FD_ISSET(fd, arguments.errorfds) && inode->has_error())
|
||||
{ FD_SET(fd, &efds); return_value++; }
|
||||
auto inode = TRY(m_open_file_descriptors.inode_of(fd));
|
||||
if (wantr && inode->can_read())
|
||||
{ FD_SET(fd, &ret_rfds); return_value++; }
|
||||
if (wantw && inode->can_write())
|
||||
{ FD_SET(fd, &ret_wfds); return_value++; }
|
||||
if (wante && inode->has_error())
|
||||
{ FD_SET(fd, &ret_efds); return_value++; }
|
||||
}
|
||||
|
||||
if (return_value || SystemTimer::get().ns_since_boot() >= waketime_ns)
|
||||
{
|
||||
if (arguments.readfds)
|
||||
memcpy(arguments.readfds, &rfds, sizeof(fd_set));
|
||||
TRY(write_to_user(arguments.readfds, &ret_rfds, sizeof(fd_set)));
|
||||
if (arguments.writefds)
|
||||
memcpy(arguments.writefds, &wfds, sizeof(fd_set));
|
||||
TRY(write_to_user(arguments.writefds, &ret_wfds, sizeof(fd_set)));
|
||||
if (arguments.errorfds)
|
||||
memcpy(arguments.errorfds, &efds, sizeof(fd_set));
|
||||
TRY(write_to_user(arguments.errorfds, &ret_efds, sizeof(fd_set)));
|
||||
return return_value;
|
||||
}
|
||||
}
|
||||
@@ -1940,20 +1940,17 @@ namespace Kernel
|
||||
for (int fd = 0; fd < arguments.nfds; fd++)
|
||||
{
|
||||
uint32_t events = 0;
|
||||
if (arguments.readfds && FD_ISSET(fd, arguments.readfds))
|
||||
if (FD_ISSET(fd, &rfds))
|
||||
events |= EPOLLIN;
|
||||
if (arguments.writefds && FD_ISSET(fd, arguments.writefds))
|
||||
if (FD_ISSET(fd, &wfds))
|
||||
events |= EPOLLOUT;
|
||||
if (arguments.errorfds && FD_ISSET(fd, arguments.errorfds))
|
||||
if (FD_ISSET(fd, &efds))
|
||||
events |= EPOLLERR;
|
||||
if (events == 0)
|
||||
continue;
|
||||
|
||||
auto inode_or_error = m_open_file_descriptors.inode_of(fd);
|
||||
if (inode_or_error.is_error())
|
||||
continue;
|
||||
|
||||
TRY(epoll->ctl(EPOLL_CTL_ADD, fd, inode_or_error.release_value(), { .events = events, .data = { .fd = fd }}));
|
||||
auto inode = TRY(m_open_file_descriptors.inode_of(fd));
|
||||
TRY(epoll->ctl(EPOLL_CTL_ADD, fd, inode, { .events = events, .data = { .fd = fd }}));
|
||||
}
|
||||
|
||||
BAN::Vector<epoll_event> event_buffer;
|
||||
@@ -1961,25 +1958,24 @@ namespace Kernel
|
||||
|
||||
const size_t waited_events = TRY(epoll->wait(event_buffer.span(), waketime_ns));
|
||||
|
||||
if (arguments.readfds)
|
||||
FD_ZERO(arguments.readfds);
|
||||
if (arguments.writefds)
|
||||
FD_ZERO(arguments.writefds);
|
||||
if (arguments.errorfds)
|
||||
FD_ZERO(arguments.errorfds);
|
||||
|
||||
size_t return_value = 0;
|
||||
for (size_t i = 0; i < waited_events; i++)
|
||||
{
|
||||
const int fd = event_buffer[i].data.fd;
|
||||
if (arguments.readfds && event_buffer[i].events & (EPOLLIN | EPOLLHUP))
|
||||
{ FD_SET(fd, arguments.readfds); return_value++; }
|
||||
if (arguments.writefds && event_buffer[i].events & (EPOLLOUT))
|
||||
{ FD_SET(fd, arguments.writefds); return_value++; }
|
||||
if (arguments.errorfds && event_buffer[i].events & (EPOLLERR))
|
||||
{ FD_SET(fd, arguments.errorfds); return_value++; }
|
||||
if (FD_ISSET(fd, &rfds) && event_buffer[i].events & (EPOLLIN | EPOLLHUP))
|
||||
{ FD_SET(fd, &ret_rfds); return_value++; }
|
||||
if (FD_ISSET(fd, &wfds) && event_buffer[i].events & (EPOLLOUT))
|
||||
{ FD_SET(fd, &ret_wfds); return_value++; }
|
||||
if (FD_ISSET(fd, &efds) && event_buffer[i].events & (EPOLLERR))
|
||||
{ FD_SET(fd, &ret_efds); return_value++; }
|
||||
}
|
||||
|
||||
if (arguments.readfds)
|
||||
TRY(write_to_user(arguments.readfds, &ret_rfds, sizeof(fd_set)));
|
||||
if (arguments.writefds)
|
||||
TRY(write_to_user(arguments.writefds, &ret_wfds, sizeof(fd_set)));
|
||||
if (arguments.errorfds)
|
||||
TRY(write_to_user(arguments.errorfds, &ret_efds, sizeof(fd_set)));
|
||||
return return_value;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@ namespace Kernel
|
||||
ProcessorID Processor::s_bsp_id { PROCESSOR_NONE };
|
||||
BAN::Atomic<uint8_t> Processor::s_processor_count { 0 };
|
||||
BAN::Atomic<bool> Processor::s_is_smp_enabled { false };
|
||||
BAN::Atomic<bool> Processor::s_should_print_cpu_load { false };
|
||||
paddr_t Processor::s_shared_page_paddr { 0 };
|
||||
vaddr_t Processor::s_shared_page_vaddr { 0 };
|
||||
|
||||
@@ -598,6 +597,26 @@ namespace Kernel
|
||||
set_interrupt_state(state);
|
||||
}
|
||||
|
||||
Processor::LoadStats Processor::get_load_stats(size_t index)
|
||||
{
|
||||
ASSERT(index < Processor::count());
|
||||
|
||||
auto& processor = s_processors[s_processor_ids[index].as_u32()];
|
||||
|
||||
bool expected = false;
|
||||
while (!processor.m_load_stat_lock.compare_exchange(expected, true))
|
||||
{
|
||||
Processor::pause();
|
||||
expected = false;
|
||||
}
|
||||
|
||||
const auto load_stats = processor.m_load_stats;
|
||||
|
||||
processor.m_load_stat_lock.store(false);
|
||||
|
||||
return load_stats;
|
||||
}
|
||||
|
||||
void Processor::yield()
|
||||
{
|
||||
auto state = get_interrupt_state();
|
||||
@@ -605,47 +624,32 @@ namespace Kernel
|
||||
|
||||
ASSERT(!Thread::current().has_spinlock());
|
||||
|
||||
auto& processor_info = s_processors[current_id().as_u32()];
|
||||
auto& processor = s_processors[current_id().as_u32()];
|
||||
|
||||
{
|
||||
constexpr uint64_t load_update_interval_ns = 1'000'000'000;
|
||||
bool expected = false;
|
||||
while (!processor.m_load_stat_lock.compare_exchange(expected, true))
|
||||
{
|
||||
Processor::pause();
|
||||
expected = false;
|
||||
}
|
||||
|
||||
const uint64_t current_ns = SystemTimer::get().ns_since_boot();
|
||||
const uint64_t elapsed_ns = SystemTimer::get().ns_since_boot() - processor.m_load_start_ns;
|
||||
|
||||
auto& load_stats = processor.m_load_stats;
|
||||
if (scheduler().is_idle())
|
||||
processor_info.m_idle_ns += current_ns - processor_info.m_start_ns;
|
||||
load_stats.ns_idle += elapsed_ns;
|
||||
load_stats.ns_total += elapsed_ns;
|
||||
|
||||
if (current_ns >= processor_info.m_next_update_ns)
|
||||
{
|
||||
if (s_should_print_cpu_load && g_terminal_driver)
|
||||
{
|
||||
const uint64_t duration_ns = current_ns - processor_info.m_last_update_ns;
|
||||
const uint64_t load_x1000 = 100'000 * (duration_ns - BAN::Math::min(processor_info.m_idle_ns, duration_ns)) / duration_ns;
|
||||
|
||||
uint32_t x = g_terminal_driver->width() - 16;
|
||||
uint32_t y = current_id().as_u32();
|
||||
const auto proc_putc =
|
||||
[&x, y](char ch)
|
||||
{
|
||||
if (x < g_terminal_driver->width() && y < g_terminal_driver->height())
|
||||
g_terminal_driver->putchar_at(ch, x++, y, TerminalColor::WHITE, TerminalColor::BLACK);
|
||||
};
|
||||
|
||||
BAN::Formatter::print(proc_putc, "CPU { 2}: { 3}.{3}%", current_id(), load_x1000 / 1000, load_x1000 % 1000);
|
||||
}
|
||||
|
||||
processor_info.m_idle_ns = 0;
|
||||
processor_info.m_last_update_ns = current_ns;
|
||||
processor_info.m_next_update_ns += load_update_interval_ns;
|
||||
}
|
||||
processor.m_load_stat_lock.store(false);
|
||||
}
|
||||
|
||||
if (!scheduler().is_idle())
|
||||
Thread::current().set_cpu_time_stop();
|
||||
|
||||
asm_yield_trampoline(processor_info.stack_top_vaddr());
|
||||
asm_yield_trampoline(processor.stack_top_vaddr());
|
||||
|
||||
processor_info.m_start_ns = SystemTimer::get().ns_since_boot();
|
||||
processor.m_load_start_ns = SystemTimer::get().ns_since_boot();
|
||||
|
||||
if (!scheduler().is_idle())
|
||||
Thread::current().set_cpu_time_start();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <BAN/ScopeGuard.h>
|
||||
#include <kernel/BootInfo.h>
|
||||
#include <kernel/Lock/LockGuard.h>
|
||||
#include <kernel/Memory/Heap.h>
|
||||
#include <kernel/Memory/PageTable.h>
|
||||
#include <kernel/Storage/DiskCache.h>
|
||||
|
||||
@@ -10,10 +10,14 @@
|
||||
#include <kernel/Thread.h>
|
||||
#include <kernel/Timer/Timer.h>
|
||||
#include <kernel/UserCopy.h>
|
||||
#include <sys/syscall.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
static_assert(SYS_SIGPROCMASK == 79, "this is hard coded in arch/*/Signal.S");
|
||||
static_assert(SIG_SETMASK == 3, "this is hard coded in arch/*/Signal.S");
|
||||
|
||||
#if ARCH(x86_64)
|
||||
static constexpr vaddr_t s_user_stack_addr_start = 0x0000700000000000;
|
||||
#elif ARCH(i686)
|
||||
@@ -582,9 +586,15 @@ namespace Kernel
|
||||
const uint64_t full_pending_mask = m_signal_pending_mask | process().signal_pending_mask();
|
||||
const uint64_t signals = full_pending_mask & ~m_signal_block_mask;
|
||||
for (size_t sig = _SIGMIN; sig <= _SIGMAX; sig++)
|
||||
if (signals & (static_cast<uint64_t>(1) << sig))
|
||||
if (is_terminating_signal(sig) || is_abnormal_terminating_signal(sig))
|
||||
{
|
||||
if (!(signals & (static_cast<uint64_t>(1) << sig)))
|
||||
continue;
|
||||
if (!is_terminating_signal(sig) && !is_abnormal_terminating_signal(sig))
|
||||
continue;
|
||||
SpinLockGuard _(m_process->m_signal_lock);
|
||||
if (m_process->m_signal_handlers[sig].sa_handler == SIG_DFL)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -211,6 +211,8 @@ static void init2(void*)
|
||||
|
||||
SystemTimer::get().initialize_tsc();
|
||||
|
||||
ProcFileSystem::get().post_scheduler_initialize();
|
||||
|
||||
auto console = MUST(DevFileSystem::get().root_inode()->find_inode(cmdline.console));
|
||||
ASSERT(console->is_tty());
|
||||
static_cast<Kernel::TTY*>(console.ptr())->set_as_current();
|
||||
|
||||
@@ -20,5 +20,5 @@ build() {
|
||||
}
|
||||
|
||||
install() {
|
||||
cmake --install build || exit 1
|
||||
DESTDIR="$DESTDIR" cmake --install build || exit 1
|
||||
}
|
||||
|
||||
@@ -19,5 +19,5 @@ build() {
|
||||
}
|
||||
|
||||
install() {
|
||||
cmake --install build || exit 1
|
||||
DESTDIR="$DESTDIR" cmake --install build || exit 1
|
||||
}
|
||||
|
||||
@@ -23,5 +23,5 @@ build() {
|
||||
}
|
||||
|
||||
install() {
|
||||
cmake --install build || exit 1
|
||||
DESTDIR="$DESTDIR" cmake --install build || exit 1
|
||||
}
|
||||
|
||||
@@ -19,5 +19,5 @@ build() {
|
||||
}
|
||||
|
||||
install() {
|
||||
cp -v bin/gcc/$specseek_arch/specseek_$specseek_arch "$BANAN_SYSROOT/usr/bin/specseek" || exit 1
|
||||
cp -v bin/gcc/$specseek_arch/specseek_$specseek_arch "$DESTDIR/usr/bin/specseek" || exit 1
|
||||
}
|
||||
|
||||
@@ -24,5 +24,5 @@ build() {
|
||||
}
|
||||
|
||||
install() {
|
||||
cmake --install build || exit 1
|
||||
DESTDIR="$DESTDIR" cmake --install build || exit 1
|
||||
}
|
||||
|
||||
@@ -24,5 +24,5 @@ build() {
|
||||
}
|
||||
|
||||
install() {
|
||||
cmake --install build || exit 1
|
||||
DESTDIR="$DESTDIR" cmake --install build || exit 1
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ CONFIGURE_OPTIONS=(
|
||||
)
|
||||
|
||||
post_install() {
|
||||
if [ ! -L $BANAN_SYSROOT/usr/bin/sh ]; then
|
||||
ln -s bash $BANAN_SYSROOT/usr/bin/sh
|
||||
if [ ! -L $DESTDIR/usr/bin/sh ]; then
|
||||
ln -s bash $DESTDIR/usr/bin/sh
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -13,14 +13,16 @@ build() {
|
||||
}
|
||||
|
||||
install() {
|
||||
cp -v libbz2.so.$VERSION $BANAN_SYSROOT/usr/lib/ || exit 1
|
||||
ln -svf libbz2.so.$VERSION $BANAN_SYSROOT/usr/lib/libbz2.so || exit 1
|
||||
ln -svf libbz2.so.$VERSION $BANAN_SYSROOT/usr/lib/libbz2.so.1 || exit 1
|
||||
ln -svf libbz2.so.$VERSION $BANAN_SYSROOT/usr/lib/libbz2.so.1.0 || exit 1
|
||||
mkdir -p "$DESTDIR/usr/lib"
|
||||
cp -v libbz2.so.$VERSION "$DESTDIR/usr/lib/" || exit 1
|
||||
ln -svf libbz2.so.$VERSION "$DESTDIR/usr/lib/libbz2.so" || exit 1
|
||||
ln -svf libbz2.so.$VERSION "$DESTDIR/usr/lib/libbz2.so.1" || exit 1
|
||||
ln -svf libbz2.so.$VERSION "$DESTDIR/usr/lib/libbz2.so.1.0" || exit 1
|
||||
|
||||
cp -v bzlib.h $BANAN_SYSROOT/usr/include/ || exit 1
|
||||
mkdir -p "$DESTDIR/usr/include"
|
||||
cp -v bzlib.h "$DESTDIR/usr/include/" || exit 1
|
||||
|
||||
cat > $BANAN_SYSROOT/usr/lib/pkgconfig/bzip2.pc << EOF
|
||||
cat > $DESTDIR/usr/lib/pkgconfig/bzip2.pc << EOF
|
||||
prefix=/usr
|
||||
exec_prefix=\${prefix}
|
||||
bindir=\${exec_prefix}/bin
|
||||
|
||||
@@ -13,10 +13,10 @@ build() {
|
||||
}
|
||||
|
||||
install() {
|
||||
rm -rf "$BANAN_SYSROOT/etc/cacert/extracted"
|
||||
mkdir -p "$BANAN_SYSROOT/etc/cacert/extracted"
|
||||
rm -rf "$DESTDIR/etc/cacert/extracted"
|
||||
mkdir -p "$DESTDIR/etc/cacert/extracted"
|
||||
|
||||
cp -vf "../cacert-${VERSION//./-}.pem" "$BANAN_SYSROOT/etc/cacert/cacert.pem"
|
||||
cp -vf "../cacert-${VERSION//./-}.pem" "$DESTDIR/etc/cacert/cacert.pem"
|
||||
awk '/-----BEGIN CERTIFICATE-----/ {c=1;n++} c {print > sprintf("cert%03d.pem", n)} /-----END CERTIFICATE-----/ {c=0}' "../cacert-${VERSION//./-}.pem"
|
||||
mv cert*.pem "$BANAN_SYSROOT/etc/cacert/extracted/"
|
||||
mv cert*.pem "$DESTDIR/etc/cacert/extracted/"
|
||||
}
|
||||
|
||||
@@ -22,5 +22,5 @@ build() {
|
||||
}
|
||||
|
||||
install() {
|
||||
meson install --destdir="$BANAN_SYSROOT" -C build || exit 1
|
||||
meson install --destdir="$DESTDIR" -C build || exit 1
|
||||
}
|
||||
|
||||
@@ -21,6 +21,6 @@ build() {
|
||||
}
|
||||
|
||||
install() {
|
||||
cmake --install build || exit 1
|
||||
cp $BANAN_TOOLCHAIN_DIR/cmake-platform/* $BANAN_SYSROOT/usr/share/cmake-3.26/Modules/Platform/
|
||||
DESTDIR="$DESTDIR" cmake --install build || exit 1
|
||||
cp $BANAN_TOOLCHAIN_DIR/cmake-platform/* $DESTDIR/usr/share/cmake-3.26/Modules/Platform/
|
||||
}
|
||||
|
||||
@@ -25,5 +25,5 @@ build() {
|
||||
}
|
||||
|
||||
install() {
|
||||
meson install --destdir="$BANAN_SYSROOT" -C build || exit 1
|
||||
meson install --destdir="$DESTDIR" -C build || exit 1
|
||||
}
|
||||
|
||||
@@ -18,6 +18,9 @@ build() {
|
||||
}
|
||||
|
||||
install() {
|
||||
cp doomgeneric/doomgeneric "${BANAN_SYSROOT}/bin/doom" || exit 1
|
||||
cp ../doom1.wad "$BANAN_SYSROOT/home/user/" || exit 1
|
||||
mkdir -p "$DESTDIR/usr/bin"
|
||||
cp -vf doomgeneric/doomgeneric "$DESTDIR/usr/bin/doom"
|
||||
|
||||
mkdir -p "$DESTDIR/home/user"
|
||||
cp -vf ../doom1.wad "$DESTDIR/home/user/"
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
NAME='ffmpeg'
|
||||
VERSION='8.0.1'
|
||||
DOWNLOAD_URL="https://ffmpeg.org/releases/ffmpeg-$VERSION.tar.xz#05ee0b03119b45c0bdb4df654b96802e909e0a752f72e4fe3794f487229e5a41"
|
||||
DEPENDENCIES=('SDL2')
|
||||
DEPENDENCIES=('SDL2' 'openssl')
|
||||
CONFIGURE_OPTIONS=(
|
||||
'--prefix=/usr'
|
||||
'--target-os=none'
|
||||
@@ -13,6 +13,8 @@ CONFIGURE_OPTIONS=(
|
||||
'--enable-cross-compile'
|
||||
'--enable-shared'
|
||||
'--enable-gpl'
|
||||
'--enable-version3'
|
||||
'--enable-openssl'
|
||||
)
|
||||
|
||||
configure() {
|
||||
|
||||
@@ -23,7 +23,7 @@ build() {
|
||||
}
|
||||
|
||||
install() {
|
||||
meson install --destdir="$BANAN_SYSROOT" -C build || exit 1
|
||||
meson install --destdir="$DESTDIR" -C build || exit 1
|
||||
}
|
||||
|
||||
post_install() {
|
||||
@@ -39,9 +39,9 @@ post_install() {
|
||||
tar xf "$font_name.tar.bz2" || exit 1
|
||||
fi
|
||||
|
||||
mkdir -p "$BANAN_SYSROOT/usr/share/fonts/TTF" || exit 1
|
||||
cp "$font_name/ttf/"* "$BANAN_SYSROOT/usr/share/fonts/TTF/" || exit 1
|
||||
cp "$font_name/fontconfig/"* "$BANAN_SYSROOT/usr/share/fontconfig/conf.avail/" || exit 1
|
||||
mkdir -p "$DESTDIR/usr/share/fonts/TTF" || exit 1
|
||||
cp "$font_name/ttf/"* "$DESTDIR/usr/share/fonts/TTF/" || exit 1
|
||||
cp "$font_name/fontconfig/"* "$DESTDIR/usr/share/fontconfig/conf.avail/" || exit 1
|
||||
|
||||
popd &>/dev/null
|
||||
}
|
||||
|
||||
@@ -23,5 +23,5 @@ build() {
|
||||
}
|
||||
|
||||
install() {
|
||||
meson install --destdir="$BANAN_SYSROOT" -C build || exit 1
|
||||
meson install --destdir="$DESTDIR" -C build || exit 1
|
||||
}
|
||||
|
||||
@@ -22,5 +22,5 @@ build() {
|
||||
}
|
||||
|
||||
install() {
|
||||
meson install --destdir="$BANAN_SYSROOT" -C build || exit 1
|
||||
meson install --destdir="$DESTDIR" -C build || exit 1
|
||||
}
|
||||
|
||||
@@ -18,5 +18,5 @@ build() {
|
||||
}
|
||||
|
||||
install() {
|
||||
cmake --install build || exit 1
|
||||
DESTDIR="$DESTDIR" cmake --install build || exit 1
|
||||
}
|
||||
|
||||
@@ -17,5 +17,5 @@ build() {
|
||||
}
|
||||
|
||||
install() {
|
||||
meson install --destdir="$BANAN_SYSROOT" -C build || exit 1
|
||||
meson install --destdir="$DESTDIR" -C build || exit 1
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
NAME='gtk'
|
||||
VERSION='3.24.49'
|
||||
DOWNLOAD_URL="https://gitlab.gnome.org/GNOME/gtk/-/archive/$VERSION/gtk-$VERSION.tar.gz#a2958d82986c81794e953a3762335fa7c78948706d23cced421f7245ca544cbc"
|
||||
DEPENDENCIES=('glib' 'gdk-pixbuf' 'pango' 'libatk' 'libepoxy' 'libXrandr')
|
||||
DEPENDENCIES=('glib' 'gdk-pixbuf' 'pango' 'libatk' 'libepoxy' 'libXrandr' 'libXcursor' 'libXinerama')
|
||||
CONFIGURE_OPTIONS=(
|
||||
'-Dprefix=/usr'
|
||||
'-Dtests=false'
|
||||
@@ -26,5 +26,5 @@ build() {
|
||||
}
|
||||
|
||||
install() {
|
||||
meson install --destdir="$BANAN_SYSROOT" -C build || exit 1
|
||||
meson install --destdir="$DESTDIR" -C build || exit 1
|
||||
}
|
||||
|
||||
@@ -14,5 +14,5 @@ build() {
|
||||
}
|
||||
|
||||
install() {
|
||||
./waf install --destdir=$BANAN_SYSROOT/home/user/halflife || exit 1
|
||||
./waf install --destdir="$DESTDIR/home/user/halflife" || exit 1
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
NAME='harfbuzz'
|
||||
VERSION='12.2.0'
|
||||
DOWNLOAD_URL="https://github.com/harfbuzz/harfbuzz/releases/download/$VERSION/harfbuzz-$VERSION.tar.xz#ecb603aa426a8b24665718667bda64a84c1504db7454ee4cadbd362eea64e545"
|
||||
DEPENDENCIES=('glib' 'freetype')
|
||||
DEPENDENCIES=('glib' 'freetype' 'icu')
|
||||
CONFIGURE_OPTIONS=(
|
||||
'-Dprefix=/usr'
|
||||
'-Dtests=disabled'
|
||||
@@ -23,7 +23,7 @@ build() {
|
||||
}
|
||||
|
||||
install() {
|
||||
meson install --destdir="$BANAN_SYSROOT" -C build || exit 1
|
||||
meson install --destdir="$DESTDIR" -C build || exit 1
|
||||
}
|
||||
|
||||
post_install() {
|
||||
|
||||
@@ -4,7 +4,6 @@ NAME='icu'
|
||||
VERSION='78.1'
|
||||
DOWNLOAD_URL="https://github.com/unicode-org/icu/releases/download/release-$VERSION/icu4c-$VERSION-sources.tgz#6217f58ca39b23127605cfc6c7e0d3475fe4b0d63157011383d716cb41617886"
|
||||
TAR_CONTENT='icu'
|
||||
_DEPENDENCIES=('ca-certificates' 'openssl' 'zlib' 'zstd')
|
||||
CONFIG_SUB=('source/config.sub')
|
||||
CONFIGURE_OPTIONS=(
|
||||
"--with-cross-build=$BANAN_PORT_DIR/icu/icu-$VERSION-$BANAN_ARCH/source/build-host"
|
||||
|
||||
@@ -43,8 +43,10 @@ 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|PKG_CONFIG|$BANAN_PORT_DIR/pkg-config|" "$MESON_CROSS_FILE"
|
||||
sed -i "s|CMAKE_BINARY|$BANAN_CMAKE|" "$MESON_CROSS_FILE"
|
||||
sed -i "s|CMAKE_TOOLCHAIN|$BANAN_TOOLCHAIN_DIR/Toolchain.txt|" "$MESON_CROSS_FILE"
|
||||
fi
|
||||
|
||||
MAKE_BUILD_TARGETS=('all')
|
||||
@@ -250,6 +252,7 @@ if (( $needs_compile )); then
|
||||
sha256sum "$BANAN_SYSROOT/usr/lib/libc.a" > "../.compile_hash"
|
||||
fi
|
||||
|
||||
DESTDIR="$BANAN_SYSROOT"
|
||||
pre_install
|
||||
install
|
||||
grep -qsxF "$NAME-$VERSION" "$installed_file" || echo "$NAME-$VERSION" >> "$installed_file"
|
||||
|
||||
@@ -19,5 +19,5 @@ build() {
|
||||
}
|
||||
|
||||
install() {
|
||||
cmake --install build || exit 1
|
||||
DESTDIR="$DESTDIR" cmake --install build || exit 1
|
||||
}
|
||||
|
||||
@@ -22,5 +22,5 @@ build() {
|
||||
}
|
||||
|
||||
install() {
|
||||
meson install --destdir="$BANAN_SYSROOT" -C build || exit 1
|
||||
meson install --destdir="$DESTDIR" -C build || exit 1
|
||||
}
|
||||
|
||||
@@ -23,5 +23,5 @@ build() {
|
||||
}
|
||||
|
||||
install() {
|
||||
meson install --destdir="$BANAN_SYSROOT" -C build || exit 1
|
||||
meson install --destdir="$DESTDIR" -C build || exit 1
|
||||
}
|
||||
|
||||
@@ -4,3 +4,6 @@ NAME='libffi'
|
||||
VERSION='3.5.2'
|
||||
DOWNLOAD_URL="https://github.com/libffi/libffi/releases/download/v$VERSION/libffi-$VERSION.tar.gz#f3a3082a23b37c293a4fcd1053147b371f2ff91fa7ea1b2a52e335676bac82dc"
|
||||
CONFIG_SUB=('config.sub')
|
||||
CONFIGURE_OPTIONS=(
|
||||
'--disable-static'
|
||||
)
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
NAME='libsndfile'
|
||||
VERSION='1.2.2'
|
||||
DOWNLOAD_URL="https://github.com/libsndfile/libsndfile/releases/download/$VERSION/libsndfile-$VERSION.tar.xz#3799ca9924d3125038880367bf1468e53a1b7e3686a934f098b7e1d286cdb80e"
|
||||
_DEPENDENCIES=('ca-certificates' 'openssl' 'zlib' 'zstd')
|
||||
CONFIG_SUB=('build-aux/config.sub')
|
||||
CONFIGURE_OPTIONS=(
|
||||
'CFLAGS=-std=c11'
|
||||
|
||||
@@ -18,5 +18,5 @@ build() {
|
||||
}
|
||||
|
||||
install() {
|
||||
cmake --install build || exit 1
|
||||
DESTDIR="$DESTDIR" cmake --install build || exit 1
|
||||
}
|
||||
|
||||
@@ -23,5 +23,5 @@ build() {
|
||||
}
|
||||
|
||||
install() {
|
||||
meson install --destdir="$BANAN_SYSROOT" -C build || exit 1
|
||||
meson install --destdir="$DESTDIR" -C build || exit 1
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
NAME='links'
|
||||
VERSION='2.30'
|
||||
DOWNLOAD_URL="http://links.twibright.com/download/links-$VERSION.tar.gz#7f0d54f4f7d1f094c25c9cbd657f98bc998311122563b1d757c9aeb1d3423b9e"
|
||||
DEPENDENCIES=('ca-certificates' 'openssl' 'zlib' 'zstd' 'libpng' 'libjpeg' 'libtiff' 'libwebp')
|
||||
DEPENDENCIES=('openssl' 'zlib' 'zstd' 'libpng' 'libjpeg' 'libtiff' 'libwebp')
|
||||
|
||||
post_configure() {
|
||||
config_defines=(
|
||||
@@ -50,5 +50,6 @@ build() {
|
||||
}
|
||||
|
||||
install() {
|
||||
cp -v links "$BANAN_SYSROOT/usr/bin/" || exit 1
|
||||
mkdir -p "$DESTDIR/usr/bin"
|
||||
cp -v links "$DESTDIR/usr/bin/" || exit 1
|
||||
}
|
||||
|
||||
@@ -13,5 +13,5 @@ build() {
|
||||
}
|
||||
|
||||
install() {
|
||||
make install PLAT=posix INSTALL_TOP="$BANAN_SYSROOT/usr" || exit 1
|
||||
make install PLAT=posix INSTALL_TOP="$DESTDIR/usr" || exit 1
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ NAME='lynx'
|
||||
VERSION='2.9.2'
|
||||
DOWNLOAD_URL="https://invisible-island.net/archives/lynx/tarballs/lynx$VERSION.tar.gz#99f8f28f860094c533100d1cedf058c27fb242ce25e991e2d5f30ece4457a3bf"
|
||||
TAR_CONTENT="lynx$VERSION"
|
||||
DEPENDENCIES=('ncurses' 'ca-certificates' 'openssl' 'zlib')
|
||||
DEPENDENCIES=('ncurses' 'openssl' 'zlib')
|
||||
CONFIG_SUB=('config.sub')
|
||||
CONFIGURE_OPTIONS=(
|
||||
'--without-system-type'
|
||||
|
||||
@@ -74,8 +74,9 @@ build() {
|
||||
}
|
||||
|
||||
install() {
|
||||
meson install --destdir="$BANAN_SYSROOT" -C build || exit 1
|
||||
meson install --destdir="$DESTDIR" -C build || exit 1
|
||||
|
||||
ln -sf osmesa.pc $BANAN_SYSROOT/usr/lib/pkgconfig/opengl.pc
|
||||
ln -sf libOSMesa.so $BANAN_SYSROOT/usr/lib/libGL.so
|
||||
mkdir -p "$DESTDIR/usr/lib/pkgconfig"
|
||||
ln -sf osmesa.pc $DESTDIR/usr/lib/pkgconfig/opengl.pc
|
||||
ln -sf libOSMesa.so $DESTDIR/usr/lib/libGL.so
|
||||
}
|
||||
|
||||
@@ -9,5 +9,6 @@ configure() {
|
||||
}
|
||||
|
||||
install() {
|
||||
cp src/nyancat "$BANAN_SYSROOT/usr/bin/"
|
||||
mkdir -p "$DESTDIR/usr/bin"
|
||||
cp src/nyancat "$DESTDIR/usr/bin/"
|
||||
}
|
||||
|
||||
@@ -21,5 +21,5 @@ build() {
|
||||
}
|
||||
|
||||
install() {
|
||||
cmake --install build || exit 1
|
||||
DESTDIR="$DESTDIR" cmake --install build || exit 1
|
||||
}
|
||||
|
||||
@@ -11,16 +11,16 @@ configure() {
|
||||
}
|
||||
|
||||
post_install() {
|
||||
rm -f "$BANAN_SYSROOT/etc/ssl/certs"/*
|
||||
rm -f "$DESTDIR/etc/ssl/certs"/*
|
||||
|
||||
ln -svf "../cacert/cacert.pem" "$BANAN_SYSROOT/etc/ssl/cert.pem"
|
||||
ln -svf "../../cacert/cacert.pem" "$BANAN_SYSROOT/etc/ssl/certs/ca-certificates.crt"
|
||||
ln -svf "../../cacert/cacert.pem" "$BANAN_SYSROOT/etc/ssl/certs/ca-bundle.crt"
|
||||
ln -svf "../cacert/cacert.pem" "$DESTDIR/etc/ssl/cert.pem"
|
||||
ln -svf "../../cacert/cacert.pem" "$DESTDIR/etc/ssl/certs/ca-certificates.crt"
|
||||
ln -svf "../../cacert/cacert.pem" "$DESTDIR/etc/ssl/certs/ca-bundle.crt"
|
||||
|
||||
openssl rehash "$BANAN_SYSROOT/etc/cacert/extracted"
|
||||
find "$BANAN_SYSROOT/etc/cacert/extracted" -type l -print0 |
|
||||
while IFS= read -r -d '' link; do
|
||||
ln -s "../../cacert/extracted/$(readlink "$link")" "$BANAN_SYSROOT/etc/ssl/certs/${link##*/}"
|
||||
ln -s "../../cacert/extracted/$(readlink "$link")" "$DESTDIR/etc/ssl/certs/${link##*/}"
|
||||
rm "$link"
|
||||
done
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
NAME='pango'
|
||||
VERSION='1.57.0'
|
||||
DOWNLOAD_URL="https://gitlab.gnome.org/GNOME/pango/-/archive/$VERSION/pango-$VERSION.tar.gz#1b2e2f683dfb5adec3faf17087ade8c648f10a5d3d0e17e421e0ac1a39e6740e"
|
||||
DEPENDENCIES=('glib' 'fontconfig' 'cairo' 'fribidi')
|
||||
DEPENDENCIES=('glib' 'fontconfig' 'cairo' 'fribidi' 'libXft')
|
||||
CONFIGURE_OPTIONS=(
|
||||
'-Dprefix=/usr'
|
||||
'-Dbuild-testsuite=false'
|
||||
@@ -22,5 +22,5 @@ build() {
|
||||
}
|
||||
|
||||
install() {
|
||||
meson install --destdir="$BANAN_SYSROOT" -C build || exit 1
|
||||
meson install --destdir="$DESTDIR" -C build || exit 1
|
||||
}
|
||||
|
||||
@@ -4,3 +4,6 @@ NAME='pcre2'
|
||||
VERSION='10.45'
|
||||
DOWNLOAD_URL="https://github.com/PCRE2Project/pcre2/releases/download/pcre2-$VERSION/pcre2-$VERSION.tar.gz#0e138387df7835d7403b8351e2226c1377da804e0737db0e071b48f07c9d12ee"
|
||||
CONFIG_SUB=('config.sub')
|
||||
CONFIGURE_OPTIONS=(
|
||||
'--disable-static'
|
||||
)
|
||||
|
||||
@@ -20,5 +20,5 @@ build() {
|
||||
}
|
||||
|
||||
install() {
|
||||
cmake --install build || exit 1
|
||||
DESTDIR="$DESTDIR" cmake --install build || exit 1
|
||||
}
|
||||
|
||||
@@ -21,5 +21,5 @@ build() {
|
||||
}
|
||||
|
||||
install() {
|
||||
meson install --destdir="$BANAN_SYSROOT" -C build || exit 1
|
||||
meson install --destdir="$DESTDIR" -C build || exit 1
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ CONFIGURE_OPTIONS=(
|
||||
'--target-list=x86_64-softmmu'
|
||||
'--disable-tpm'
|
||||
'--disable-docs'
|
||||
'--enable-slirp'
|
||||
)
|
||||
|
||||
pre_configure() {
|
||||
|
||||
@@ -31,9 +31,9 @@ build() {
|
||||
}
|
||||
|
||||
install() {
|
||||
cp -v build/quake2-soft "${BANAN_SYSROOT}/bin/quake2" || exit 1
|
||||
mkdir -p "$DESTDIR/usr/bin"
|
||||
cp -vf build/quake2-soft "$DESTDIR/usr/bin/quake2" || exit 1
|
||||
|
||||
baseq2_tar=$(realpath ../baseq2.tar.gz || exit 1)
|
||||
cd "$BANAN_SYSROOT/home/user/"
|
||||
tar xf $baseq2_tar
|
||||
mkdir -p "$DESTDIR/home/user"
|
||||
tar xf ../baseq2.tar.gz -C "$DESTDIR/home/user/"
|
||||
}
|
||||
|
||||
@@ -20,5 +20,5 @@ build() {
|
||||
}
|
||||
|
||||
install() {
|
||||
cmake --install build || exit 1
|
||||
DESTDIR="$DESTDIR" cmake --install build || exit 1
|
||||
}
|
||||
|
||||
@@ -24,5 +24,5 @@ build() {
|
||||
}
|
||||
|
||||
install() {
|
||||
meson install --destdir="$BANAN_SYSROOT" -C build || exit 1
|
||||
meson install --destdir="$DESTDIR" -C build || exit 1
|
||||
}
|
||||
|
||||
@@ -26,5 +26,5 @@ configure() {
|
||||
}
|
||||
|
||||
post_install() {
|
||||
ln -sf $tcc_arch-tcc $BANAN_SYSROOT/usr/bin/tcc
|
||||
ln -sf $tcc_arch-tcc $DESTDIR/usr/bin/tcc
|
||||
}
|
||||
|
||||
@@ -18,5 +18,5 @@ build() {
|
||||
}
|
||||
|
||||
install() {
|
||||
make -C unix install "DESTDIR=$BANAN_SYSROOT" || exit 1
|
||||
make -C unix install "DESTDIR=$DESTDIR" || exit 1
|
||||
}
|
||||
|
||||
@@ -19,9 +19,10 @@ post_install() {
|
||||
fi
|
||||
|
||||
eawpats_dir="/usr/share/eawpats"
|
||||
mkdir -p "$BANAN_SYSROOT/$eawpats_dir"
|
||||
unzip -qod "$BANAN_SYSROOT/$eawpats_dir" ../eawpats.zip
|
||||
mkdir -p "$DESTDIR/$eawpats_dir"
|
||||
unzip -qod "$DESTDIR/$eawpats_dir" ../eawpats.zip
|
||||
|
||||
cp "$BANAN_SYSROOT/$eawpats_dir/timidity.cfg" "$BANAN_SYSROOT/etc/"
|
||||
sed -i "s|^dir .*$|dir $eawpats_dir|g" "$BANAN_SYSROOT/etc/timidity.cfg"
|
||||
mkdir -p "$DESTDIR/etc"
|
||||
cp "$DESTDIR/$eawpats_dir/timidity.cfg" "$DESTDIR/etc/"
|
||||
sed -i "s|^dir .*$|dir $eawpats_dir|g" "$DESTDIR/etc/timidity.cfg"
|
||||
}
|
||||
|
||||
@@ -15,5 +15,5 @@ build() {
|
||||
}
|
||||
|
||||
install() {
|
||||
cp -v tinygb "$BANAN_SYSROOT"/usr/bin || exit 1
|
||||
cp -v tinygb "$DESTDIR/usr/bin/" || exit 1
|
||||
}
|
||||
|
||||
@@ -31,9 +31,9 @@ post_install() {
|
||||
tar xf "tuxracer-data-$VERSION.tar.gz" || exit 1
|
||||
fi
|
||||
|
||||
mkdir -p "$BANAN_SYSROOT/usr/share/tuxracer" || exit 1
|
||||
cp -r "tuxracer-data-$VERSION"/* "$BANAN_SYSROOT/usr/share/tuxracer/" || exit 1
|
||||
find "$BANAN_SYSROOT/usr/share/tuxracer" -type f -exec chmod 644 {} +
|
||||
mkdir -p "$DESTDIR/usr/share/tuxracer" || exit 1
|
||||
cp -r "tuxracer-data-$VERSION"/* "$DESTDIR/usr/share/tuxracer/" || exit 1
|
||||
find "$DESTDIR/usr/share/tuxracer" -type f -exec chmod 644 {} +
|
||||
|
||||
popd
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
NAME='xash3d-fwgs'
|
||||
VERSION='git'
|
||||
DOWNLOAD_URL="https://github.com/FWGS/xash3d-fwgs.git#da1b9ad80d76156a5cbd54d3ce87edb32634ea87"
|
||||
DEPENDENCIES=('SDL2' 'freetype')
|
||||
DEPENDENCIES=('SDL2' 'freetype' 'bzip2' 'libvorbis')
|
||||
|
||||
configure() {
|
||||
git submodule update --init --recursive || exit 1
|
||||
@@ -22,13 +22,12 @@ build() {
|
||||
}
|
||||
|
||||
install() {
|
||||
./waf install --destdir=$BANAN_SYSROOT/home/user/halflife || exit 1
|
||||
patchelf --add-needed libxash.so $BANAN_SYSROOT/home/user/halflife/xash3d
|
||||
./waf install --destdir="$DESTDIR/usr/share/games/halflife" || exit 1
|
||||
|
||||
cat > $BANAN_SYSROOT/home/user/halflife/start.sh << EOF
|
||||
cat > "$DESTDIR/home/user/halflife/start.sh" << EOF
|
||||
#!/bin/Shell
|
||||
export LD_LIBRARY_PATH=/home/user/halflife
|
||||
./xash3d -console
|
||||
EOF
|
||||
chmod +x $BANAN_SYSROOT/home/user/halflife/start.sh
|
||||
chmod +x $DESTDIR/home/user/halflife/start.sh
|
||||
}
|
||||
|
||||
@@ -18,10 +18,11 @@ build() {
|
||||
}
|
||||
|
||||
install() {
|
||||
cp -v build/xbanan/xbanan "$BANAN_SYSROOT/usr/bin" || exit 1
|
||||
mkdir -p "$DESTDIR/usr/bin"
|
||||
cp -v build/xbanan/xbanan "$DESTDIR/usr/bin/" || exit 1
|
||||
|
||||
mkdir -p "$BANAN_SYSROOT/usr/share/fonts/X11"
|
||||
cp -r fonts/misc "$BANAN_SYSROOT/usr/share/fonts/X11/" || exit 1
|
||||
mkdir -p "$DESTDIR/usr/share/fonts/X11"
|
||||
cp -r fonts/misc "$DESTDIR/usr/share/fonts/X11/" || exit 1
|
||||
}
|
||||
|
||||
post_install() {
|
||||
|
||||
@@ -21,5 +21,5 @@ build() {
|
||||
}
|
||||
|
||||
install() {
|
||||
meson install --destdir="$BANAN_SYSROOT" -C build || exit 1
|
||||
meson install --destdir="$DESTDIR" -C build || exit 1
|
||||
}
|
||||
|
||||
@@ -20,5 +20,5 @@ build() {
|
||||
}
|
||||
|
||||
install() {
|
||||
cmake --install build ||exit 1
|
||||
DESTDIR="$DESTDIR" cmake --install build ||exit 1
|
||||
}
|
||||
|
||||
@@ -17,5 +17,5 @@ build() {
|
||||
}
|
||||
|
||||
install() {
|
||||
cmake --install build || exit 1
|
||||
DESTDIR="$DESTDIR" cmake --install build || exit 1
|
||||
}
|
||||
|
||||
@@ -16,5 +16,5 @@ build() {
|
||||
}
|
||||
|
||||
install() {
|
||||
cmake --install _build ||exit 1
|
||||
DESTDIR="$DESTDIR" cmake --install _build ||exit 1
|
||||
}
|
||||
|
||||
@@ -16,13 +16,11 @@ set(TOOLCHAIN_PREFIX $ENV{BANAN_TOOLCHAIN_PREFIX})
|
||||
set(CMAKE_SYSTEM_NAME banan-os)
|
||||
set(CMAKE_SYSTEM_PROCESSOR ${BANAN_ARCH})
|
||||
|
||||
set(CMAKE_SYSROOT ${BANAN_SYSROOT})
|
||||
set(CMAKE_STAGING_PREFIX ${BANAN_SYSROOT}/usr)
|
||||
|
||||
set(CMAKE_FIND_ROOT_PATH ${BANAN_SYSROOT})
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE BOTH)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||
|
||||
@@ -130,7 +130,8 @@ build_gcc () {
|
||||
--enable-shared \
|
||||
--enable-lto \
|
||||
--disable-nls \
|
||||
--enable-languages=c,c++
|
||||
--enable-languages=c,c++ \
|
||||
CXXFLAGS='-fno-char8_t'
|
||||
|
||||
XCFLAGS=""
|
||||
if [ $BANAN_ARCH = "x86_64" ]; then
|
||||
|
||||
@@ -11,11 +11,12 @@ 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'
|
||||
pkg-config = 'PKG_CONFIG'
|
||||
cmake = 'CMAKE_BINARY'
|
||||
|
||||
glib-compile-schemas = '/usr/bin/glib-compile-schemas'
|
||||
glib-compile-resources = '/usr/bin/glib-compile-resources'
|
||||
|
||||
[properties]
|
||||
sys_root='SYSROOT'
|
||||
cmake_toolchain_file='CMAKE_TOOLCHAIN'
|
||||
|
||||
@@ -127,6 +127,8 @@ int vsnprintf(char* __restrict s, size_t n, const char* __restrict format, va_l
|
||||
int vsprintf(char* __restrict s, const char* __restrict format, va_list ap);
|
||||
int vsscanf(const char* __restrict s, const char* __restrict format, va_list arg);
|
||||
|
||||
void __fseterr(FILE* stream);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif
|
||||
|
||||
@@ -75,8 +75,8 @@ int mblen(const char* s, size_t n);
|
||||
size_t mbstowcs(wchar_t* __restrict pwcs, const char* __restrict s, size_t n);
|
||||
int mbtowc(wchar_t* __restrict pwc, const char* __restrict s, size_t n);
|
||||
char* mkdtemp(char* _template);
|
||||
char* mktemp(char* _template);
|
||||
int mkstemp(char* _template);
|
||||
int mkostemp(char* _template, int flags);
|
||||
long mrand48(void);
|
||||
long nrand48(unsigned short xsubi[3]);
|
||||
int posix_memalign(void** memptr, size_t alignment, size_t size);
|
||||
@@ -109,6 +109,10 @@ int unsetenv(const char* name);
|
||||
size_t wcstombs(char* __restrict s, const wchar_t* __restrict pwcs, size_t n);
|
||||
int wctomb(char* s, wchar_t wchar);
|
||||
|
||||
char* mktemp(char* _template);
|
||||
int mkstemps(char* _template, int suffixlen);
|
||||
int mkostemps(char* _template, int suffixlen, int flags);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
__BEGIN_DECLS
|
||||
|
||||
#define LOCK_UN 0
|
||||
#define LOCK_EX 1
|
||||
#define LOCK_SH 2
|
||||
#define LOCK_NB 4
|
||||
#define LOCK_SH 1
|
||||
#define LOCK_EX 2
|
||||
#define LOCK_NB (1 << 2)
|
||||
|
||||
int flock(int fd, int op);
|
||||
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
#include <BAN/Atomic.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <spawn.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/banan-os.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define TODO_FUNC(name, ...) int name(__VA_ARGS__) { dwarnln("TODO: " #name); errno = ENOTSUP; return -1; }
|
||||
@@ -205,20 +201,6 @@ int posix_spawn_file_actions_addopen(posix_spawn_file_actions_t* __restrict file
|
||||
|
||||
static int do_posix_spawn(pid_t* __restrict pid, const char* __restrict path, const posix_spawn_file_actions_t* file_actions, const posix_spawnattr_t* __restrict attrp, char* const argv[], char* const envp[], bool do_path_resolution)
|
||||
{
|
||||
// MAP_SHARED | MAP_ANONYMOUS is not supported :D
|
||||
|
||||
const auto smo_key = smo_create(sizeof(int), PROT_READ | PROT_WRITE);
|
||||
if (smo_key == -1)
|
||||
return errno;
|
||||
|
||||
void* addr = smo_map(smo_key);
|
||||
smo_delete(smo_key);
|
||||
if (addr == MAP_FAILED)
|
||||
return errno;
|
||||
|
||||
auto& child_status = *static_cast<BAN::Atomic<int>*>(addr);
|
||||
child_status = INT_MAX;
|
||||
|
||||
const pid_t child_pid = fork();
|
||||
if (child_pid == 0)
|
||||
{
|
||||
@@ -227,7 +209,6 @@ static int do_posix_spawn(pid_t* __restrict pid, const char* __restrict path, co
|
||||
auto ret = __VA_ARGS__; \
|
||||
if (ret != (err)) \
|
||||
break; \
|
||||
child_status = errno; \
|
||||
exit(127); \
|
||||
} while (false)
|
||||
|
||||
@@ -249,7 +230,7 @@ static int do_posix_spawn(pid_t* __restrict pid, const char* __restrict path, co
|
||||
if (attrp->flags & POSIX_SPAWN_SETSIGDEF)
|
||||
for (int sig = _SIGMIN; sig <= _SIGMAX; sig++)
|
||||
if (attrp->sigdefault & (1ull << sig))
|
||||
DIE_ON_ERROR(NULL, signal(sig, SIG_DFL));
|
||||
DIE_ON_ERROR(SIG_ERR, signal(sig, SIG_DFL));
|
||||
|
||||
if (attrp->flags & POSIX_SPAWN_SETSIGMASK)
|
||||
DIE_ON_ERROR(-1, sigprocmask(SIG_SETMASK, &attrp->sigmask, nullptr));
|
||||
@@ -287,31 +268,13 @@ static int do_posix_spawn(pid_t* __restrict pid, const char* __restrict path, co
|
||||
|
||||
#undef DIE_ON_ERROR
|
||||
|
||||
child_status = 0;
|
||||
|
||||
auto* func = do_path_resolution ? execvpe : execve;
|
||||
func(path, argv, envp);
|
||||
exit(127);
|
||||
}
|
||||
|
||||
if (child_pid == -1)
|
||||
{
|
||||
munmap(addr, sizeof(int));
|
||||
return errno;
|
||||
}
|
||||
|
||||
while (child_status == INT_MAX)
|
||||
sched_yield();
|
||||
|
||||
const int child_status_copy = child_status;
|
||||
munmap(addr, sizeof(int));
|
||||
|
||||
if (child_status_copy != 0)
|
||||
{
|
||||
while (waitpid(child_pid, nullptr, 0) == -1 && errno == EINTR)
|
||||
continue;
|
||||
return child_status_copy;
|
||||
}
|
||||
|
||||
if (pid != nullptr)
|
||||
*pid = child_pid;
|
||||
|
||||
@@ -134,6 +134,12 @@ void clearerr(FILE* file)
|
||||
file->error = false;
|
||||
}
|
||||
|
||||
void __fseterr(FILE* file)
|
||||
{
|
||||
ScopeLock _(file);
|
||||
file->error = true;
|
||||
}
|
||||
|
||||
char* ctermid(char* buffer)
|
||||
{
|
||||
static char s_buffer[L_ctermid];
|
||||
@@ -398,7 +404,8 @@ FILE* freopen(const char* pathname, const char* mode_str, FILE* file)
|
||||
|
||||
if (pathname)
|
||||
{
|
||||
fclose(file);
|
||||
fflush(file);
|
||||
close(file->fd);
|
||||
file->fd = open(pathname, mode, 0666);
|
||||
file->mode = mode & O_ACCMODE;
|
||||
if (file->fd == -1)
|
||||
|
||||
@@ -475,31 +475,36 @@ int system(const char* command)
|
||||
return stat_val;
|
||||
}
|
||||
|
||||
static size_t temp_template_count_x(const char* _template)
|
||||
static void randomize_temp(char* buffer)
|
||||
{
|
||||
const size_t len = strlen(_template);
|
||||
for (size_t i = 0; i < len; i++)
|
||||
if (_template[len - i - 1] != 'X')
|
||||
return i;
|
||||
return len;
|
||||
// FIXME: don't use rand()
|
||||
const uint32_t value = rand() & 0xFFFFFF;
|
||||
sprintf(buffer, "%06x", value);
|
||||
}
|
||||
|
||||
static void generate_temp_template(char* _template, size_t x_count)
|
||||
static char* validate_temp_template(char* _template, int suffixlen)
|
||||
{
|
||||
const size_t len = strlen(_template);
|
||||
for (size_t i = 0; i < x_count; i++)
|
||||
const size_t length = strlen(_template);
|
||||
if (suffixlen < 0 || length < static_cast<size_t>(suffixlen + 6))
|
||||
{
|
||||
const uint8_t nibble = rand() & 0xF;
|
||||
_template[len - i - 1] = (nibble < 10)
|
||||
? ('0' + nibble)
|
||||
: ('a' + nibble - 10);
|
||||
errno = EINVAL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
char* xptr = _template + length - suffixlen - 6;
|
||||
if (memcmp(xptr, "XXXXXX", 6) != 0)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return xptr;
|
||||
}
|
||||
|
||||
char* mktemp(char* _template)
|
||||
{
|
||||
const size_t x_count = temp_template_count_x(_template);
|
||||
if (x_count < 6)
|
||||
char* xptr = validate_temp_template(_template, 0);
|
||||
if (xptr == nullptr)
|
||||
{
|
||||
errno = EINVAL;
|
||||
_template[0] = '\0';
|
||||
@@ -508,18 +513,22 @@ char* mktemp(char* _template)
|
||||
|
||||
for (;;)
|
||||
{
|
||||
generate_temp_template(_template, x_count);
|
||||
randomize_temp(xptr);
|
||||
|
||||
struct stat st;
|
||||
if (stat(_template, &st) == 0)
|
||||
if (stat(_template, &st) == -1)
|
||||
{
|
||||
if (errno != ENOENT)
|
||||
_template[0] = '\0';
|
||||
return _template;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char* mkdtemp(char* _template)
|
||||
{
|
||||
const size_t x_count = temp_template_count_x(_template);
|
||||
if (x_count < 6)
|
||||
char* xptr = validate_temp_template(_template, 0);
|
||||
if (xptr == nullptr)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return nullptr;
|
||||
@@ -527,8 +536,7 @@ char* mkdtemp(char* _template)
|
||||
|
||||
for (;;)
|
||||
{
|
||||
generate_temp_template(_template, x_count);
|
||||
|
||||
randomize_temp(xptr);
|
||||
if (mkdir(_template, S_IRUSR | S_IWUSR | S_IXUSR) != -1)
|
||||
return _template;
|
||||
if (errno != EEXIST)
|
||||
@@ -538,8 +546,26 @@ char* mkdtemp(char* _template)
|
||||
|
||||
int mkstemp(char* _template)
|
||||
{
|
||||
const size_t x_count = temp_template_count_x(_template);
|
||||
if (x_count < 6)
|
||||
return mkostemps(_template, 0, 0);
|
||||
}
|
||||
|
||||
int mkostemp(char* _template, int flags)
|
||||
{
|
||||
return mkostemps(_template, 0, flags);
|
||||
}
|
||||
|
||||
int mkstemps(char* _template, int suffixlen)
|
||||
{
|
||||
return mkostemps(_template, suffixlen, 0);
|
||||
}
|
||||
|
||||
int mkostemps(char* _template, int suffixlen, int flags)
|
||||
{
|
||||
flags &= O_APPEND | O_CLOEXEC | O_SYNC;
|
||||
flags |= O_RDWR | O_CREAT | O_EXCL;
|
||||
|
||||
char* xptr = validate_temp_template(_template, suffixlen);
|
||||
if (xptr == nullptr)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
@@ -547,10 +573,8 @@ int mkstemp(char* _template)
|
||||
|
||||
for (;;)
|
||||
{
|
||||
generate_temp_template(_template, x_count);
|
||||
|
||||
int fd = open(_template, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
|
||||
if (fd != -1)
|
||||
randomize_temp(xptr);
|
||||
if (int fd = open(_template, flags, 0600); fd != -1)
|
||||
return fd;
|
||||
if (errno != EEXIST)
|
||||
return -1;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
|
||||
@@ -40,38 +42,35 @@ int posix_madvise(void* addr, size_t len, int advice)
|
||||
(void)addr;
|
||||
(void)len;
|
||||
(void)advice;
|
||||
fprintf(stddbg, "TODO: posix_madvise");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <BAN/Assert.h>
|
||||
#include <BAN/Debug.h>
|
||||
#include <errno.h>
|
||||
|
||||
int mlock(const void*, size_t)
|
||||
int mlock(const void* addr, size_t len)
|
||||
{
|
||||
ASSERT_NOT_REACHED();
|
||||
(void)addr;
|
||||
(void)len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int munlock(const void*, size_t)
|
||||
int munlock(const void* addr, size_t len)
|
||||
{
|
||||
ASSERT_NOT_REACHED();
|
||||
(void)addr;
|
||||
(void)len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int shm_open(const char* name, int oflag, mode_t mode)
|
||||
{
|
||||
(void)name;
|
||||
(void)oflag;
|
||||
(void)mode;
|
||||
dwarnln("TODO: shm_open");
|
||||
errno = ENOTSUP;
|
||||
if (mkdir("/tmp/shm", 0777) == -1 && errno != EEXIST)
|
||||
return -1;
|
||||
char path[PATH_MAX];
|
||||
sprintf(path, "/tmp/shm%s", name);
|
||||
return open(path, oflag | O_CLOEXEC, mode);
|
||||
}
|
||||
|
||||
int shm_unlink(const char* name)
|
||||
{
|
||||
(void)name;
|
||||
dwarnln("TODO: shm_unlink");
|
||||
errno = ENOTSUP;
|
||||
return -1;
|
||||
char path[PATH_MAX];
|
||||
sprintf(path, "/tmp/shm%s", name);
|
||||
return unlink(path);
|
||||
}
|
||||
|
||||
@@ -300,10 +300,10 @@ namespace LibGUI
|
||||
return {};
|
||||
}
|
||||
|
||||
void Window::wait_events()
|
||||
void Window::wait_events(const timespec* timeout)
|
||||
{
|
||||
epoll_event dummy;
|
||||
epoll_wait(m_epoll_fd, &dummy, 1, -1);
|
||||
epoll_pwait2(m_epoll_fd, &dummy, 1, timeout, nullptr);
|
||||
}
|
||||
|
||||
void Window::poll_events()
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace LibGUI
|
||||
uint32_t width() const { return m_width; }
|
||||
uint32_t height() const { return m_height; }
|
||||
|
||||
void wait_events();
|
||||
void wait_events(const timespec* timeout = nullptr);
|
||||
void poll_events();
|
||||
|
||||
void set_socket_error_callback(BAN::Function<void()> callback) { m_socket_error_callback = callback; }
|
||||
|
||||
@@ -4,9 +4,10 @@
|
||||
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#include <inttypes.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <time.h>
|
||||
|
||||
static BAN::ErrorOr<long long> read_integer_from_file(const char* file)
|
||||
{
|
||||
@@ -63,6 +64,77 @@ static BAN::String get_battery_percentage()
|
||||
return result;
|
||||
}
|
||||
|
||||
static BAN::String get_cpu_load(bool show_long)
|
||||
{
|
||||
struct LoadStats
|
||||
{
|
||||
uint64_t idle_ns;
|
||||
uint64_t total_ns;
|
||||
};
|
||||
|
||||
static BAN::Vector<LoadStats> cpu_stats;
|
||||
|
||||
BAN::Vector<LoadStats> delta_stats;
|
||||
(void)delta_stats.reserve(show_long ? cpu_stats.size() : 1);
|
||||
|
||||
for (size_t i = 0;; i++)
|
||||
{
|
||||
char buffer[PATH_MAX];
|
||||
sprintf(buffer, "/proc/cpu/%zu", i);
|
||||
|
||||
FILE* fp = fopen(buffer, "r");
|
||||
if (fp == nullptr)
|
||||
break;
|
||||
|
||||
LoadStats stats;
|
||||
if (fscanf(fp, "%" SCNu64 " %" SCNu64, &stats.idle_ns, &stats.total_ns) == 2)
|
||||
{
|
||||
if (i >= cpu_stats.size())
|
||||
MUST(cpu_stats.resize(i + 1, {}));
|
||||
|
||||
const LoadStats delta {
|
||||
.idle_ns = stats.idle_ns - cpu_stats[i].idle_ns,
|
||||
.total_ns = stats.total_ns - cpu_stats[i].total_ns,
|
||||
};
|
||||
cpu_stats[i] = stats;
|
||||
|
||||
if (show_long)
|
||||
(void)delta_stats.push_back(delta);
|
||||
else
|
||||
{
|
||||
if (delta_stats.empty())
|
||||
(void)delta_stats.push_back(delta);
|
||||
else
|
||||
{
|
||||
delta_stats[0].idle_ns += delta.idle_ns;
|
||||
delta_stats[0].total_ns += delta.total_ns;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
BAN::String result;
|
||||
(void)result.append("CPU");
|
||||
|
||||
for (size_t i = 0; i < delta_stats.size(); i++)
|
||||
{
|
||||
const uint64_t idle_10000 = 10'000 * delta_stats[i].idle_ns / delta_stats[i].total_ns;
|
||||
const uint64_t load_10000 = 10'000 - idle_10000;
|
||||
|
||||
auto string = BAN::String::formatted(" {}.{2}%", load_10000 / 100, load_10000 % 100);
|
||||
if (string.is_error())
|
||||
continue;
|
||||
|
||||
(void)result.append(string.release_value());
|
||||
}
|
||||
|
||||
(void)result.append(" | "_sv);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int open_audio_server_fd()
|
||||
{
|
||||
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
@@ -106,10 +178,12 @@ static BAN::String get_audio_volume()
|
||||
return MUST(BAN::String::formatted("vol {}% | ", response / 10));
|
||||
}
|
||||
|
||||
static BAN::ErrorOr<BAN::String> get_task_bar_string()
|
||||
static BAN::ErrorOr<BAN::String> get_task_bar_string(bool show_long)
|
||||
{
|
||||
BAN::String result;
|
||||
|
||||
TRY(result.append(get_cpu_load(show_long)));
|
||||
|
||||
TRY(result.append(get_battery_percentage()));
|
||||
|
||||
TRY(result.append(get_audio_volume()));
|
||||
@@ -144,6 +218,12 @@ int main()
|
||||
|
||||
window->set_position(0, 0);
|
||||
|
||||
bool show_long = false;
|
||||
window->set_mouse_button_event_callback([&](auto event) {
|
||||
if (event.pressed)
|
||||
show_long = !show_long;
|
||||
});
|
||||
|
||||
window->texture().fill(bg_color);
|
||||
window->invalidate();
|
||||
|
||||
@@ -153,7 +233,7 @@ int main()
|
||||
const auto update_string =
|
||||
[&]()
|
||||
{
|
||||
auto text_or_error = get_task_bar_string();
|
||||
auto text_or_error = get_task_bar_string(show_long);
|
||||
if (text_or_error.is_error())
|
||||
return;
|
||||
const auto text = text_or_error.release_value();
|
||||
@@ -176,6 +256,8 @@ int main()
|
||||
|
||||
while (is_running)
|
||||
{
|
||||
window->poll_events();
|
||||
|
||||
update_string();
|
||||
|
||||
constexpr uint64_t ns_per_s = 1'000'000'000;
|
||||
@@ -193,10 +275,10 @@ int main()
|
||||
|
||||
uint64_t sleep_ns = target_ns - current_ns;
|
||||
|
||||
timespec sleep_ts;
|
||||
sleep_ts.tv_sec = sleep_ns / ns_per_s;
|
||||
sleep_ts.tv_nsec = sleep_ns % ns_per_s;
|
||||
timespec timeout_ts;
|
||||
timeout_ts.tv_sec = sleep_ns / ns_per_s;
|
||||
timeout_ts.tv_nsec = sleep_ns % ns_per_s;
|
||||
|
||||
nanosleep(&sleep_ts, nullptr);
|
||||
window->wait_events(&timeout_ts);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ struct DNSEntry
|
||||
|
||||
DNSEntry(DNSEntry&& other)
|
||||
{
|
||||
*this = BAN::move(other);
|
||||
initialize_no_clear(BAN::move(other));
|
||||
}
|
||||
|
||||
~DNSEntry() { clear(); }
|
||||
@@ -74,6 +74,12 @@ struct DNSEntry
|
||||
DNSEntry& operator=(DNSEntry&& other)
|
||||
{
|
||||
clear();
|
||||
initialize_no_clear(BAN::move(other));
|
||||
return *this;
|
||||
}
|
||||
|
||||
void initialize_no_clear(DNSEntry&& other)
|
||||
{
|
||||
valid_until = other.valid_until;
|
||||
switch (type = other.type)
|
||||
{
|
||||
@@ -88,7 +94,6 @@ struct DNSEntry
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
other.clear();
|
||||
return *this;
|
||||
}
|
||||
|
||||
void clear()
|
||||
@@ -448,6 +453,7 @@ int main(int, char**)
|
||||
|
||||
if (send(client.socket, &addr, sizeof(addr), 0) == -1)
|
||||
dprintln("send: {}", strerror(errno));
|
||||
dwarnln("{} -> {}", client.query.data(), inet_ntoa({ .s_addr = resolved->raw }));
|
||||
client.close = true;
|
||||
break;
|
||||
}
|
||||
@@ -460,14 +466,8 @@ int main(int, char**)
|
||||
|
||||
if (!client.query.empty())
|
||||
{
|
||||
static uint8_t buffer[4096];
|
||||
ssize_t nrecv = recv(client.socket, buffer, sizeof(buffer), 0);
|
||||
if (nrecv < 0)
|
||||
dprintln("{}", strerror(errno));
|
||||
if (nrecv <= 0)
|
||||
dprintln("unexpected data from client");
|
||||
client.close = true;
|
||||
else
|
||||
dprintln("Client already has a query");
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -480,8 +480,11 @@ int main(int, char**)
|
||||
|
||||
BAN::Optional<BAN::IPv4Address> result;
|
||||
|
||||
// TODO: add and parse /etc/hosts
|
||||
if (*hostname && strcmp(query->data(), hostname) == 0)
|
||||
result = BAN::IPv4Address(ntohl(INADDR_LOOPBACK));
|
||||
else if (strcmp(query->data(), "localhost") == 0)
|
||||
result = BAN::IPv4Address(ntohl(INADDR_LOOPBACK));
|
||||
else if (auto resolved = resolve_from_dns_cache(dns_cache, query.value()); resolved.has_value())
|
||||
result = resolved.release_value();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user