diff --git a/kernel/include/kernel/FS/ProcFS/Inode.h b/kernel/include/kernel/FS/ProcFS/Inode.h index 87226ba9..a71164c4 100644 --- a/kernel/include/kernel/FS/ProcFS/Inode.h +++ b/kernel/include/kernel/FS/ProcFS/Inode.h @@ -20,4 +20,25 @@ namespace Kernel Process& m_process; }; + class ProcMemInode final : public RamInode + { + public: + static BAN::ErrorOr> create(Process&, RamFileSystem&, mode_t, uid_t, gid_t); + ~ProcMemInode() = default; + + protected: + virtual BAN::ErrorOr read_impl(off_t, void*, size_t) override; + + // You may not write here and this is always non blocking + virtual BAN::ErrorOr write_impl(off_t, const void*, size_t) override { return BAN::Error::from_errno(EINVAL); } + virtual BAN::ErrorOr truncate_impl(size_t) override { return BAN::Error::from_errno(EINVAL); } + virtual bool has_data_impl() const override { return true; } + + private: + ProcMemInode(Process&, RamFileSystem&, const FullInodeInfo&); + + private: + Process& m_process; + }; + } diff --git a/kernel/include/kernel/Process.h b/kernel/include/kernel/Process.h index 6e7b04bc..625d34c6 100644 --- a/kernel/include/kernel/Process.h +++ b/kernel/include/kernel/Process.h @@ -13,6 +13,7 @@ #include #include +#include #include #include @@ -138,6 +139,8 @@ namespace Kernel PageTable& page_table() { return m_page_table ? *m_page_table : PageTable::kernel(); } + void get_meminfo(proc_meminfo_t*) const; + bool is_userspace() const { return m_is_userspace; } const userspace_info_t& userspace_info() const { return m_userspace_info; } diff --git a/kernel/kernel/FS/ProcFS/Inode.cpp b/kernel/kernel/FS/ProcFS/Inode.cpp index 6fccc23b..fdba47e3 100644 --- a/kernel/kernel/FS/ProcFS/Inode.cpp +++ b/kernel/kernel/FS/ProcFS/Inode.cpp @@ -23,4 +23,36 @@ namespace Kernel { } + BAN::ErrorOr> ProcMemInode::create(Process& process, RamFileSystem& fs, mode_t mode, uid_t uid, gid_t gid) + { + FullInodeInfo inode_info(fs, mode, uid, gid); + + auto* inode_ptr = new ProcMemInode(process, fs, inode_info); + if (inode_ptr == nullptr) + return BAN::Error::from_errno(ENOMEM); + return BAN::RefPtr::adopt(inode_ptr); + } + + ProcMemInode::ProcMemInode(Process& process, RamFileSystem& fs, const FullInodeInfo& inode_info) + : RamInode(fs, inode_info) + , m_process(process) + { + m_inode_info.mode |= Inode::Mode::IFREG; + } + + BAN::ErrorOr ProcMemInode::read_impl(off_t offset, void* buffer, size_t buffer_size) + { + ASSERT(offset >= 0); + if ((size_t)offset >= sizeof(proc_meminfo_t)) + return 0; + + proc_meminfo_t meminfo; + m_process.get_meminfo(&meminfo); + + size_t bytes = BAN::Math::min(buffer_size, sizeof(meminfo) - offset); + memcpy(buffer, &meminfo, bytes); + + return bytes; + } + } diff --git a/kernel/kernel/Process.cpp b/kernel/kernel/Process.cpp index 1ca4b213..7e237b9a 100644 --- a/kernel/kernel/Process.cpp +++ b/kernel/kernel/Process.cpp @@ -252,6 +252,21 @@ namespace Kernel thread->set_terminating(); } + void Process::get_meminfo(proc_meminfo_t* out) const + { + LockGuard _(m_lock); + + out->page_size = PAGE_SIZE; + + out->virt_pages = 0; + for (auto* thread : m_threads) + out->virt_pages += thread->virtual_page_count(); + for (auto& region : m_mapped_regions) + out->virt_pages += region->virtual_page_count(); + if (m_loadable_elf) + out->virt_pages += m_loadable_elf->virtual_page_count(); + } + BAN::ErrorOr Process::sys_exit(int status) { exit(status, 0); diff --git a/libc/include/sys/banan-os.h b/libc/include/sys/banan-os.h index 08fe6a38..f514f829 100644 --- a/libc/include/sys/banan-os.h +++ b/libc/include/sys/banan-os.h @@ -5,6 +5,9 @@ __BEGIN_DECLS +#define __need_size_t 1 +#include + #define TTY_CMD_SET 0x01 #define TTY_CMD_UNSET 0x02 @@ -14,6 +17,12 @@ __BEGIN_DECLS #define POWEROFF_SHUTDOWN 0 #define POWEROFF_REBOOT 1 +struct proc_meminfo_t +{ + size_t page_size; + size_t virt_pages; +}; + /* fildes: refers to valid tty device command: one of TTY_CMD_* definitions