diff --git a/AK/Lock.h b/AK/Lock.h index cc9bc5ff1a..da5a2e1de9 100644 --- a/AK/Lock.h +++ b/AK/Lock.h @@ -103,6 +103,12 @@ public: Lock& lock() { return m_lock; } T& resource() { return m_resource; } + T lock_and_copy() + { + LOCKER(m_lock); + return m_resource; + } + private: T m_resource; Lock m_lock; diff --git a/Kernel/ProcFS.cpp b/Kernel/ProcFS.cpp index a45dd3b0ef..e8a51f978b 100644 --- a/Kernel/ProcFS.cpp +++ b/Kernel/ProcFS.cpp @@ -560,7 +560,11 @@ static ByteBuffer read_sys_bool(InodeIdentifier inode_id) 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'; + auto* lockable_bool = reinterpret_cast*>(custom_data.address); + { + LOCKER(lockable_bool->lock()); + buffer[0] = lockable_bool->resource() ? '1' : '0'; + } buffer[1] = '\n'; return buffer; } @@ -572,14 +576,17 @@ static ssize_t write_sys_bool(InodeIdentifier inode_id, const ByteBuffer& data) return { }; auto& inode = static_cast(*inode_ptr); 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 new_value = data[0] == '1'; - *reinterpret_cast(custom_data.address) = new_value; - if (custom_data.notify_callback) - custom_data.notify_callback(); + if (data.is_empty() || !(data[0] == '0' || data[0] == '1')) + return data.size(); + + auto& custom_data = *static_cast(inode.custom_data()); + auto* lockable_bool = reinterpret_cast*>(custom_data.address); + { + LOCKER(lockable_bool->lock()); + lockable_bool->resource() = data[0] == '1'; } + if (custom_data.notify_callback) + custom_data.notify_callback(); return data.size(); } @@ -618,7 +625,7 @@ static ssize_t write_sys_string(InodeIdentifier inode_id, const ByteBuffer& data return data.size(); } -void ProcFS::add_sys_bool(String&& name, bool* var, Function&& notify_callback) +void ProcFS::add_sys_bool(String&& name, Lockable& var, Function&& notify_callback) { InterruptDisabler disabler; @@ -627,7 +634,7 @@ void ProcFS::add_sys_bool(String&& name, bool* var, Function&& notify_ca auto data = make(); data->type = SysVariableData::Boolean; data->notify_callback = move(notify_callback); - data->address = var; + data->address = &var; inode->set_custom_data(move(data)); m_sys_entries.append({ strdup(name.characters()), name.length(), read_sys_bool, write_sys_bool, move(inode) }); } diff --git a/Kernel/ProcFS.h b/Kernel/ProcFS.h index f2cd53b176..9c5591bff0 100644 --- a/Kernel/ProcFS.h +++ b/Kernel/ProcFS.h @@ -26,7 +26,7 @@ public: virtual RetainPtr create_directory(InodeIdentifier parent_id, const String& name, mode_t, int& error) override; void add_sys_file(String&&, Function&& read_callback, Function&& write_callback); - void add_sys_bool(String&&, bool*, Function&& notify_callback = nullptr); + void add_sys_bool(String&&, Lockable&, Function&& notify_callback = nullptr); void add_sys_string(String&&, Lockable&, Function&& notify_callback = nullptr); private: diff --git a/WindowServer/WSWindowManager.cpp b/WindowServer/WSWindowManager.cpp index 26de830a28..7919f4727d 100644 --- a/WindowServer/WSWindowManager.cpp +++ b/WindowServer/WSWindowManager.cpp @@ -131,6 +131,7 @@ WSWindowManager::WSWindowManager() : m_screen(WSScreen::the()) , m_screen_rect(m_screen.rect()) , m_lock("WSWindowManager") + , m_flash_flush(false) { #ifndef DEBUG_COUNTERS (void)m_compose_count; @@ -168,7 +169,7 @@ WSWindowManager::WSWindowManager() m_wallpaper = GraphicsBitmap::load_from_file(m_wallpaper_path.resource(), m_screen_rect.size()); } - ProcFS::the().add_sys_bool("wm_flash_flush", &m_flash_flush); + ProcFS::the().add_sys_bool("wm_flash_flush", m_flash_flush); ProcFS::the().add_sys_string("wm_wallpaper", m_wallpaper_path, [this] { LOCKER(m_wallpaper_path.lock()); m_wallpaper = GraphicsBitmap::load_from_file(m_wallpaper_path.resource(), m_screen_rect.size()); @@ -441,7 +442,6 @@ void WSWindowManager::compose() if (any_window_contains_rect(dirty_rect)) { continue; } - //dbgprintf("Repaint root %d,%d %dx%d\n", dirty_rect.x(), dirty_rect.y(), dirty_rect.width(), dirty_rect.height()); LOCKER(m_wallpaper_path.lock()); if (!m_wallpaper) m_back_painter->fill_rect(dirty_rect, m_background_color); @@ -472,7 +472,8 @@ void WSWindowManager::compose() } draw_cursor(); - if (m_flash_flush) { + + if (m_flash_flush.lock_and_copy()) { for (auto& rect : dirty_rects) m_front_painter->fill_rect(rect, Color::Yellow); } diff --git a/WindowServer/WSWindowManager.h b/WindowServer/WSWindowManager.h index 1c9b547263..18e32fcfff 100644 --- a/WindowServer/WSWindowManager.h +++ b/WindowServer/WSWindowManager.h @@ -110,6 +110,6 @@ private: mutable Lock m_lock; - bool m_flash_flush { false }; + Lockable m_flash_flush; bool m_buffers_are_flipped { false }; };