diff options
author | Andreas Kling <awesomekling@gmail.com> | 2019-01-18 15:01:40 +0100 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-01-18 15:01:40 +0100 |
commit | f7cc4541626279b07626b9d98beba03a7230b518 (patch) | |
tree | 3aaebc55d63a16825b27d70160316b7d1e86c735 /Kernel | |
parent | 9454c5dd5254c9cd75b1b039da0cadb8c020ae38 (diff) | |
download | serenity-f7cc4541626279b07626b9d98beba03a7230b518.zip |
Add mechanism to expose kernel variables to userspace via ProcFS.
Only booleans are supported at first. More types can be added easily.
Use this to add /proc/sys/wm_flash_flush which when enabled flashes pending
screen flush rects in yellow before they happen.
Diffstat (limited to 'Kernel')
-rw-r--r-- | Kernel/MemoryManager.h | 3 | ||||
-rw-r--r-- | Kernel/ProcFileSystem.cpp | 78 | ||||
-rw-r--r-- | Kernel/ProcFileSystem.h | 5 |
3 files changed, 72 insertions, 14 deletions
diff --git a/Kernel/MemoryManager.h b/Kernel/MemoryManager.h index cd82206966..17b99fcfe1 100644 --- a/Kernel/MemoryManager.h +++ b/Kernel/MemoryManager.h @@ -15,6 +15,7 @@ class Process; extern Process* current; +class SynthFSInode; enum class PageFaultResponse { ShouldCrash, @@ -166,7 +167,7 @@ class MemoryManager { friend class PhysicalPage; friend class Region; friend class VMObject; - friend ByteBuffer procfs$mm(); + friend ByteBuffer procfs$mm(SynthFSInode&); public: static MemoryManager& the() PURE; diff --git a/Kernel/ProcFileSystem.cpp b/Kernel/ProcFileSystem.cpp index 7c2293df32..37d0b0d2e0 100644 --- a/Kernel/ProcFileSystem.cpp +++ b/Kernel/ProcFileSystem.cpp @@ -156,15 +156,15 @@ void ProcFS::add_process(Process& process) ksprintf(buf, "%d", process.pid()); auto dir = add_file(create_directory(buf)); m_pid2inode.set(process.pid(), dir.index()); - add_file(create_generated_file("vm", [&process] { return procfs$pid_vm(process); }), dir.index()); - add_file(create_generated_file("vmo", [&process] { return procfs$pid_vmo(process); }), dir.index()); - add_file(create_generated_file("stack", [&process] { return procfs$pid_stack(process); }), dir.index()); - add_file(create_generated_file("regs", [&process] { return procfs$pid_regs(process); }), dir.index()); - add_file(create_generated_file("fds", [&process] { return procfs$pid_fds(process); }), dir.index()); + add_file(create_generated_file("vm", [&process] (SynthFSInode&) { return procfs$pid_vm(process); }), dir.index()); + add_file(create_generated_file("vmo", [&process] (SynthFSInode&) { return procfs$pid_vmo(process); }), dir.index()); + add_file(create_generated_file("stack", [&process] (SynthFSInode&) { return procfs$pid_stack(process); }), dir.index()); + add_file(create_generated_file("regs", [&process] (SynthFSInode&) { return procfs$pid_regs(process); }), dir.index()); + add_file(create_generated_file("fds", [&process] (SynthFSInode&) { return procfs$pid_fds(process); }), dir.index()); if (process.executable_inode()) - add_file(create_generated_file("exe", [&process] { return procfs$pid_exe(process); }, 00120777), dir.index()); + add_file(create_generated_file("exe", [&process] (SynthFSInode&) { return procfs$pid_exe(process); }, 00120777), dir.index()); if (process.cwd_inode()) - add_file(create_generated_file("cwd", [&process] { return procfs$pid_cwd(process); }, 00120777), dir.index()); + add_file(create_generated_file("cwd", [&process] (SynthFSInode&) { return procfs$pid_cwd(process); }, 00120777), dir.index()); } void ProcFS::remove_process(Process& process) @@ -179,7 +179,7 @@ void ProcFS::remove_process(Process& process) m_pid2inode.remove(pid); } -ByteBuffer procfs$mm() +ByteBuffer procfs$mm(SynthFSInode&) { // FIXME: Implement InterruptDisabler disabler; @@ -198,7 +198,7 @@ ByteBuffer procfs$mm() return builder.to_byte_buffer(); } -ByteBuffer procfs$mounts() +ByteBuffer procfs$mounts(SynthFSInode&) { InterruptDisabler disabler; StringBuilder builder; @@ -213,7 +213,7 @@ ByteBuffer procfs$mounts() return builder.to_byte_buffer(); } -ByteBuffer procfs$cpuinfo() +ByteBuffer procfs$cpuinfo(SynthFSInode&) { StringBuilder builder; { @@ -276,7 +276,7 @@ ByteBuffer procfs$cpuinfo() return builder.to_byte_buffer(); } -ByteBuffer procfs$kmalloc() +ByteBuffer procfs$kmalloc(SynthFSInode&) { StringBuilder builder; builder.appendf( @@ -290,7 +290,7 @@ ByteBuffer procfs$kmalloc() return builder.to_byte_buffer(); } -ByteBuffer procfs$summary() +ByteBuffer procfs$summary(SynthFSInode&) { InterruptDisabler disabler; auto processes = Process::allProcesses(); @@ -313,7 +313,7 @@ ByteBuffer procfs$summary() return builder.to_byte_buffer(); } -ByteBuffer procfs$inodes() +ByteBuffer procfs$inodes(SynthFSInode&) { extern HashTable<Inode*>& all_inodes(); auto& vfs = VFS::the(); @@ -326,6 +326,57 @@ ByteBuffer procfs$inodes() return builder.to_byte_buffer(); } +struct SysVariableData final : public SynthFSInodeCustomData { + virtual ~SysVariableData() override { } + + enum Type { + Invalid, + Boolean, + }; + Type type { Invalid }; + Function<void()> change_callback; + void* address; +}; + +static ByteBuffer read_sys_bool(SynthFSInode& inode) +{ + ASSERT(inode.custom_data()); + auto buffer = ByteBuffer::create_uninitialized(2); + auto& custom_data = *static_cast<const SysVariableData*>(inode.custom_data()); + ASSERT(custom_data.type == SysVariableData::Boolean); + ASSERT(custom_data.address); + buffer[0] = *reinterpret_cast<bool*>(custom_data.address) ? '1' : '0'; + buffer[1] = '\n'; + return buffer; +} + +static ssize_t write_sys_bool(SynthFSInode& inode, const ByteBuffer& data) +{ + ASSERT(inode.custom_data()); + if (data.size() >= 1 && (data[0] == '0' || data[0] == '1')) { + auto& custom_data = *static_cast<const SysVariableData*>(inode.custom_data()); + ASSERT(custom_data.address); + bool old_value = *reinterpret_cast<bool*>(custom_data.address); + bool new_value = data[0] == '1'; + *reinterpret_cast<bool*>(custom_data.address) = new_value; + if (old_value != new_value && custom_data.change_callback) + custom_data.change_callback(); + } + return data.size(); +} + +void ProcFS::add_sys_bool(String&& name, bool* var, Function<void()>&& change_callback) +{ + auto file = create_generated_file(move(name), move(read_sys_bool), move(write_sys_bool)); + auto data = make<SysVariableData>(); + data->type = SysVariableData::Boolean; + data->change_callback = move(change_callback); + data->address = var; + file->set_custom_data(move(data)); + InterruptDisabler disabler; + add_file(move(file), m_sys_dir.index()); +} + bool ProcFS::initialize() { SynthFS::initialize(); @@ -335,6 +386,7 @@ bool ProcFS::initialize() add_file(create_generated_file("summary", procfs$summary)); add_file(create_generated_file("cpuinfo", procfs$cpuinfo)); add_file(create_generated_file("inodes", procfs$inodes)); + m_sys_dir = add_file(create_directory("sys")); return true; } diff --git a/Kernel/ProcFileSystem.h b/Kernel/ProcFileSystem.h index 5f6aa061d1..3b0050556f 100644 --- a/Kernel/ProcFileSystem.h +++ b/Kernel/ProcFileSystem.h @@ -18,9 +18,14 @@ public: void add_process(Process&); void remove_process(Process&); + void add_sys_file(String&&, Function<ByteBuffer(SynthFSInode&)>&& read_callback, Function<ssize_t(SynthFSInode&, const ByteBuffer&)>&& write_callback); + + void add_sys_bool(String&&, bool*, Function<void()>&& change_callback = nullptr); + private: ProcFS(); HashMap<pid_t, InodeIndex> m_pid2inode; + InodeIdentifier m_sys_dir; }; |