Compare commits

...

23 Commits

Author SHA1 Message Date
Bananymous f15f88ebd6 TaskBar: Don't leak fds when reading battery info 2025-08-28 15:57:10 +03:00
Bananymous 391fc0c4c2 Kernel: Don't crash if Ext2 filesystem doing too many fileops
I had a hardlimit of 10 block buffers and if they ran out, the kernel
would crash. this patchs increases the number of buffers to 16 and
removes the crash condition when they run out :D
2025-08-28 15:55:40 +03:00
Bananymous 948ef2c820 Kernel: Fix race condition when destroying threads 2025-08-28 15:55:40 +03:00
Bananymous c1b6b6b76a Kernel: Fix string validation in unlink syscall 2025-08-28 15:55:40 +03:00
Bananymous a8bb07052e Kernel: Rewrite SMP message code
Remove locks and map smp buffer as uncached
2025-08-28 15:55:40 +03:00
Bananymous 6976a2dae7 Kernel: Add hardlink support to USTAR
Also handle file types L and K for long file names and link names
2025-08-28 15:55:40 +03:00
Bananymous 51cd951b4c Kernel: Add hardlink support to tmpfs 2025-08-28 15:55:40 +03:00
Bananymous 16a5a234c1 Kernel: Cleanup hardlink creation 2025-08-28 15:55:40 +03:00
Bananymous f994210927 LibC: Fix sigsetjmp (again)
I was using a wrong register for signal mask storage...
2025-08-28 15:55:40 +03:00
Bananymous aaa8760d09 Kernel: Don't wait for ps2 timeout when flushing buffer
This speeds up boot time by a second :dd:
2025-08-28 15:55:40 +03:00
Bananymous cea19ecc31 Kernel: Fix possible crash during exec 2025-08-28 15:55:40 +03:00
Bananymous 706cfeb443 Kernel: Allow file backed mapping be larger than inode size
This is only allowed if the mapping does **not** exceed a page boundary.
Some port was doing an exactly two-page-mapping on a file that was one
and a half page long
2025-08-28 15:55:40 +03:00
Bananymous d9c91589f0 Kernel: Don't limit /tmp max size 2025-08-28 15:55:40 +03:00
Bananymous 9854691265 LibC: Don't leak fds on rename 2025-08-28 15:55:40 +03:00
Bananymous 32afa33a06 LibC: Make sure FILE's buffer does not get overflown 2025-08-28 15:55:40 +03:00
Bananymous c6946d0145 LibC: Use pthread_mutex on FILE instead of atomics 2025-08-28 15:55:40 +03:00
Bananymous abbe7b79d6 Kernel: Add /proc/<pid>/exe 2025-08-28 15:55:40 +03:00
Bananymous e4abe75043 Kernel: Add /proc/self 2025-08-28 15:55:40 +03:00
Bananymous b904503691 ports: Update GCC 15.1.0->15.2.0 2025-08-28 15:55:40 +03:00
Bananymous 2db42dfb2e BuildSystem: Don't download config.sub every hour
There isn't really any need to :D
2025-08-25 22:16:23 +03:00
Bananymous 10bd24e585 Kernel: Fix signal delivery without an alternate stack
I had only tested that sigaltstack worked, so I didn't notice my normal
signals broke :D
2025-08-25 22:16:23 +03:00
Bananymous f926e599fa Kernel: Zero initialize Processors
This moves processor array to .bss reducing data size by 8192 bytes :)

This needed GCC updated to 15.2.0 because of an internal compiler error
I found :)
2025-08-25 18:29:14 +03:00
Bananymous e7b518ba67 BuildSystem: binutils 2.44->2.45, gcc 15.1.0->15.2.0 2025-08-25 18:25:36 +03:00
28 changed files with 631 additions and 260 deletions

View File

@ -26,18 +26,40 @@ namespace Kernel
class BlockBufferWrapper class BlockBufferWrapper
{ {
BAN_NON_COPYABLE(BlockBufferWrapper); BAN_NON_COPYABLE(BlockBufferWrapper);
BAN_NON_MOVABLE(BlockBufferWrapper);
public: public:
BlockBufferWrapper(BAN::Span<uint8_t> buffer, bool& used) BlockBufferWrapper(BAN::Span<uint8_t> buffer, bool* used, Mutex* mutex, ThreadBlocker* blocker)
: m_buffer(buffer) : m_buffer(buffer)
, m_used(used) , m_used(used)
, m_mutex(mutex)
, m_blocker(blocker)
{ {
ASSERT(m_used); ASSERT(m_used && *m_used);
} }
BlockBufferWrapper(BlockBufferWrapper&& other) { *this = BAN::move(other); }
~BlockBufferWrapper() ~BlockBufferWrapper()
{ {
m_used = false; if (m_used == nullptr)
return;
m_mutex->lock();
*m_used = false;
m_blocker->unblock();
m_mutex->unlock();
}
BlockBufferWrapper& operator=(BlockBufferWrapper&& other)
{
this->m_buffer = other.m_buffer;
this->m_used = other.m_used;
this->m_mutex = other.m_mutex;
this->m_blocker = other.m_blocker;
other.m_buffer = {};
other.m_used = nullptr;
other.m_mutex = nullptr;
other.m_blocker = nullptr;
return *this;
} }
size_t size() const { return m_buffer.size(); } size_t size() const { return m_buffer.size(); }
@ -53,7 +75,9 @@ namespace Kernel
private: private:
BAN::Span<uint8_t> m_buffer; BAN::Span<uint8_t> m_buffer;
bool& m_used; bool* m_used;
Mutex* m_mutex;
ThreadBlocker* m_blocker;
}; };
public: public:
@ -79,7 +103,7 @@ namespace Kernel
BAN::ErrorOr<void> sync_superblock(); BAN::ErrorOr<void> sync_superblock();
BAN::ErrorOr<void> sync_block(uint32_t block); BAN::ErrorOr<void> sync_block(uint32_t block);
BlockBufferWrapper get_block_buffer(); BAN::ErrorOr<BlockBufferWrapper> get_block_buffer();
BAN::ErrorOr<uint32_t> reserve_free_block(uint32_t primary_bgd); BAN::ErrorOr<uint32_t> reserve_free_block(uint32_t primary_bgd);
BAN::ErrorOr<void> release_block(uint32_t block); BAN::ErrorOr<void> release_block(uint32_t block);
@ -102,7 +126,7 @@ namespace Kernel
{ {
public: public:
BlockBufferManager() = default; BlockBufferManager() = default;
BlockBufferWrapper get_buffer(); BAN::ErrorOr<BlockBufferWrapper> get_buffer();
BAN::ErrorOr<void> initialize(size_t block_size); BAN::ErrorOr<void> initialize(size_t block_size);
@ -114,7 +138,9 @@ namespace Kernel
}; };
private: private:
BAN::Array<BlockBuffer, 10> m_buffers; Mutex m_buffer_mutex;
ThreadBlocker m_buffer_blocker;
BAN::Array<BlockBuffer, 16> m_buffers;
}; };
private: private:

View File

@ -82,4 +82,30 @@ namespace Kernel
size_t (*m_callback)(off_t, BAN::ByteSpan); size_t (*m_callback)(off_t, BAN::ByteSpan);
}; };
class ProcSymlinkInode final : public TmpInode
{
public:
static BAN::ErrorOr<BAN::RefPtr<ProcSymlinkInode>> create_new(BAN::ErrorOr<BAN::String> (*)(void*), void* data, TmpFileSystem&, mode_t, uid_t, gid_t);
~ProcSymlinkInode() = default;
protected:
virtual BAN::ErrorOr<BAN::String> link_target_impl() override;
// You may not write here and this is always non blocking
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override { return BAN::Error::from_errno(EINVAL); }
virtual BAN::ErrorOr<void> truncate_impl(size_t) override { return BAN::Error::from_errno(EINVAL); }
virtual bool can_read_impl() const override { return false; }
virtual bool can_write_impl() const override { return false; }
virtual bool has_error_impl() const override { return false; }
virtual bool has_hungup_impl() const override { return false; }
private:
ProcSymlinkInode(BAN::ErrorOr<BAN::String> (*callback)(void*), void* data, TmpFileSystem&, const TmpInodeInfo&);
private:
BAN::ErrorOr<BAN::String> (*m_callback)(void*);
void* m_data;
};
} }

View File

@ -156,6 +156,7 @@ namespace Kernel
virtual BAN::ErrorOr<size_t> list_next_inodes_impl(off_t, struct dirent*, size_t) override final; virtual BAN::ErrorOr<size_t> list_next_inodes_impl(off_t, struct dirent*, size_t) override final;
virtual BAN::ErrorOr<void> create_file_impl(BAN::StringView, mode_t, uid_t, gid_t) override final; virtual BAN::ErrorOr<void> create_file_impl(BAN::StringView, mode_t, uid_t, gid_t) override final;
virtual BAN::ErrorOr<void> create_directory_impl(BAN::StringView, mode_t, uid_t, gid_t) override final; virtual BAN::ErrorOr<void> create_directory_impl(BAN::StringView, mode_t, uid_t, gid_t) override final;
virtual BAN::ErrorOr<void> link_inode_impl(BAN::StringView, BAN::RefPtr<Inode>) override final;
virtual BAN::ErrorOr<void> unlink_impl(BAN::StringView) override; virtual BAN::ErrorOr<void> unlink_impl(BAN::StringView) override;
virtual bool can_read_impl() const override { return false; } virtual bool can_read_impl() const override { return false; }

View File

@ -226,6 +226,8 @@ namespace Kernel
size_t proc_cmdline(off_t offset, BAN::ByteSpan) const; size_t proc_cmdline(off_t offset, BAN::ByteSpan) const;
size_t proc_environ(off_t offset, BAN::ByteSpan) const; size_t proc_environ(off_t offset, BAN::ByteSpan) const;
BAN::StringView executable() const { return m_executable; }
// Returns error if page could not be allocated // Returns error if page could not be allocated
// Returns true if the page was allocated successfully // Returns true if the page was allocated successfully
// Return false if access was page violation (segfault) // Return false if access was page violation (segfault)
@ -339,6 +341,7 @@ namespace Kernel
BAN::Vector<BAN::String> m_cmdline; BAN::Vector<BAN::String> m_cmdline;
BAN::Vector<BAN::String> m_environ; BAN::Vector<BAN::String> m_environ;
BAN::String m_executable;
BAN::Vector<ChildExitStatus> m_child_exit_statuses; BAN::Vector<ChildExitStatus> m_child_exit_statuses;
ThreadBlocker m_child_exit_blocker; ThreadBlocker m_child_exit_blocker;

View File

@ -120,6 +120,8 @@ namespace Kernel
static ProcessorID read_processor_id(); static ProcessorID read_processor_id();
static void initialize_smp();
template<typename T> template<typename T>
static T read_gs_sized(uintptr_t offset) requires(sizeof(T) <= 8) static T read_gs_sized(uintptr_t offset) requires(sizeof(T) <= 8)
{ {
@ -158,7 +160,7 @@ namespace Kernel
static BAN::Atomic<bool> s_is_smp_enabled; static BAN::Atomic<bool> s_is_smp_enabled;
static BAN::Atomic<bool> s_should_print_cpu_load; static BAN::Atomic<bool> s_should_print_cpu_load;
ProcessorID m_id { PROCESSOR_NONE }; ProcessorID m_id { 0 };
static constexpr size_t s_stack_size { 4096 }; static constexpr size_t s_stack_size { 4096 };
void* m_stack { nullptr }; void* m_stack { nullptr };
@ -173,12 +175,8 @@ namespace Kernel
uint64_t m_last_update_ns { 0 }; uint64_t m_last_update_ns { 0 };
uint64_t m_next_update_ns { 0 }; uint64_t m_next_update_ns { 0 };
BAN::Atomic<bool> m_smp_pending_lock { false }; BAN::Atomic<SMPMessage*> m_smp_pending { nullptr };
SMPMessage* m_smp_pending { nullptr }; BAN::Atomic<SMPMessage*> m_smp_free { nullptr };
BAN::Atomic<bool> m_smp_free_lock { false };
SMPMessage* m_smp_free { nullptr };
SMPMessage* m_smp_message_storage { nullptr }; SMPMessage* m_smp_message_storage { nullptr };
void* m_current_page_table { nullptr }; void* m_current_page_table { nullptr };

View File

@ -125,7 +125,7 @@ namespace Kernel
TRY(m_buffer_manager.initialize(block_size())); TRY(m_buffer_manager.initialize(block_size()));
{ {
auto block_buffer = m_buffer_manager.get_buffer(); auto block_buffer = TRY(m_buffer_manager.get_buffer());
if (superblock().rev_level == Ext2::Enum::GOOD_OLD_REV) if (superblock().rev_level == Ext2::Enum::GOOD_OLD_REV)
{ {
@ -170,6 +170,9 @@ namespace Kernel
BAN::ErrorOr<uint32_t> Ext2FS::create_inode(const Ext2::Inode& ext2_inode) BAN::ErrorOr<uint32_t> Ext2FS::create_inode(const Ext2::Inode& ext2_inode)
{ {
auto bgd_buffer = TRY(m_buffer_manager.get_buffer());
auto inode_bitmap = TRY(m_buffer_manager.get_buffer());
LockGuard _(m_mutex); LockGuard _(m_mutex);
ASSERT(ext2_inode.size == 0); ASSERT(ext2_inode.size == 0);
@ -179,9 +182,6 @@ namespace Kernel
const uint32_t block_size = this->block_size(); const uint32_t block_size = this->block_size();
auto bgd_buffer = m_buffer_manager.get_buffer();
auto inode_bitmap = m_buffer_manager.get_buffer();
uint32_t current_group = -1; uint32_t current_group = -1;
BlockLocation bgd_location {}; BlockLocation bgd_location {};
Ext2::BlockGroupDescriptor* bgd = nullptr; Ext2::BlockGroupDescriptor* bgd = nullptr;
@ -248,15 +248,15 @@ namespace Kernel
BAN::ErrorOr<void> Ext2FS::delete_inode(uint32_t ino) BAN::ErrorOr<void> Ext2FS::delete_inode(uint32_t ino)
{ {
auto bgd_buffer = TRY(get_block_buffer());
auto bitmap_buffer = TRY(get_block_buffer());
auto inode_buffer = TRY(get_block_buffer());
LockGuard _(m_mutex); LockGuard _(m_mutex);
ASSERT(ino >= superblock().first_ino); ASSERT(ino >= superblock().first_ino);
ASSERT(ino <= superblock().inodes_count); ASSERT(ino <= superblock().inodes_count);
auto bgd_buffer = get_block_buffer();
auto bitmap_buffer = get_block_buffer();
auto inode_buffer = get_block_buffer();
const uint32_t inode_group = (ino - 1) / superblock().inodes_per_group; const uint32_t inode_group = (ino - 1) / superblock().inodes_per_group;
const uint32_t inode_index = (ino - 1) % superblock().inodes_per_group; const uint32_t inode_index = (ino - 1) % superblock().inodes_per_group;
@ -334,6 +334,8 @@ namespace Kernel
BAN::ErrorOr<void> Ext2FS::sync_superblock() BAN::ErrorOr<void> Ext2FS::sync_superblock()
{ {
auto superblock_buffer = TRY(get_block_buffer());
LockGuard _(m_mutex); LockGuard _(m_mutex);
const uint32_t sector_size = m_block_device->blksize(); const uint32_t sector_size = m_block_device->blksize();
@ -347,8 +349,6 @@ namespace Kernel
const uint32_t lba = 1024 / sector_size; const uint32_t lba = 1024 / sector_size;
const uint32_t sector_count = BAN::Math::div_round_up<uint32_t>(superblock_bytes, sector_size); const uint32_t sector_count = BAN::Math::div_round_up<uint32_t>(superblock_bytes, sector_size);
auto superblock_buffer = get_block_buffer();
TRY(m_block_device->read_blocks(lba, sector_count, superblock_buffer.span())); TRY(m_block_device->read_blocks(lba, sector_count, superblock_buffer.span()));
if (memcmp(superblock_buffer.data(), &m_superblock, superblock_bytes)) if (memcmp(superblock_buffer.data(), &m_superblock, superblock_bytes))
{ {
@ -370,22 +370,21 @@ namespace Kernel
return m_block_device->sync_blocks(block * sectors_per_block, sectors_per_block); return m_block_device->sync_blocks(block * sectors_per_block, sectors_per_block);
} }
Ext2FS::BlockBufferWrapper Ext2FS::get_block_buffer() BAN::ErrorOr<Ext2FS::BlockBufferWrapper> Ext2FS::get_block_buffer()
{ {
LockGuard _(m_mutex);
return m_buffer_manager.get_buffer(); return m_buffer_manager.get_buffer();
} }
BAN::ErrorOr<uint32_t> Ext2FS::reserve_free_block(uint32_t primary_bgd) BAN::ErrorOr<uint32_t> Ext2FS::reserve_free_block(uint32_t primary_bgd)
{ {
auto bgd_buffer = TRY(m_buffer_manager.get_buffer());
auto block_bitmap = TRY(m_buffer_manager.get_buffer());
LockGuard _(m_mutex); LockGuard _(m_mutex);
if (m_superblock.r_blocks_count >= m_superblock.free_blocks_count) if (m_superblock.r_blocks_count >= m_superblock.free_blocks_count)
return BAN::Error::from_errno(ENOSPC); return BAN::Error::from_errno(ENOSPC);
auto bgd_buffer = m_buffer_manager.get_buffer();
auto block_bitmap = m_buffer_manager.get_buffer();
auto check_block_group = auto check_block_group =
[&](uint32_t block_group) -> BAN::ErrorOr<uint32_t> [&](uint32_t block_group) -> BAN::ErrorOr<uint32_t>
{ {
@ -439,6 +438,9 @@ namespace Kernel
BAN::ErrorOr<void> Ext2FS::release_block(uint32_t block) BAN::ErrorOr<void> Ext2FS::release_block(uint32_t block)
{ {
auto bgd_buffer = TRY(get_block_buffer());
auto bitmap_buffer = TRY(get_block_buffer());
LockGuard _(m_mutex); LockGuard _(m_mutex);
ASSERT(block >= m_superblock.first_data_block); ASSERT(block >= m_superblock.first_data_block);
@ -447,9 +449,6 @@ namespace Kernel
const uint32_t block_group = (block - m_superblock.first_data_block) / m_superblock.blocks_per_group; const uint32_t block_group = (block - m_superblock.first_data_block) / m_superblock.blocks_per_group;
const uint32_t block_offset = (block - m_superblock.first_data_block) % m_superblock.blocks_per_group; const uint32_t block_offset = (block - m_superblock.first_data_block) % m_superblock.blocks_per_group;
auto bgd_buffer = get_block_buffer();
auto bitmap_buffer = get_block_buffer();
auto bgd_location = locate_block_group_descriptior(block_group); auto bgd_location = locate_block_group_descriptior(block_group);
TRY(read_block(bgd_location.block, bgd_buffer)); TRY(read_block(bgd_location.block, bgd_buffer));
@ -480,7 +479,7 @@ namespace Kernel
const uint32_t block_size = this->block_size(); const uint32_t block_size = this->block_size();
auto bgd_buffer = m_buffer_manager.get_buffer(); auto bgd_buffer = TRY(m_buffer_manager.get_buffer());
const uint32_t inode_group = (ino - 1) / superblock().inodes_per_group; const uint32_t inode_group = (ino - 1) / superblock().inodes_per_group;
const uint32_t inode_index = (ino - 1) % superblock().inodes_per_group; const uint32_t inode_index = (ino - 1) % superblock().inodes_per_group;
@ -533,16 +532,22 @@ namespace Kernel
}; };
} }
Ext2FS::BlockBufferWrapper Ext2FS::BlockBufferManager::get_buffer() BAN::ErrorOr<Ext2FS::BlockBufferWrapper> Ext2FS::BlockBufferManager::get_buffer()
{ {
for (auto& buffer : m_buffers) LockGuard _(m_buffer_mutex);
for (;;)
{ {
if (buffer.used) for (auto& buffer : m_buffers)
continue; {
buffer.used = true; if (buffer.used)
return Ext2FS::BlockBufferWrapper(buffer.buffer.span(), buffer.used); continue;
buffer.used = true;
return Ext2FS::BlockBufferWrapper(buffer.buffer.span(), &buffer.used, &m_buffer_mutex, &m_buffer_blocker);
}
TRY(Thread::current().block_or_eintr_indefinite(m_buffer_blocker, &m_buffer_mutex));
} }
ASSERT_NOT_REACHED();
} }
BAN::ErrorOr<void> Ext2FS::BlockBufferManager::initialize(size_t block_size) BAN::ErrorOr<void> Ext2FS::BlockBufferManager::initialize(size_t block_size)

View File

@ -32,7 +32,7 @@ namespace Kernel
auto inode_location = TRY(fs.locate_inode(inode_ino)); auto inode_location = TRY(fs.locate_inode(inode_ino));
auto block_buffer = fs.get_block_buffer(); auto block_buffer = TRY(fs.get_block_buffer());
TRY(fs.read_block(inode_location.block, block_buffer)); TRY(fs.read_block(inode_location.block, block_buffer));
auto& inode = block_buffer.span().slice(inode_location.offset).as<Ext2::Inode>(); auto& inode = block_buffer.span().slice(inode_location.offset).as<Ext2::Inode>();
@ -61,7 +61,7 @@ namespace Kernel
return BAN::Optional<uint32_t>(); return BAN::Optional<uint32_t>();
ASSERT(depth >= 1); ASSERT(depth >= 1);
auto block_buffer = m_fs.get_block_buffer(); auto block_buffer = TRY(m_fs.get_block_buffer());
TRY(m_fs.read_block(block, block_buffer)); TRY(m_fs.read_block(block, block_buffer));
const uint32_t indices_per_block = blksize() / sizeof(uint32_t); const uint32_t indices_per_block = blksize() / sizeof(uint32_t);
@ -152,7 +152,7 @@ namespace Kernel
const uint32_t block_size = blksize(); const uint32_t block_size = blksize();
auto block_buffer = m_fs.get_block_buffer(); auto block_buffer = TRY(m_fs.get_block_buffer());
const uint32_t first_block = offset / block_size; const uint32_t first_block = offset / block_size;
const uint32_t last_block = BAN::Math::div_round_up<uint32_t>(offset + count, block_size); const uint32_t last_block = BAN::Math::div_round_up<uint32_t>(offset + count, block_size);
@ -192,7 +192,7 @@ namespace Kernel
const uint32_t block_size = blksize(); const uint32_t block_size = blksize();
auto block_buffer = m_fs.get_block_buffer(); auto block_buffer = TRY(m_fs.get_block_buffer());
size_t written = 0; size_t written = 0;
size_t to_write = buffer.size(); size_t to_write = buffer.size();
@ -349,7 +349,7 @@ namespace Kernel
return {}; return {};
} }
auto block_buffer = m_fs.get_block_buffer(); auto block_buffer = TRY(m_fs.get_block_buffer());
TRY(m_fs.read_block(block, block_buffer)); TRY(m_fs.read_block(block, block_buffer));
const uint32_t ids_per_block = blksize() / sizeof(uint32_t); const uint32_t ids_per_block = blksize() / sizeof(uint32_t);
@ -409,7 +409,7 @@ done:
// FIXME: can we actually assume directories have all their blocks allocated // FIXME: can we actually assume directories have all their blocks allocated
const uint32_t block_index = TRY(fs_block_of_data_block_index(offset)).value(); const uint32_t block_index = TRY(fs_block_of_data_block_index(offset)).value();
auto block_buffer = m_fs.get_block_buffer(); auto block_buffer = TRY(m_fs.get_block_buffer());
TRY(m_fs.read_block(block_index, block_buffer)); TRY(m_fs.read_block(block_index, block_buffer));
@ -569,9 +569,7 @@ done:
{ {
ASSERT(this->mode().ifdir()); ASSERT(this->mode().ifdir());
ASSERT(!inode->mode().ifdir()); ASSERT(!inode->mode().ifdir());
ASSERT(&m_fs == inode->filesystem());
if (&m_fs != inode->filesystem())
return BAN::Error::from_errno(EXDEV);
if (!find_inode_impl(name).is_error()) if (!find_inode_impl(name).is_error())
return BAN::Error::from_errno(EEXIST); return BAN::Error::from_errno(EEXIST);
@ -604,7 +602,7 @@ done:
const uint32_t block_size = m_fs.block_size(); const uint32_t block_size = m_fs.block_size();
auto block_buffer = m_fs.get_block_buffer(); auto block_buffer = TRY(m_fs.get_block_buffer());
auto write_inode = auto write_inode =
[&](uint32_t entry_offset, uint32_t entry_rec_len) -> BAN::ErrorOr<void> [&](uint32_t entry_offset, uint32_t entry_rec_len) -> BAN::ErrorOr<void>
@ -691,7 +689,7 @@ needs_new_block:
{ {
ASSERT(mode().ifdir()); ASSERT(mode().ifdir());
auto block_buffer = m_fs.get_block_buffer(); auto block_buffer = TRY(m_fs.get_block_buffer());
// Confirm that this doesn't contain anything else than '.' or '..' // Confirm that this doesn't contain anything else than '.' or '..'
for (uint32_t i = 0; i < max_used_data_block_count(); i++) for (uint32_t i = 0; i < max_used_data_block_count(); i++)
@ -728,7 +726,7 @@ needs_new_block:
return BAN::Error::from_errno(ENOTSUP); return BAN::Error::from_errno(ENOTSUP);
} }
auto block_buffer = m_fs.get_block_buffer(); auto block_buffer = TRY(m_fs.get_block_buffer());
for (uint32_t i = 0; i < max_used_data_block_count(); i++) for (uint32_t i = 0; i < max_used_data_block_count(); i++)
{ {
@ -784,7 +782,7 @@ needs_new_block:
return BAN::Error::from_errno(ENOTSUP); return BAN::Error::from_errno(ENOTSUP);
} }
auto block_buffer = m_fs.get_block_buffer(); auto block_buffer = TRY(m_fs.get_block_buffer());
for (uint32_t i = 0; i < max_used_data_block_count(); i++) for (uint32_t i = 0; i < max_used_data_block_count(); i++)
{ {
@ -846,7 +844,7 @@ needs_new_block:
block = TRY(m_fs.reserve_free_block(block_group())); block = TRY(m_fs.reserve_free_block(block_group()));
m_inode.blocks += inode_blocks_per_fs_block; m_inode.blocks += inode_blocks_per_fs_block;
auto block_buffer = m_fs.get_block_buffer(); auto block_buffer = TRY(m_fs.get_block_buffer());
memset(block_buffer.data(), 0x00, block_buffer.size()); memset(block_buffer.data(), 0x00, block_buffer.size());
TRY(m_fs.write_block(block, block_buffer)); TRY(m_fs.write_block(block, block_buffer));
} }
@ -854,7 +852,7 @@ needs_new_block:
if (depth == 0) if (depth == 0)
return block; return block;
auto block_buffer = m_fs.get_block_buffer(); auto block_buffer = TRY(m_fs.get_block_buffer());
TRY(m_fs.read_block(block, block_buffer)); TRY(m_fs.read_block(block, block_buffer));
uint32_t divisor = 1; uint32_t divisor = 1;
@ -903,7 +901,7 @@ needs_new_block:
BAN::ErrorOr<void> Ext2Inode::sync() BAN::ErrorOr<void> Ext2Inode::sync()
{ {
auto inode_location = TRY(m_fs.locate_inode(ino())); auto inode_location = TRY(m_fs.locate_inode(ino()));
auto block_buffer = m_fs.get_block_buffer(); auto block_buffer = TRY(m_fs.get_block_buffer());
TRY(m_fs.read_block(inode_location.block, block_buffer)); TRY(m_fs.read_block(inode_location.block, block_buffer));
if (memcmp(block_buffer.data() + inode_location.offset, &m_inode, sizeof(Ext2::Inode))) if (memcmp(block_buffer.data() + inode_location.offset, &m_inode, sizeof(Ext2::Inode)))
@ -919,7 +917,7 @@ needs_new_block:
{ {
ASSERT(mode().ifdir()); ASSERT(mode().ifdir());
auto block_buffer = m_fs.get_block_buffer(); auto block_buffer = TRY(m_fs.get_block_buffer());
for (uint32_t i = 0; i < max_used_data_block_count(); i++) for (uint32_t i = 0; i < max_used_data_block_count(); i++)
{ {

View File

@ -107,6 +107,8 @@ namespace Kernel
return BAN::Error::from_errno(ENOTDIR); return BAN::Error::from_errno(ENOTDIR);
if (inode->mode().ifdir()) if (inode->mode().ifdir())
return BAN::Error::from_errno(EINVAL); return BAN::Error::from_errno(EINVAL);
if (this->filesystem() != inode->filesystem())
return BAN::Error::from_errno(EXDEV);
if (auto* fs = filesystem(); fs && (fs->flag() & ST_RDONLY)) if (auto* fs = filesystem(); fs && (fs->flag() & ST_RDONLY))
return BAN::Error::from_errno(EROFS); return BAN::Error::from_errno(EROFS);
return link_inode_impl(name, inode); return link_inode_impl(name, inode);

View File

@ -38,6 +38,14 @@ namespace Kernel
auto cmdline_inode = MUST(TmpFileInode::create_new(*s_instance, 0444, 0, 0)); auto cmdline_inode = MUST(TmpFileInode::create_new(*s_instance, 0444, 0, 0));
MUST(cmdline_inode->write(0, { reinterpret_cast<const uint8_t*>(g_boot_info.command_line.data()), g_boot_info.command_line.size() })); MUST(cmdline_inode->write(0, { reinterpret_cast<const uint8_t*>(g_boot_info.command_line.data()), g_boot_info.command_line.size() }));
MUST(static_cast<TmpDirectoryInode*>(s_instance->root_inode().ptr())->link_inode(*cmdline_inode, "cmdline"_sv)); MUST(static_cast<TmpDirectoryInode*>(s_instance->root_inode().ptr())->link_inode(*cmdline_inode, "cmdline"_sv));
auto self_inode = MUST(ProcSymlinkInode::create_new(
[](void*) -> BAN::ErrorOr<BAN::String> {
return BAN::String::formatted("{}", Process::current().pid());
},
nullptr, *s_instance, 0444, 0, 0)
);
MUST(static_cast<TmpDirectoryInode*>(s_instance->root_inode().ptr())->link_inode(*self_inode, "self"_sv));
} }
ProcFileSystem& ProcFileSystem::get() ProcFileSystem& ProcFileSystem::get()

View File

@ -18,6 +18,16 @@ namespace Kernel
TRY(inode->link_inode(*MUST(ProcROProcessInode::create_new(process, &Process::proc_cmdline, fs, 0400)), "cmdline"_sv)); TRY(inode->link_inode(*MUST(ProcROProcessInode::create_new(process, &Process::proc_cmdline, fs, 0400)), "cmdline"_sv));
TRY(inode->link_inode(*MUST(ProcROProcessInode::create_new(process, &Process::proc_environ, fs, 0400)), "environ"_sv)); TRY(inode->link_inode(*MUST(ProcROProcessInode::create_new(process, &Process::proc_environ, fs, 0400)), "environ"_sv));
TRY(inode->link_inode(*MUST(ProcSymlinkInode::create_new(
[](void* process) -> BAN::ErrorOr<BAN::String>
{
BAN::String result;
TRY(result.append(static_cast<Process*>(process)->executable()));
return result;
},
&process, fs, 0400, process.credentials().ruid(), process.credentials().ruid()
)), "exe"_sv));
return inode; return inode;
} }
@ -32,6 +42,7 @@ namespace Kernel
(void)TmpDirectoryInode::unlink_impl("meminfo"_sv); (void)TmpDirectoryInode::unlink_impl("meminfo"_sv);
(void)TmpDirectoryInode::unlink_impl("cmdline"_sv); (void)TmpDirectoryInode::unlink_impl("cmdline"_sv);
(void)TmpDirectoryInode::unlink_impl("environ"_sv); (void)TmpDirectoryInode::unlink_impl("environ"_sv);
(void)TmpDirectoryInode::unlink_impl("exe"_sv);
} }
BAN::ErrorOr<BAN::RefPtr<ProcROProcessInode>> ProcROProcessInode::create_new(Process& process, size_t (Process::*callback)(off_t, BAN::ByteSpan) const, TmpFileSystem& fs, mode_t mode) BAN::ErrorOr<BAN::RefPtr<ProcROProcessInode>> ProcROProcessInode::create_new(Process& process, size_t (Process::*callback)(off_t, BAN::ByteSpan) const, TmpFileSystem& fs, mode_t mode)
@ -83,4 +94,27 @@ namespace Kernel
return m_callback(offset, buffer); return m_callback(offset, buffer);
} }
BAN::ErrorOr<BAN::RefPtr<ProcSymlinkInode>> ProcSymlinkInode::create_new(BAN::ErrorOr<BAN::String> (*callback)(void*), void* data, TmpFileSystem& fs, mode_t mode, uid_t uid, gid_t gid)
{
auto inode_info = create_inode_info(Mode::IFLNK | mode, uid, gid);
auto* inode_ptr = new ProcSymlinkInode(callback, data, fs, inode_info);
if (inode_ptr == nullptr)
return BAN::Error::from_errno(ENOMEM);
return BAN::RefPtr<ProcSymlinkInode>::adopt(inode_ptr);
}
ProcSymlinkInode::ProcSymlinkInode(BAN::ErrorOr<BAN::String> (*callback)(void*), void* data, TmpFileSystem& fs, const TmpInodeInfo& inode_info)
: TmpInode(fs, MUST(fs.allocate_inode(inode_info)), inode_info)
, m_callback(callback)
, m_data(data)
{
m_inode_info.mode |= Inode::Mode::IFLNK;
}
BAN::ErrorOr<BAN::String> ProcSymlinkInode::link_target_impl()
{
return m_callback(m_data);
}
} }

View File

@ -655,6 +655,20 @@ namespace Kernel
return {}; return {};
} }
BAN::ErrorOr<void> TmpDirectoryInode::link_inode_impl(BAN::StringView name, BAN::RefPtr<Inode> inode)
{
ASSERT(this->mode().ifdir());
ASSERT(!inode->mode().ifdir());
ASSERT(&m_fs == inode->filesystem());
if (!find_inode_impl(name).is_error())
return BAN::Error::from_errno(EEXIST);
auto* tmp_inode = static_cast<TmpInode*>(inode.ptr());
TRY(link_inode(*tmp_inode, name));
return {};
}
BAN::ErrorOr<void> TmpDirectoryInode::unlink_impl(BAN::StringView name) BAN::ErrorOr<void> TmpDirectoryInode::unlink_impl(BAN::StringView name)
{ {
ino_t entry_ino = 0; ino_t entry_ino = 0;

View File

@ -36,6 +36,9 @@ namespace Kernel
return BAN::Error::from_errno(ENOMEM); return BAN::Error::from_errno(ENOMEM);
BAN::ScopeGuard _([temp_page] { kfree(temp_page); }); BAN::ScopeGuard _([temp_page] { kfree(temp_page); });
BAN::String next_file_name;
BAN::String next_link_name;
size_t offset = 0; size_t offset = 0;
while (offset + 512 <= module.size) while (offset + 512 <= module.size)
{ {
@ -87,12 +90,13 @@ namespace Kernel
auto parent_inode = filesystem->root_inode(); auto parent_inode = filesystem->root_inode();
auto file_path_parts = TRY(BAN::StringView(file_path).split('/')); auto file_path_parts = TRY(BAN::StringView(next_file_name.empty() ? file_path : next_file_name.sv()).split('/'));
for (size_t i = 0; i < file_path_parts.size() - 1; i++) for (size_t i = 0; i < file_path_parts.size() - 1; i++)
parent_inode = TRY(parent_inode->find_inode(file_path_parts[i])); parent_inode = TRY(parent_inode->find_inode(file_path_parts[i]));
switch (file_type) switch (file_type)
{ {
case 'L': case 'K': break;
case REGTYPE: case REGTYPE:
case AREGTYPE: file_mode |= Inode::Mode::IFREG; break; case AREGTYPE: file_mode |= Inode::Mode::IFREG; break;
case LNKTYPE: break; case LNKTYPE: break;
@ -102,12 +106,34 @@ namespace Kernel
case DIRTYPE: file_mode |= Inode::Mode::IFDIR; break; case DIRTYPE: file_mode |= Inode::Mode::IFDIR; break;
case FIFOTYPE: file_mode |= Inode::Mode::IFIFO; break; case FIFOTYPE: file_mode |= Inode::Mode::IFIFO; break;
default: default:
ASSERT_NOT_REACHED(); panic("unknown file type {}", file_type);
} }
auto file_name_sv = file_path_parts.back(); auto file_name_sv = file_path_parts.back();
if (file_type == DIRTYPE) if (file_type == 'L' || file_type == 'K')
{
auto& target = (file_type == 'L') ? next_file_name : next_link_name;
TRY(target.resize(file_size));
size_t nwritten = 0;
while (nwritten < file_size)
{
const paddr_t paddr = module.start + offset + 512 + nwritten;
PageTable::with_fast_page(paddr & PAGE_ADDR_MASK, [&] {
memcpy(temp_page, PageTable::fast_page_as_ptr(), PAGE_SIZE);
});
const size_t page_off = paddr % PAGE_SIZE;
const size_t to_write = BAN::Math::min(file_size - nwritten, PAGE_SIZE - page_off);
memcpy(target.data() + nwritten, temp_page + page_off, to_write);
nwritten += to_write;
}
while (!target.empty() && target.back() == '\0')
target.pop_back();
}
else if (file_type == DIRTYPE)
{ {
if (file_name_sv == "."_sv) if (file_name_sv == "."_sv)
; // NOTE: don't create "." (root) ; // NOTE: don't create "." (root)
@ -116,7 +142,38 @@ namespace Kernel
} }
else if (file_type == LNKTYPE) else if (file_type == LNKTYPE)
{ {
dwarnln("TODO: hardlink"); BAN::StringView link_name;
char link_buffer[101] {};
if (!next_link_name.empty())
link_name = next_link_name.sv();
else
{
const paddr_t paddr = module.start + offset;
PageTable::with_fast_page(paddr & PAGE_ADDR_MASK, [&] {
memcpy(link_buffer, PageTable::fast_page_as_ptr((paddr % PAGE_SIZE) + 157), 100);
});
link_name = link_buffer;
}
auto target_inode = filesystem->root_inode();
auto link_path_parts = TRY(link_name.split('/'));
for (const auto part : link_path_parts)
{
auto find_result = target_inode->find_inode(part);
if (!find_result.is_error())
target_inode = find_result.release_value();
else
{
target_inode = {};
break;
}
}
if (target_inode)
if (auto ret = parent_inode->link_inode(file_name_sv, target_inode); ret.is_error())
dwarnln("failed to create hardlink '{}': {}", file_name_sv, ret.error());
} }
else if (file_type == SYMTYPE) else if (file_type == SYMTYPE)
{ {
@ -124,17 +181,22 @@ namespace Kernel
dwarnln("failed to create symlink '{}': {}", file_name_sv, ret.error()); dwarnln("failed to create symlink '{}': {}", file_name_sv, ret.error());
else else
{ {
char link_target[101] {}; BAN::StringView link_name;
const paddr_t paddr = module.start + offset;
PageTable::with_fast_page(paddr & PAGE_ADDR_MASK, [&] {
memcpy(link_target, PageTable::fast_page_as_ptr((paddr % PAGE_SIZE) + 157), 100);
});
if (link_target[0]) char link_buffer[101] {};
if (!next_link_name.empty())
link_name = next_link_name.sv();
else
{ {
auto inode = TRY(parent_inode->find_inode(file_name_sv)); const paddr_t paddr = module.start + offset;
TRY(inode->set_link_target(link_target)); PageTable::with_fast_page(paddr & PAGE_ADDR_MASK, [&] {
memcpy(link_buffer, PageTable::fast_page_as_ptr((paddr % PAGE_SIZE) + 157), 100);
});
link_name = link_buffer;
} }
auto inode = TRY(parent_inode->find_inode(file_name_sv));
TRY(inode->set_link_target(link_name));
} }
} }
else else
@ -164,6 +226,12 @@ namespace Kernel
} }
} }
if (file_type != 'L' && file_type != 'K')
{
next_file_name.clear();
next_link_name.clear();
}
offset += 512 + file_size; offset += 512 + file_size;
if (auto rem = offset % 512) if (auto rem = offset % 512)
offset += 512 - rem; offset += 512 - rem;

View File

@ -174,7 +174,7 @@ namespace Kernel
MUST(s_instance->mount(root_creds, &ProcFileSystem::get(), "/proc"_sv)); MUST(s_instance->mount(root_creds, &ProcFileSystem::get(), "/proc"_sv));
auto tmpfs = MUST(TmpFileSystem::create(1024, 0777, 0, 0)); auto tmpfs = MUST(TmpFileSystem::create(-1, 0777, 0, 0));
MUST(s_instance->mount(root_creds, tmpfs, "/tmp"_sv)); MUST(s_instance->mount(root_creds, tmpfs, "/tmp"_sv));
} }

View File

@ -468,8 +468,8 @@ namespace Kernel::Input
TRY(send_command(PS2::Command::DISABLE_SECOND_PORT)); TRY(send_command(PS2::Command::DISABLE_SECOND_PORT));
// Flush The Output Buffer // Flush The Output Buffer
while (!read_byte().is_error()) while (IO::inb(m_command_port) & PS2::Status::OUTPUT_STATUS)
continue; IO::inb(m_data_port);
// Set the Controller Configuration Byte // Set the Controller Configuration Byte
TRY(send_command(PS2::Command::READ_CONFIG)); TRY(send_command(PS2::Command::READ_CONFIG));

View File

@ -13,7 +13,12 @@ namespace Kernel
if (offset < 0 || offset % PAGE_SIZE || size == 0) if (offset < 0 || offset % PAGE_SIZE || size == 0)
return BAN::Error::from_errno(EINVAL); return BAN::Error::from_errno(EINVAL);
if ((size > (size_t)inode->size() || (size_t)offset > (size_t)inode->size() - size))
size_t inode_size_aligned = inode->size();
if (auto rem = inode_size_aligned % PAGE_SIZE)
inode_size_aligned += PAGE_SIZE - rem;
if ((size > inode_size_aligned || static_cast<size_t>(offset) > inode_size_aligned - size))
return BAN::Error::from_errno(EOVERFLOW); return BAN::Error::from_errno(EOVERFLOW);
auto* region_ptr = new FileBackedRegion(inode, page_table, offset, size, type, flags, status_flags); auto* region_ptr = new FileBackedRegion(inode, page_table, offset, size, type, flags, status_flags);

View File

@ -132,6 +132,8 @@ namespace Kernel
auto executable = TRY(ELF::load_from_inode(process->m_root_file.inode, executable_inode, process->m_credentials, process->page_table())); auto executable = TRY(ELF::load_from_inode(process->m_root_file.inode, executable_inode, process->m_credentials, process->page_table()));
process->m_mapped_regions = BAN::move(executable.regions); process->m_mapped_regions = BAN::move(executable.regions);
TRY(process->m_executable.append(executable_file.canonical_path));
if (executable_inode->mode().mode & +Inode::Mode::ISUID) if (executable_inode->mode().mode & +Inode::Mode::ISUID)
process->m_credentials.set_euid(executable_inode->uid()); process->m_credentials.set_euid(executable_inode->uid());
if (executable_inode->mode().mode & +Inode::Mode::ISGID) if (executable_inode->mode().mode & +Inode::Mode::ISGID)
@ -672,6 +674,9 @@ namespace Kernel
auto executable = TRY(ELF::load_from_inode(m_root_file.inode, executable_inode, m_credentials, *new_page_table)); auto executable = TRY(ELF::load_from_inode(m_root_file.inode, executable_inode, m_credentials, *new_page_table));
auto new_mapped_regions = BAN::move(executable.regions); auto new_mapped_regions = BAN::move(executable.regions);
BAN::String executable_path;
TRY(executable_path.append(executable_file.canonical_path));
BAN::Vector<LibELF::AuxiliaryVector> auxiliary_vector; BAN::Vector<LibELF::AuxiliaryVector> auxiliary_vector;
TRY(auxiliary_vector.reserve(1 + executable.open_execfd)); TRY(auxiliary_vector.reserve(1 + executable.open_execfd));
@ -712,6 +717,11 @@ namespace Kernel
new_thread->set_tls(tls_result.addr); new_thread->set_tls(tls_result.addr);
} }
// NOTE: this is done before disabling interrupts and moving the threads as
// shared filebacked mmap can write to disk on on clearing, this will lock
// filesystem mutex which can yield
m_mapped_regions.clear();
ASSERT(Processor::get_interrupt_state() == InterruptState::Enabled); ASSERT(Processor::get_interrupt_state() == InterruptState::Enabled);
Processor::set_interrupt_state(InterruptState::Disabled); Processor::set_interrupt_state(InterruptState::Disabled);
@ -756,6 +766,7 @@ namespace Kernel
m_cmdline = BAN::move(str_argv); m_cmdline = BAN::move(str_argv);
m_environ = BAN::move(str_envp); m_environ = BAN::move(str_envp);
m_executable = BAN::move(executable_path);
} }
m_has_called_exec = true; m_has_called_exec = true;
@ -1225,7 +1236,8 @@ namespace Kernel
{ {
LockGuard _(m_process_lock); LockGuard _(m_process_lock);
TRY(validate_string_access(path1)); TRY(validate_string_access(path1));
TRY(validate_string_access(path2)); if (path2 != nullptr)
TRY(validate_string_access(path2));
if (!find_file(fd, path2, O_NOFOLLOW).is_error()) if (!find_file(fd, path2, O_NOFOLLOW).is_error())
return BAN::Error::from_errno(EEXIST); return BAN::Error::from_errno(EEXIST);

View File

@ -1,4 +1,5 @@
#include <kernel/InterruptController.h> #include <kernel/InterruptController.h>
#include <kernel/Memory/Heap.h>
#include <kernel/Memory/kmalloc.h> #include <kernel/Memory/kmalloc.h>
#include <kernel/Processor.h> #include <kernel/Processor.h>
#include <kernel/Terminal/TerminalDriver.h> #include <kernel/Terminal/TerminalDriver.h>
@ -47,6 +48,10 @@ namespace Kernel
if (s_bsp_id == PROCESSOR_NONE || id == PROCESSOR_NONE || id.m_id >= s_processors.size()) if (s_bsp_id == PROCESSOR_NONE || id == PROCESSOR_NONE || id.m_id >= s_processors.size())
Kernel::panic("Trying to initialize invalid processor {}", id.m_id); Kernel::panic("Trying to initialize invalid processor {}", id.m_id);
if (id == s_bsp_id)
for (auto& processor : s_processors)
processor.m_id = PROCESSOR_NONE;
auto& processor = s_processors[id.m_id]; auto& processor = s_processors[id.m_id];
ASSERT(processor.m_id == PROCESSOR_NONE); ASSERT(processor.m_id == PROCESSOR_NONE);
@ -64,15 +69,6 @@ namespace Kernel
processor.m_scheduler = MUST(Scheduler::create()); processor.m_scheduler = MUST(Scheduler::create());
ASSERT(processor.m_scheduler); ASSERT(processor.m_scheduler);
SMPMessage* smp_storage = new SMPMessage[0x1000];
ASSERT(smp_storage);
for (size_t i = 0; i < 0xFFF; i++)
smp_storage[i].next = &smp_storage[i + 1];
smp_storage[0xFFF].next = nullptr;
processor.m_smp_pending = nullptr;
processor.m_smp_free = smp_storage;
s_processors_created++; s_processors_created++;
return processor; return processor;
@ -103,6 +99,34 @@ namespace Kernel
return processor; return processor;
} }
void Processor::initialize_smp()
{
const auto processor_id = current_id();
auto& processor = s_processors[processor_id.as_u32()];
const paddr_t smp_paddr = Heap::get().take_free_page();
ASSERT(smp_paddr);
const vaddr_t smp_vaddr = PageTable::kernel().reserve_free_page(KERNEL_OFFSET);
ASSERT(smp_vaddr);
PageTable::kernel().map_page_at(
smp_paddr, smp_vaddr,
PageTable::Flags::ReadWrite | PageTable::Flags::Present,
PageTable::MemoryType::Uncached
);
auto* smp_storage = reinterpret_cast<SMPMessage*>(smp_vaddr);
constexpr size_t smp_storage_entries = PAGE_SIZE / sizeof(SMPMessage);
for (size_t i = 0; i < smp_storage_entries - 1; i++)
smp_storage[i].next = &smp_storage[i + 1];
smp_storage[smp_storage_entries - 1].next = nullptr;
processor.m_smp_pending = nullptr;
processor.m_smp_free = smp_storage;
}
ProcessorID Processor::id_from_index(size_t index) ProcessorID Processor::id_from_index(size_t index)
{ {
ASSERT(index < s_processor_count); ASSERT(index < s_processor_count);
@ -112,12 +136,7 @@ namespace Kernel
void Processor::wait_until_processors_ready() void Processor::wait_until_processors_ready()
{ {
if (s_processors_created == 1) initialize_smp();
{
ASSERT(current_is_bsp());
s_processor_count++;
s_processor_ids[0] = current_id();
}
// wait until bsp is ready // wait until bsp is ready
if (current_is_bsp()) if (current_is_bsp())
@ -178,21 +197,6 @@ namespace Kernel
handle_smp_messages(); handle_smp_messages();
} }
template<typename F>
void with_atomic_lock(BAN::Atomic<bool>& lock, F callback)
{
bool expected = false;
while (!lock.compare_exchange(expected, true, BAN::MemoryOrder::memory_order_acquire))
{
__builtin_ia32_pause();
expected = false;
}
callback();
lock.store(false, BAN::MemoryOrder::memory_order_release);
}
void Processor::handle_smp_messages() void Processor::handle_smp_messages()
{ {
auto state = get_interrupt_state(); auto state = get_interrupt_state();
@ -201,65 +205,61 @@ namespace Kernel
auto processor_id = current_id(); auto processor_id = current_id();
auto& processor = s_processors[processor_id.m_id]; auto& processor = s_processors[processor_id.m_id];
SMPMessage* pending = nullptr; auto* pending = processor.m_smp_pending.exchange(nullptr);
with_atomic_lock(processor.m_smp_pending_lock, if (pending == nullptr)
[&]() return set_interrupt_state(state);
{
pending = processor.m_smp_pending;
processor.m_smp_pending = nullptr;
}
);
if (pending) // reverse smp message queue from LIFO to FIFO
{ {
// reverse smp message queue from LIFO to FIFO SMPMessage* reversed = nullptr;
for (auto* message = pending; message;)
{ {
SMPMessage* reversed = nullptr; SMPMessage* next = message->next;
message->next = reversed;
for (SMPMessage* message = pending; message;) reversed = message;
{ message = next;
SMPMessage* next = message->next;
message->next = reversed;
reversed = message;
message = next;
}
pending = reversed;
} }
SMPMessage* last_handled = nullptr; pending = reversed;
}
// handle messages SMPMessage* last_handled = nullptr;
for (auto* message = pending; message; message = message->next)
// handle messages
for (auto* message = pending; message; message = message->next)
{
switch (message->type)
{ {
switch (message->type) case SMPMessage::Type::FlushTLB:
{ for (size_t i = 0; i < message->flush_tlb.page_count; i++)
case SMPMessage::Type::FlushTLB: asm volatile("invlpg (%0)" :: "r"(message->flush_tlb.vaddr + i * PAGE_SIZE) : "memory");
for (size_t i = 0; i < message->flush_tlb.page_count; i++) break;
asm volatile("invlpg (%0)" :: "r"(message->flush_tlb.vaddr + i * PAGE_SIZE) : "memory"); case SMPMessage::Type::NewThread:
break; processor.m_scheduler->add_thread(message->new_thread);
case SMPMessage::Type::NewThread: break;
processor.m_scheduler->add_thread(message->new_thread); case SMPMessage::Type::UnblockThread:
break; processor.m_scheduler->unblock_thread(message->unblock_thread);
case SMPMessage::Type::UnblockThread: break;
processor.m_scheduler->unblock_thread(message->unblock_thread); #if WITH_PROFILING
break; case SMPMessage::Type::StartProfiling:
case SMPMessage::Type::StackTrace: processor.start_profiling();
dwarnln("Stack trace of CPU {}", current_id().as_u32()); break;
Debug::dump_stack_trace(); #endif
break; case SMPMessage::Type::StackTrace:
} dwarnln("Stack trace of CPU {}", current_id().as_u32());
Debug::dump_stack_trace();
last_handled = message; break;
} }
with_atomic_lock(processor.m_smp_free_lock, last_handled = message;
[&]() }
{
last_handled->next = processor.m_smp_free; last_handled->next = processor.m_smp_free;
processor.m_smp_free = pending; while (!processor.m_smp_free.compare_exchange(last_handled->next, pending))
} {
); __builtin_ia32_pause();
last_handled->next = processor.m_smp_free;
} }
set_interrupt_state(state); set_interrupt_state(state);
@ -279,35 +279,49 @@ namespace Kernel
void Processor::send_smp_message(ProcessorID processor_id, const SMPMessage& message, bool send_ipi) void Processor::send_smp_message(ProcessorID processor_id, const SMPMessage& message, bool send_ipi)
{ {
auto state = get_interrupt_state(); auto state = get_interrupt_state();
set_interrupt_state(InterruptState::Disabled); set_interrupt_state(InterruptState::Disabled);
auto& processor = s_processors[processor_id.m_id]; auto& processor = s_processors[processor_id.m_id];
// take free message slot // find a slot for message
SMPMessage* storage = nullptr; auto* storage = processor.m_smp_free.exchange(nullptr);
with_atomic_lock(processor.m_smp_free_lock, while (storage == nullptr)
[&]() {
{ __builtin_ia32_pause();
storage = processor.m_smp_free; storage = processor.m_smp_free.exchange(nullptr);
ASSERT(storage && storage->next); }
processor.m_smp_free = storage->next; if (auto* base = storage->next)
{
SMPMessage* null = nullptr;
if (!processor.m_smp_free.compare_exchange(null, base))
{
// NOTE: this is an annoying traversal, but most of the time
// above if condition bypasses this :)
auto* last = base;
while (last->next)
last = last->next;
last->next = processor.m_smp_free;
while (!processor.m_smp_free.compare_exchange(last->next, base))
{
__builtin_ia32_pause();
last->next = processor.m_smp_free;
}
} }
); }
// write message // write message
*storage = message; *storage = message;
// push message to pending queue // push message to pending queue
with_atomic_lock(processor.m_smp_pending_lock, storage->next = processor.m_smp_pending;
[&]() while (!processor.m_smp_pending.compare_exchange(storage->next, storage))
{ {
storage->next = processor.m_smp_pending; __builtin_ia32_pause();
processor.m_smp_pending = storage; storage->next = processor.m_smp_pending;
} }
);
if (send_ipi) if (send_ipi)
{ {

View File

@ -573,13 +573,24 @@ namespace Kernel
{ {
// Make sure stack is allocated // Make sure stack is allocated
const vaddr_t pages[3] { vaddr_t pages[3] {};
(interrupt_stack.sp - sizeof(uintptr_t)) & PAGE_ADDR_MASK, size_t page_count { 0 };
(signal_stack_top - 4 * sizeof(uintptr_t)) & PAGE_ADDR_MASK,
(signal_stack_top - 1 * sizeof(uintptr_t)) & PAGE_ADDR_MASK,
};
for (size_t i = 0; i < 3; i++) if (signal_stack_top == 0)
{
pages[0] = (interrupt_stack.sp - 1 * sizeof(uintptr_t)) & PAGE_ADDR_MASK;
pages[1] = (interrupt_stack.sp - 5 * sizeof(uintptr_t)) & PAGE_ADDR_MASK;
page_count = 2;
}
else
{
pages[0] = (interrupt_stack.sp - sizeof(uintptr_t)) & PAGE_ADDR_MASK;
pages[1] = (signal_stack_top - 4 * sizeof(uintptr_t)) & PAGE_ADDR_MASK;
pages[2] = (signal_stack_top - 1 * sizeof(uintptr_t)) & PAGE_ADDR_MASK;
page_count = 3;
}
for (size_t i = 0; i < page_count; i++)
{ {
if (m_process->page_table().get_page_flags(pages[i]) & PageTable::Flags::Present) if (m_process->page_table().get_page_flags(pages[i]) & PageTable::Flags::Present)
continue; continue;
@ -782,6 +793,8 @@ namespace Kernel
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
} }
} }
Processor::set_interrupt_state(InterruptState::Disabled);
m_state = State::Terminated; m_state = State::Terminated;
Processor::yield(); Processor::yield();
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();

View File

@ -1,10 +1,9 @@
#!/bin/bash ../install.sh #!/bin/bash ../install.sh
NAME='gcc' NAME='gcc'
VERSION='15.1.0' VERSION='15.2.0'
DOWNLOAD_URL="https://ftp.gnu.org/gnu/gcc/gcc-$VERSION/gcc-$VERSION.tar.gz#51b9919ea69c980d7a381db95d4be27edf73b21254eb13d752a08003b4d013b1" DOWNLOAD_URL="https://ftp.gnu.org/gnu/gcc/gcc-$VERSION/gcc-$VERSION.tar.xz#438fd996826b0c82485a29da03a72d71d6e3541a83ec702df4271f6fe025d24e"
DEPENDENCIES=('binutils' 'gmp' 'mpfr' 'mpc') DEPENDENCIES=('binutils' 'gmp' 'mpfr' 'mpc')
MAKE_BUILD_TARGETS=('all-gcc' 'all-target-libgcc' 'all-target-libstdc++-v3')
MAKE_INSTALL_TARGETS=('install-strip-gcc' 'install-strip-target-libgcc' 'install-strip-target-libstdc++-v3') MAKE_INSTALL_TARGETS=('install-strip-gcc' 'install-strip-target-libgcc' 'install-strip-target-libstdc++-v3')
CONFIGURE_OPTIONS=( CONFIGURE_OPTIONS=(
"--target=$BANAN_TOOLCHAIN_TRIPLE" "--target=$BANAN_TOOLCHAIN_TRIPLE"
@ -18,6 +17,17 @@ CONFIGURE_OPTIONS=(
'--enable-languages=c,c++' '--enable-languages=c,c++'
) )
build() {
xcflags=""
if [ $BANAN_ARCH = "x86_64" ]; then
xcflags="-mcmodel=large -mno-red-zone"
fi
make -j$(nproc) all-gcc || exit 1
make -j$(nproc) all-target-libgcc CFLAGS_FOR_TARGET="$xcflags" || exit 1
make -j$(nproc) all-target-libstdc++-v3 || exit 1
}
post_install() { post_install() {
# remove libtool files # remove libtool files
rm -f $BANAN_SYSROOT/usr/lib/libstdc++.la rm -f $BANAN_SYSROOT/usr/lib/libstdc++.la

View File

@ -1 +0,0 @@
../../../toolchain/gcc-15.1.0.patch

View File

@ -0,0 +1 @@
../../../toolchain/gcc-15.2.0.patch

View File

@ -59,8 +59,9 @@ config_sub_update() {
config_sub_path="$BANAN_PORT_DIR/config.sub" config_sub_path="$BANAN_PORT_DIR/config.sub"
if [ ! -f "$config_sub_path" ] || [ $(find "$config_sub_path" -mtime +1) ]; then if [ ! -f "$config_sub_path" ]; then
wget -O "$config_sub_path" 'https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD' wget -O "$config_sub_path.tmp" 'https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD' || exit 1
mv $config_sub_path.tmp $config_sub_path
fi fi
for target in "${CONFIG_SUB[@]}"; do for target in "${CONFIG_SUB[@]}"; do

View File

@ -0,0 +1,144 @@
diff -ruN binutils-2.45/bfd/config.bfd binutils-2.45-banan_os/bfd/config.bfd
--- binutils-2.45/bfd/config.bfd 2025-07-27 02:00:00.000000000 +0300
+++ binutils-2.45-banan_os/bfd/config.bfd 2025-08-25 17:59:50.309772929 +0300
@@ -612,6 +612,11 @@
targ_defvec=i386_elf32_vec
targ_selvecs=iamcu_elf32_vec
;;
+ i[3-7]86-*-banan_os*)
+ targ_defvec=i386_elf32_vec
+ targ_selvecs=
+ targ64_selvecs=x86_64_elf64_vec
+ ;;
i[3-7]86-*-dicos*)
targ_defvec=i386_elf32_vec
targ_selvecs=iamcu_elf32_vec
@@ -666,6 +671,11 @@
targ64_selvecs=x86_64_elf64_vec
;;
#ifdef BFD64
+ x86_64-*-banan_os*)
+ targ_defvec=x86_64_elf64_vec
+ targ_selvecs=i386_elf32_vec
+ want64=true
+ ;;
x86_64-*-cloudabi*)
targ_defvec=x86_64_elf64_cloudabi_vec
want64=true
diff -ruN binutils-2.45/config.sub binutils-2.45-banan_os/config.sub
--- binutils-2.45/config.sub 2025-07-27 02:00:00.000000000 +0300
+++ binutils-2.45-banan_os/config.sub 2025-08-25 17:59:50.310634287 +0300
@@ -1976,6 +1976,7 @@
| atheos* \
| auroraux* \
| aux* \
+ | banan_os* \
| beos* \
| bitrig* \
| bme* \
diff -ruN binutils-2.45/gas/configure.tgt binutils-2.45-banan_os/gas/configure.tgt
--- binutils-2.45/gas/configure.tgt 2025-07-27 02:00:00.000000000 +0300
+++ binutils-2.45-banan_os/gas/configure.tgt 2025-08-25 17:59:50.311092868 +0300
@@ -225,6 +225,7 @@
h8300-*-elf) fmt=elf ;;
h8300-*-linux*) fmt=elf em=linux ;;
+ i386-*-banan_os*) fmt=elf em=gnu ;;
i386-*-beospe*) fmt=coff em=pe ;;
i386-*-beos*) fmt=elf ;;
i386-*-elfiamcu) fmt=elf arch=iamcu ;;
diff -ruN binutils-2.45/ld/configure.tgt binutils-2.45-banan_os/ld/configure.tgt
--- binutils-2.45/ld/configure.tgt 2025-07-27 02:00:00.000000000 +0300
+++ binutils-2.45-banan_os/ld/configure.tgt 2025-08-25 17:59:50.311577500 +0300
@@ -367,6 +367,10 @@
i[3-7]86-*-rdos*) targ_emul=elf_i386
targ_extra_emuls=elf_iamcu
;;
+i[3-7]86-*-banan_os*) targ_emul=elf_i386_banan_os
+ targ_extra_emuls=elf_i386
+ targ64_extra_emuls="elf_x86_64_banan_os elf_x86_64"
+ ;;
i[3-7]86-*-bsd) targ_emul=i386bsd
targ_extra_ofiles=
;;
@@ -1000,6 +1004,9 @@
;;
x86_64-*-rdos*) targ_emul=elf64rdos
;;
+x86_64-*-banan_os*) targ_emul=elf_x86_64_banan_os
+ targ_extra_emuls="elf_i386_banan_os elf_x86_64 elf_i386"
+ ;;
x86_64-*-cloudabi*) targ_emul=elf_x86_64_cloudabi
;;
x86_64-*-haiku*) targ_emul=elf_x86_64_haiku
diff -ruN binutils-2.45/ld/emulparams/elf_banan_os.sh binutils-2.45-banan_os/ld/emulparams/elf_banan_os.sh
--- binutils-2.45/ld/emulparams/elf_banan_os.sh 1970-01-01 02:00:00.000000000 +0200
+++ binutils-2.45-banan_os/ld/emulparams/elf_banan_os.sh 2025-08-25 17:59:50.312097122 +0300
@@ -0,0 +1 @@
+ELF_INTERPRETER_NAME=\"/usr/lib/DynamicLoader.so\"
diff -ruN binutils-2.45/ld/emulparams/elf_i386_banan_os.sh binutils-2.45-banan_os/ld/emulparams/elf_i386_banan_os.sh
--- binutils-2.45/ld/emulparams/elf_i386_banan_os.sh 1970-01-01 02:00:00.000000000 +0200
+++ binutils-2.45-banan_os/ld/emulparams/elf_i386_banan_os.sh 2025-08-25 17:59:50.312315308 +0300
@@ -0,0 +1,2 @@
+source_sh ${srcdir}/emulparams/elf_i386.sh
+source_sh ${srcdir}/emulparams/elf_banan_os.sh
diff -ruN binutils-2.45/ld/emulparams/elf_x86_64_banan_os.sh binutils-2.45-banan_os/ld/emulparams/elf_x86_64_banan_os.sh
--- binutils-2.45/ld/emulparams/elf_x86_64_banan_os.sh 1970-01-01 02:00:00.000000000 +0200
+++ binutils-2.45-banan_os/ld/emulparams/elf_x86_64_banan_os.sh 2025-08-25 17:59:50.312553817 +0300
@@ -0,0 +1,2 @@
+source_sh ${srcdir}/emulparams/elf_x86_64.sh
+source_sh ${srcdir}/emulparams/elf_banan_os.sh
diff -ruN binutils-2.45/ld/Makefile.am binutils-2.45-banan_os/ld/Makefile.am
--- binutils-2.45/ld/Makefile.am 2025-07-27 02:00:00.000000000 +0300
+++ binutils-2.45-banan_os/ld/Makefile.am 2025-08-25 17:59:50.312853718 +0300
@@ -277,6 +277,7 @@
eelf32xtensa.c \
eelf32z80.c \
eelf_i386.c \
+ eelf_i386_banan_os.c \
eelf_i386_be.c \
eelf_i386_fbsd.c \
eelf_i386_haiku.c \
@@ -459,6 +460,7 @@
eelf64tilegx_be.c \
eelf_mipsel_haiku.c \
eelf_x86_64.c \
+ eelf_x86_64_banan_os.c \
eelf_x86_64_cloudabi.c \
eelf_x86_64_fbsd.c \
eelf_x86_64_haiku.c \
diff -ruN binutils-2.45/ld/Makefile.in binutils-2.45-banan_os/ld/Makefile.in
--- binutils-2.45/ld/Makefile.in 2025-07-27 02:00:00.000000000 +0300
+++ binutils-2.45-banan_os/ld/Makefile.in 2025-08-25 17:59:50.313554579 +0300
@@ -788,6 +788,7 @@
eelf32xtensa.c \
eelf32z80.c \
eelf_i386.c \
+ eelf_i386_banan_os.c \
eelf_i386_be.c \
eelf_i386_fbsd.c \
eelf_i386_haiku.c \
@@ -969,6 +970,7 @@
eelf64tilegx_be.c \
eelf_mipsel_haiku.c \
eelf_x86_64.c \
+ eelf_x86_64_banan_os.c \
eelf_x86_64_cloudabi.c \
eelf_x86_64_fbsd.c \
eelf_x86_64_haiku.c \
@@ -1476,6 +1478,7 @@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64tilegx.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64tilegx_be.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_i386.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_i386_banan_os.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_i386_be.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_i386_fbsd.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_i386_haiku.Po@am__quote@
@@ -1486,6 +1489,7 @@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_mipsel_haiku.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_s390.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_x86_64.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_x86_64_banan_os.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_x86_64_cloudabi.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_x86_64_fbsd.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf_x86_64_haiku.Po@am__quote@

View File

@ -1,12 +1,12 @@
#!/bin/bash #!/bin/bash
set -e set -e
BINUTILS_VERSION="binutils-2.44" BINUTILS_VERSION="binutils-2.45"
BINUTILS_TAR="$BINUTILS_VERSION.tar.gz" BINUTILS_TAR="$BINUTILS_VERSION.tar.xz"
BINUTILS_URL="https://ftp.gnu.org/gnu/binutils/$BINUTILS_TAR" BINUTILS_URL="https://ftp.gnu.org/gnu/binutils/$BINUTILS_TAR"
GCC_VERSION="gcc-15.1.0" GCC_VERSION="gcc-15.2.0"
GCC_TAR="$GCC_VERSION.tar.gz" GCC_TAR="$GCC_VERSION.tar.xz"
GCC_URL="https://ftp.gnu.org/gnu/gcc/$GCC_VERSION/$GCC_TAR" GCC_URL="https://ftp.gnu.org/gnu/gcc/$GCC_VERSION/$GCC_TAR"
GRUB_VERSION="grub-2.06" GRUB_VERSION="grub-2.06"

View File

@ -1,6 +1,6 @@
diff -ruN gcc-15.1.0/config.sub gcc-15.1.0-banan_os/config.sub diff -ruN gcc-15.2.0/config.sub gcc-15.2.0-banan_os/config.sub
--- gcc-15.1.0/config.sub 2025-04-25 11:17:59.000000000 +0300 --- gcc-15.2.0/config.sub 2025-08-25 18:08:25.524209333 +0300
+++ gcc-15.1.0-banan_os/config.sub 2025-06-19 11:29:44.368548733 +0300 +++ gcc-15.2.0-banan_os/config.sub 2025-08-25 18:09:09.160072736 +0300
@@ -1749,7 +1749,7 @@ @@ -1749,7 +1749,7 @@
| onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \ | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
| midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \ | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
@ -10,9 +10,9 @@ diff -ruN gcc-15.1.0/config.sub gcc-15.1.0-banan_os/config.sub
;; ;;
# This one is extra strict with allowed versions # This one is extra strict with allowed versions
sco3.2v2 | sco3.2v[4-9]* | sco5v6*) sco3.2v2 | sco3.2v[4-9]* | sco5v6*)
diff -ruN gcc-15.1.0/fixincludes/mkfixinc.sh gcc-15.1.0-banan_os/fixincludes/mkfixinc.sh diff -ruN gcc-15.2.0/fixincludes/mkfixinc.sh gcc-15.2.0-banan_os/fixincludes/mkfixinc.sh
--- gcc-15.1.0/fixincludes/mkfixinc.sh 2025-04-25 11:17:59.000000000 +0300 --- gcc-15.2.0/fixincludes/mkfixinc.sh 2025-08-25 18:08:42.043663414 +0300
+++ gcc-15.1.0-banan_os/fixincludes/mkfixinc.sh 2025-06-19 11:30:13.427343038 +0300 +++ gcc-15.2.0-banan_os/fixincludes/mkfixinc.sh 2025-08-25 18:09:09.191771254 +0300
@@ -11,6 +11,7 @@ @@ -11,6 +11,7 @@
# Check for special fix rules for particular targets # Check for special fix rules for particular targets
@ -21,9 +21,9 @@ diff -ruN gcc-15.1.0/fixincludes/mkfixinc.sh gcc-15.1.0-banan_os/fixincludes/mkf
i?86-*-cygwin* | \ i?86-*-cygwin* | \
*-mingw32* | \ *-mingw32* | \
powerpc-*-eabisim* | \ powerpc-*-eabisim* | \
diff -ruN gcc-15.1.0/gcc/config/banan_os.h gcc-15.1.0-banan_os/gcc/config/banan_os.h diff -ruN gcc-15.2.0/gcc/config/banan_os.h gcc-15.2.0-banan_os/gcc/config/banan_os.h
--- gcc-15.1.0/gcc/config/banan_os.h 1970-01-01 02:00:00.000000000 +0200 --- gcc-15.2.0/gcc/config/banan_os.h 1970-01-01 02:00:00.000000000 +0200
+++ gcc-15.1.0-banan_os/gcc/config/banan_os.h 2025-06-19 11:30:53.316059523 +0300 +++ gcc-15.2.0-banan_os/gcc/config/banan_os.h 2025-08-25 18:09:09.192159227 +0300
@@ -0,0 +1,35 @@ @@ -0,0 +1,35 @@
+/* Useful if you wish to make target-specific GCC changes. */ +/* Useful if you wish to make target-specific GCC changes. */
+#undef TARGET_BANAN_OS +#undef TARGET_BANAN_OS
@ -60,9 +60,9 @@ diff -ruN gcc-15.1.0/gcc/config/banan_os.h gcc-15.1.0-banan_os/gcc/config/banan_
+ builtin_assert ("system=unix"); \ + builtin_assert ("system=unix"); \
+ builtin_assert ("system=posix"); \ + builtin_assert ("system=posix"); \
+ } while(0); + } while(0);
diff -ruN gcc-15.1.0/gcc/config/banan_os.opt gcc-15.1.0-banan_os/gcc/config/banan_os.opt diff -ruN gcc-15.2.0/gcc/config/banan_os.opt gcc-15.2.0-banan_os/gcc/config/banan_os.opt
--- gcc-15.1.0/gcc/config/banan_os.opt 1970-01-01 02:00:00.000000000 +0200 --- gcc-15.2.0/gcc/config/banan_os.opt 1970-01-01 02:00:00.000000000 +0200
+++ gcc-15.1.0-banan_os/gcc/config/banan_os.opt 2025-06-19 11:31:29.325802503 +0300 +++ gcc-15.2.0-banan_os/gcc/config/banan_os.opt 2025-08-25 18:09:09.192299819 +0300
@@ -0,0 +1,32 @@ @@ -0,0 +1,32 @@
+; banan_os options. +; banan_os options.
+ +
@ -96,14 +96,14 @@ diff -ruN gcc-15.1.0/gcc/config/banan_os.opt gcc-15.1.0-banan_os/gcc/config/bana
+Driver +Driver
+ +
+; This comment is to ensure we retain the blank line above. +; This comment is to ensure we retain the blank line above.
diff -ruN gcc-15.1.0/gcc/config/banan_os.opt.urls gcc-15.1.0-banan_os/gcc/config/banan_os.opt.urls diff -ruN gcc-15.2.0/gcc/config/banan_os.opt.urls gcc-15.2.0-banan_os/gcc/config/banan_os.opt.urls
--- gcc-15.1.0/gcc/config/banan_os.opt.urls 1970-01-01 02:00:00.000000000 +0200 --- gcc-15.2.0/gcc/config/banan_os.opt.urls 1970-01-01 02:00:00.000000000 +0200
+++ gcc-15.1.0-banan_os/gcc/config/banan_os.opt.urls 2025-06-19 11:31:29.325802503 +0300 +++ gcc-15.2.0-banan_os/gcc/config/banan_os.opt.urls 2025-08-25 18:09:09.192460665 +0300
@@ -0,0 +1 @@ @@ -0,0 +1 @@
+; Not sure what to put here but this works +; Not sure what to put here but this works
diff -ruN gcc-15.1.0/gcc/config.gcc gcc-15.1.0-banan_os/gcc/config.gcc diff -ruN gcc-15.2.0/gcc/config.gcc gcc-15.2.0-banan_os/gcc/config.gcc
--- gcc-15.1.0/gcc/config.gcc 2025-04-25 11:18:00.000000000 +0300 --- gcc-15.2.0/gcc/config.gcc 2025-08-25 18:08:36.953184232 +0300
+++ gcc-15.1.0-banan_os/gcc/config.gcc 2025-06-19 11:32:50.391220522 +0300 +++ gcc-15.2.0-banan_os/gcc/config.gcc 2025-08-25 18:09:09.193116622 +0300
@@ -723,6 +723,14 @@ @@ -723,6 +723,14 @@
# Common parts for widely ported systems. # Common parts for widely ported systems.
@ -132,9 +132,9 @@ diff -ruN gcc-15.1.0/gcc/config.gcc gcc-15.1.0-banan_os/gcc/config.gcc
i[34567]86-*-dragonfly*) i[34567]86-*-dragonfly*)
tm_file="${tm_file} i386/unix.h i386/att.h elfos.h dragonfly.h dragonfly-stdint.h i386/dragonfly.h" tm_file="${tm_file} i386/unix.h i386/att.h elfos.h dragonfly.h dragonfly-stdint.h i386/dragonfly.h"
tmake_file="${tmake_file} i386/t-crtstuff" tmake_file="${tmake_file} i386/t-crtstuff"
diff -ruN gcc-15.1.0/libgcc/config/t-slibgcc gcc-15.1.0-banan_os/libgcc/config/t-slibgcc diff -ruN gcc-15.2.0/libgcc/config/t-slibgcc gcc-15.2.0-banan_os/libgcc/config/t-slibgcc
--- gcc-15.1.0/libgcc/config/t-slibgcc 2025-04-25 11:18:04.000000000 +0300 --- gcc-15.2.0/libgcc/config/t-slibgcc 2025-08-25 18:08:42.538268318 +0300
+++ gcc-15.1.0-banan_os/libgcc/config/t-slibgcc 2025-06-19 11:34:04.674683603 +0300 +++ gcc-15.2.0-banan_os/libgcc/config/t-slibgcc 2025-08-25 18:09:09.206796796 +0300
@@ -26,7 +26,6 @@ @@ -26,7 +26,6 @@
SHLIB_OBJS = @shlib_objs@ SHLIB_OBJS = @shlib_objs@
SHLIB_DIR = @multilib_dir@ SHLIB_DIR = @multilib_dir@
@ -143,9 +143,9 @@ diff -ruN gcc-15.1.0/libgcc/config/t-slibgcc gcc-15.1.0-banan_os/libgcc/config/t
SHLIB_MAKE_SOLINK = $(LN_S) $(SHLIB_SONAME) $(SHLIB_DIR)/$(SHLIB_SOLINK) SHLIB_MAKE_SOLINK = $(LN_S) $(SHLIB_SONAME) $(SHLIB_DIR)/$(SHLIB_SOLINK)
SHLIB_INSTALL_SOLINK = $(LN_S) $(SHLIB_SONAME) \ SHLIB_INSTALL_SOLINK = $(LN_S) $(SHLIB_SONAME) \
$(DESTDIR)$(slibdir)$(SHLIB_SLIBDIR_QUAL)/$(SHLIB_SOLINK) $(DESTDIR)$(slibdir)$(SHLIB_SLIBDIR_QUAL)/$(SHLIB_SOLINK)
diff -ruN gcc-15.1.0/libgcc/config.host gcc-15.1.0-banan_os/libgcc/config.host diff -ruN gcc-15.2.0/libgcc/config.host gcc-15.2.0-banan_os/libgcc/config.host
--- gcc-15.1.0/libgcc/config.host 2025-04-25 11:18:04.000000000 +0300 --- gcc-15.2.0/libgcc/config.host 2025-08-25 18:08:42.103193239 +0300
+++ gcc-15.1.0-banan_os/libgcc/config.host 2025-06-19 11:33:42.354845264 +0300 +++ gcc-15.2.0-banan_os/libgcc/config.host 2025-08-25 18:09:09.221444143 +0300
@@ -627,6 +627,14 @@ @@ -627,6 +627,14 @@
fixed_point=no fixed_point=no
fi fi
@ -161,9 +161,9 @@ diff -ruN gcc-15.1.0/libgcc/config.host gcc-15.1.0-banan_os/libgcc/config.host
bfin*-elf*) bfin*-elf*)
tmake_file="bfin/t-bfin bfin/t-crtlibid bfin/t-crtstuff t-libgcc-pic t-fdpbit" tmake_file="bfin/t-bfin bfin/t-crtlibid bfin/t-crtstuff t-libgcc-pic t-fdpbit"
extra_parts="$extra_parts crtbeginS.o crtendS.o crti.o crtn.o crtlibid.o" extra_parts="$extra_parts crtbeginS.o crtendS.o crti.o crtn.o crtlibid.o"
diff -ruN gcc-15.1.0/libstdc++-v3/acinclude.m4 gcc-15.1.0-banan_os/libstdc++-v3/acinclude.m4 diff -ruN gcc-15.2.0/libstdc++-v3/acinclude.m4 gcc-15.2.0-banan_os/libstdc++-v3/acinclude.m4
--- gcc-15.1.0/libstdc++-v3/acinclude.m4 2025-04-25 11:18:05.000000000 +0300 --- gcc-15.2.0/libstdc++-v3/acinclude.m4 2025-08-25 18:08:44.358147732 +0300
+++ gcc-15.1.0-banan_os/libstdc++-v3/acinclude.m4 2025-06-19 11:34:58.939289470 +0300 +++ gcc-15.2.0-banan_os/libstdc++-v3/acinclude.m4 2025-08-25 18:09:09.241116556 +0300
@@ -1792,7 +1792,7 @@ @@ -1792,7 +1792,7 @@
ac_has_nanosleep=yes ac_has_nanosleep=yes
ac_has_sched_yield=yes ac_has_sched_yield=yes
@ -173,10 +173,10 @@ diff -ruN gcc-15.1.0/libstdc++-v3/acinclude.m4 gcc-15.1.0-banan_os/libstdc++-v3/
ac_has_clock_monotonic=yes ac_has_clock_monotonic=yes
ac_has_clock_realtime=yes ac_has_clock_realtime=yes
ac_has_nanosleep=yes ac_has_nanosleep=yes
diff -ruN gcc-15.1.0/libstdc++-v3/configure gcc-15.1.0-banan_os/libstdc++-v3/configure diff -ruN gcc-15.2.0/libstdc++-v3/configure gcc-15.2.0-banan_os/libstdc++-v3/configure
--- gcc-15.1.0/libstdc++-v3/configure 2025-04-25 11:18:05.000000000 +0300 --- gcc-15.2.0/libstdc++-v3/configure 2025-08-25 18:08:47.550144038 +0300
+++ gcc-15.1.0-banan_os/libstdc++-v3/configure 2025-06-19 11:37:41.265102481 +0300 +++ gcc-15.2.0-banan_os/libstdc++-v3/configure 2025-08-25 18:09:09.262116528 +0300
@@ -15789,8 +15789,8 @@ if test "$enable_shared" = yes; then @@ -15784,8 +15784,8 @@
glibcxx_compiler_shared_flag="-D_GLIBCXX_SHARED" glibcxx_compiler_shared_flag="-D_GLIBCXX_SHARED"
else else
@ -205,9 +205,9 @@ diff -ruN gcc-15.1.0/libstdc++-v3/configure gcc-15.1.0-banan_os/libstdc++-v3/con
$as_echo "#define HAVE_ACOSF 1" >>confdefs.h $as_echo "#define HAVE_ACOSF 1" >>confdefs.h
$as_echo "#define HAVE_ASINF 1" >>confdefs.h $as_echo "#define HAVE_ASINF 1" >>confdefs.h
diff -ruN gcc-15.1.0/libstdc++-v3/crossconfig.m4 gcc-15.1.0-banan_os/libstdc++-v3/crossconfig.m4 diff -ruN gcc-15.2.0/libstdc++-v3/crossconfig.m4 gcc-15.2.0-banan_os/libstdc++-v3/crossconfig.m4
--- gcc-15.1.0/libstdc++-v3/crossconfig.m4 2025-04-25 11:18:05.000000000 +0300 --- gcc-15.2.0/libstdc++-v3/crossconfig.m4 2025-08-25 18:08:47.570807934 +0300
+++ gcc-15.1.0-banan_os/libstdc++-v3/crossconfig.m4 2025-06-19 11:36:53.954449540 +0300 +++ gcc-15.2.0-banan_os/libstdc++-v3/crossconfig.m4 2025-08-25 18:09:09.263116526 +0300
@@ -9,7 +9,7 @@ @@ -9,7 +9,7 @@
# This is a freestanding configuration; there is nothing to do here. # This is a freestanding configuration; there is nothing to do here.
;; ;;

View File

@ -48,7 +48,7 @@ sigsetjmp:
subq $8, %rsp subq $8, %rsp
movq %rdi, (%rsp) movq %rdi, (%rsp)
leaq 72(%rsi), %rdx leaq 72(%rdi), %rdx
xorq %rsi, %rsi xorq %rsi, %rsi
call pthread_sigmask call pthread_sigmask
movq (%rsp), %rdi movq (%rsp), %rdi

View File

@ -34,11 +34,7 @@ struct FILE
unsigned char unget_buffer[12]; unsigned char unget_buffer[12];
uint32_t unget_buf_idx; uint32_t unget_buf_idx;
// TODO: use recursive pthread_mutex when implemented? pthread_mutex_t mutex;
// this storage hack is to keep FILE pod (init order)
BAN::Atomic<pthread_t>& locker() { return *reinterpret_cast<BAN::Atomic<pthread_t>*>(locker_storage); }
unsigned char locker_storage[sizeof(pthread_t)];
uint32_t lock_depth;
}; };
static_assert(BAN::is_pod_v<FILE>); static_assert(BAN::is_pod_v<FILE>);
@ -98,9 +94,11 @@ static void _init_stdio()
{ {
init_closed_file(&s_files[i]); init_closed_file(&s_files[i]);
new (&s_files[i].locker()) BAN::Atomic<pthread_t>(); pthread_mutexattr_t attr;
s_files[i].locker() = -1; pthread_mutexattr_init(&attr);
s_files[i].lock_depth = 0; pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&s_files[i].mutex, &attr);
pthread_mutexattr_destroy(&attr);
} }
s_files[STDIN_FILENO].fd = STDIN_FILENO; s_files[STDIN_FILENO].fd = STDIN_FILENO;
@ -313,22 +311,6 @@ int fileno(FILE* fp)
return fp->fd; return fp->fd;
} }
void flockfile(FILE* fp)
{
const pthread_t tid = pthread_self();
pthread_t expected = -1;
while (!fp->locker().compare_exchange(expected, tid, BAN::MemoryOrder::memory_order_acq_rel))
{
if (expected == tid)
break;
sched_yield();
expected = -1;
}
fp->lock_depth++;
}
FILE* fopen(const char* pathname, const char* mode_str) FILE* fopen(const char* pathname, const char* mode_str)
{ {
mode_t mode = parse_mode_string(mode_str); mode_t mode = parse_mode_string(mode_str);
@ -485,25 +467,19 @@ off_t ftello(FILE* file)
return offset - file->unget_buf_idx; return offset - file->unget_buf_idx;
} }
void flockfile(FILE* fp)
{
pthread_mutex_lock(&fp->mutex);
}
int ftrylockfile(FILE* fp) int ftrylockfile(FILE* fp)
{ {
const pthread_t tid = pthread_self(); return pthread_mutex_trylock(&fp->mutex);
pthread_t expected = -1;
if (!fp->locker().compare_exchange(expected, tid, BAN::MemoryOrder::memory_order_acq_rel))
if (expected != tid)
return 1;
fp->lock_depth++;
return 0;
} }
void funlockfile(FILE* fp) void funlockfile(FILE* fp)
{ {
ASSERT(fp->locker() == pthread_self()); pthread_mutex_unlock(&fp->mutex);
ASSERT(fp->lock_depth > 0);
if (--fp->lock_depth == 0)
fp->locker().store(-1, BAN::MemoryOrder::memory_order_release);
} }
size_t fwrite(const void* buffer, size_t size, size_t nitems, FILE* file) size_t fwrite(const void* buffer, size_t size, size_t nitems, FILE* file)
@ -803,11 +779,17 @@ int putc_unlocked(int c, FILE* file)
return (unsigned char)c; return (unsigned char)c;
} }
if (file->buffer_idx >= file->buffer_size)
if (fflush(file) == EOF)
return EOF;
file->buffer[file->buffer_idx] = c; file->buffer[file->buffer_idx] = c;
file->buffer_idx++; file->buffer_idx++;
if ((file->buffer_type == _IOLBF && c == '\n') || file->buffer_idx >= file->buffer_size) if ((file->buffer_type == _IOLBF && c == '\n') || file->buffer_idx >= file->buffer_size)
if (fflush(file) == EOF) if (fflush(file) == EOF)
return EOF; return EOF;
return (unsigned char)c; return (unsigned char)c;
} }
@ -875,6 +857,9 @@ int rename(const char* old, const char* _new)
} }
} }
close(new_fd);
close(old_fd);
unlink(old); unlink(old);
return 0; return 0;

View File

@ -27,6 +27,8 @@ static BAN::ErrorOr<long long> read_integer_from_file(const char* file)
static BAN::String get_battery_percentage() static BAN::String get_battery_percentage()
{ {
DIR* dirp = opendir("/dev/batteries"); DIR* dirp = opendir("/dev/batteries");
if (dirp == nullptr)
return {};
BAN::String result; BAN::String result;
while (dirent* dirent = readdir(dirp)) while (dirent* dirent = readdir(dirp))
@ -53,6 +55,8 @@ static BAN::String get_battery_percentage()
(void)result.append(string.value()); (void)result.append(string.value());
} }
closedir(dirp);
return result; return result;
} }