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& 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 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(inode.custom_data()); + ASSERT(custom_data.type == SysVariableData::Boolean); + ASSERT(custom_data.address); + buffer[0] = *reinterpret_cast(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(inode.custom_data()); + ASSERT(custom_data.address); + bool old_value = *reinterpret_cast(custom_data.address); + bool new_value = data[0] == '1'; + *reinterpret_cast(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&& change_callback) +{ + auto file = create_generated_file(move(name), move(read_sys_bool), move(write_sys_bool)); + auto data = make(); + 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&& read_callback, Function&& write_callback); + + void add_sys_bool(String&&, bool*, Function&& change_callback = nullptr); + private: ProcFS(); HashMap m_pid2inode; + InodeIdentifier m_sys_dir; }; diff --git a/VirtualFileSystem/FileDescriptor.cpp b/VirtualFileSystem/FileDescriptor.cpp index 60f89cda17..6b20ee8ef9 100644 --- a/VirtualFileSystem/FileDescriptor.cpp +++ b/VirtualFileSystem/FileDescriptor.cpp @@ -167,9 +167,10 @@ ssize_t FileDescriptor::write(Process& process, const byte* data, size_t size) // FIXME: What should happen to m_currentOffset? return m_device->write(process, data, size); } - // FIXME: Implement non-device writes. - ASSERT_NOT_REACHED(); - return -1; + ASSERT(m_inode); + ssize_t nwritten = m_inode->write(ByteBuffer::wrap((byte*)data, size)); + m_current_offset += nwritten; + return nwritten; } bool FileDescriptor::can_write(Process& process) diff --git a/VirtualFileSystem/SyntheticFileSystem.cpp b/VirtualFileSystem/SyntheticFileSystem.cpp index b3afec2445..a0cdb29740 100644 --- a/VirtualFileSystem/SyntheticFileSystem.cpp +++ b/VirtualFileSystem/SyntheticFileSystem.cpp @@ -69,7 +69,7 @@ RetainPtr SynthFS::create_text_file(String&& name, ByteBuffer&& co return file; } -RetainPtr SynthFS::create_generated_file(String&& name, Function&& generator, Unix::mode_t mode) +RetainPtr SynthFS::create_generated_file(String&& name, Function&& generator, Unix::mode_t mode) { auto file = adopt(*new SynthFSInode(*this, generate_inode_index())); file->m_generator = move(generator); @@ -82,6 +82,20 @@ RetainPtr SynthFS::create_generated_file(String&& name, Function SynthFS::create_generated_file(String&& name, Function&& read_callback, Function&& write_callback, Unix::mode_t mode) +{ + auto file = adopt(*new SynthFSInode(*this, generate_inode_index())); + file->m_generator = move(read_callback); + file->m_write_callback = move(write_callback); + file->m_name = move(name); + file->m_metadata.size = 0; + file->m_metadata.uid = 0; + file->m_metadata.gid = 0; + file->m_metadata.mode = mode; + file->m_metadata.mtime = mepoch; + return file; +} + InodeIdentifier SynthFS::add_file(RetainPtr&& file, InodeIndex parent) { ASSERT_INTERRUPTS_DISABLED(); @@ -197,10 +211,10 @@ ssize_t SynthFSInode::read_bytes(Unix::off_t offset, size_t count, byte* buffer, ByteBuffer generatedData; if (m_generator) { if (!descriptor) { - generatedData = m_generator(); + generatedData = m_generator(*this); } else { if (!descriptor->generator_cache()) - descriptor->generator_cache() = m_generator(); + descriptor->generator_cache() = m_generator(*this); generatedData = descriptor->generator_cache(); } } @@ -259,10 +273,11 @@ void SynthFSInode::flush_metadata() { } -bool SynthFSInode::write(const ByteBuffer&) +bool SynthFSInode::write(const ByteBuffer& data) { - ASSERT_NOT_REACHED(); - return false; + if (!m_write_callback) + return 0; // FIXME: -EPERM? + return m_write_callback(*this, data); } bool SynthFSInode::add_child(InodeIdentifier child_id, const String& name, byte file_type, int& error) @@ -274,3 +289,7 @@ bool SynthFSInode::add_child(InodeIdentifier child_id, const String& name, byte ASSERT_NOT_REACHED(); return false; } + +SynthFSInodeCustomData::~SynthFSInodeCustomData() +{ +} diff --git a/VirtualFileSystem/SyntheticFileSystem.h b/VirtualFileSystem/SyntheticFileSystem.h index c1b43fdee1..ec440cd2e1 100644 --- a/VirtualFileSystem/SyntheticFileSystem.h +++ b/VirtualFileSystem/SyntheticFileSystem.h @@ -28,7 +28,8 @@ protected: RetainPtr create_directory(String&& name); RetainPtr create_text_file(String&& name, ByteBuffer&&, Unix::mode_t = 0010644); - RetainPtr create_generated_file(String&& name, Function&&, Unix::mode_t = 0100644); + RetainPtr create_generated_file(String&& name, Function&&, Unix::mode_t = 0100644); + RetainPtr create_generated_file(String&& name, Function&&, Function&&, Unix::mode_t = 0100644); InodeIdentifier add_file(RetainPtr&&, InodeIndex parent = RootInodeIndex); bool remove_file(InodeIndex); @@ -38,11 +39,19 @@ private: HashMap> m_inodes; }; +struct SynthFSInodeCustomData { + virtual ~SynthFSInodeCustomData(); +}; + class SynthFSInode final : public Inode { friend class SynthFS; public: virtual ~SynthFSInode() override; + void set_custom_data(OwnPtr&& custom_data) { m_custom_data = move(custom_data); } + SynthFSInodeCustomData* custom_data() { return m_custom_data.ptr(); } + const SynthFSInodeCustomData* custom_data() const { return m_custom_data.ptr(); } + private: // ^Inode virtual ssize_t read_bytes(Unix::off_t, size_t, byte* buffer, FileDescriptor*) override; @@ -62,9 +71,11 @@ private: String m_name; InodeIdentifier m_parent; ByteBuffer m_data; - Function m_generator; + Function m_generator; + Function m_write_callback; Vector m_children; InodeMetadata m_metadata; + OwnPtr m_custom_data; }; inline SynthFS& SynthFSInode::fs() diff --git a/WindowServer/WSWindowManager.cpp b/WindowServer/WSWindowManager.cpp index b5fd018610..21132c86f9 100644 --- a/WindowServer/WSWindowManager.cpp +++ b/WindowServer/WSWindowManager.cpp @@ -4,11 +4,11 @@ #include "WSEventLoop.h" #include "Process.h" #include "MemoryManager.h" +#include #include #include #include -//#define DEBUG_FLUSH_YELLOW //#define DEBUG_COUNTERS static const int windowTitleBarHeight = 16; @@ -130,6 +130,8 @@ WSWindowManager::WSWindowManager() m_cursor_bitmap_inner = CharacterBitmap::create_from_ascii(cursor_bitmap_inner_ascii, 12, 17); m_cursor_bitmap_outer = CharacterBitmap::create_from_ascii(cursor_bitmap_outer_ascii, 12, 17); + ProcFS::the().add_sys_bool("wm_flash_flush", &m_flash_flush); + invalidate(); compose(); } @@ -444,9 +446,8 @@ void WSWindowManager::flush(const Rect& a_rect) const RGBA32* back_ptr = m_back_bitmap->scanline(rect.y()) + rect.x(); size_t pitch = m_back_bitmap->pitch(); -#ifdef DEBUG_FLUSH_YELLOW - m_front_painter->fill_rect(rect, Color::Yellow); -#endif + if (m_flash_flush) + m_front_painter->fill_rect(rect, Color::Yellow); for (int y = 0; y < rect.height(); ++y) { fast_dword_copy(front_ptr, back_ptr, rect.width()); diff --git a/WindowServer/WSWindowManager.h b/WindowServer/WSWindowManager.h index 75d8c217c8..9df93d8515 100644 --- a/WindowServer/WSWindowManager.h +++ b/WindowServer/WSWindowManager.h @@ -94,4 +94,6 @@ private: OwnPtr m_front_painter; mutable Lock m_lock; + + bool m_flash_flush { false }; };