diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index e051d1ed13..5b143240e3 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -2408,7 +2408,7 @@ int Process::sys$create_shared_buffer(int size, void** buffer) int shared_buffer_id = ++s_next_shared_buffer_id; auto shared_buffer = make(shared_buffer_id, size); shared_buffer->share_with(m_pid); - *buffer = shared_buffer->get_address(*this); + *buffer = shared_buffer->ref_for_process_and_get_address(*this); ASSERT((int)shared_buffer->size() >= size); #ifdef SHARED_BUFFER_DEBUG kprintf("%s(%u): Created shared buffer %d @ %p (%u bytes, vmo is %u)\n", name().characters(), pid(), shared_buffer_id, *buffer, size, shared_buffer->size()); @@ -2447,7 +2447,7 @@ int Process::sys$release_shared_buffer(int shared_buffer_id) #ifdef SHARED_BUFFER_DEBUG kprintf("%s(%u): Releasing shared buffer %d, buffer count: %u\n", name().characters(), pid(), shared_buffer_id, shared_buffers().resource().size()); #endif - shared_buffer.release(*this); + shared_buffer.deref_for_process(*this); return 0; } @@ -2463,7 +2463,7 @@ void* Process::sys$get_shared_buffer(int shared_buffer_id) #ifdef SHARED_BUFFER_DEBUG kprintf("%s(%u): Retaining shared buffer %d, buffer count: %u\n", name().characters(), pid(), shared_buffer_id, shared_buffers().resource().size()); #endif - return shared_buffer.get_address(*this); + return shared_buffer.ref_for_process_and_get_address(*this); } int Process::sys$seal_shared_buffer(int shared_buffer_id) diff --git a/Kernel/SharedBuffer.cpp b/Kernel/SharedBuffer.cpp index c5574f12df..a082555bae 100644 --- a/Kernel/SharedBuffer.cpp +++ b/Kernel/SharedBuffer.cpp @@ -21,12 +21,14 @@ bool SharedBuffer::is_shared_with(pid_t peer_pid) return false; } -void* SharedBuffer::get_address(Process& process) +void* SharedBuffer::ref_for_process_and_get_address(Process& process) { LOCKER(shared_buffers().lock()); ASSERT(is_shared_with(process.pid())); for (auto& ref : m_refs) { if (ref.pid == process.pid()) { + ref.count++; + m_total_refs++; if (ref.region == nullptr) { ref.region = process.allocate_region_with_vmo(VirtualAddress(), size(), m_vmo, 0, "SharedBuffer", PROT_READ | (m_writable ? PROT_WRITE : 0)); ref.region->set_shared(true); @@ -42,7 +44,7 @@ void SharedBuffer::share_with(pid_t peer_pid) LOCKER(shared_buffers().lock()); for (auto& ref : m_refs) { if (ref.pid == peer_pid) { - ref.count++; + // don't increment the reference count yet; let them get_shared_buffer it first. return; } } @@ -50,7 +52,7 @@ void SharedBuffer::share_with(pid_t peer_pid) m_refs.append(Reference(peer_pid)); } -void SharedBuffer::release(Process& process) +void SharedBuffer::deref_for_process(Process& process) { LOCKER(shared_buffers().lock()); for (int i = 0; i < m_refs.size(); ++i) { @@ -94,7 +96,7 @@ void SharedBuffer::disown(pid_t pid) void SharedBuffer::destroy_if_unused() { LOCKER(shared_buffers().lock()); - if (m_refs.size() == 0) { + if (m_total_refs == 0) { #ifdef SHARED_BUFFER_DEBUG kprintf("Destroying unused SharedBuffer{%p} id: %d\n", this, m_shared_buffer_id); #endif diff --git a/Kernel/SharedBuffer.h b/Kernel/SharedBuffer.h index c2187f1068..c2d4d05ec5 100644 --- a/Kernel/SharedBuffer.h +++ b/Kernel/SharedBuffer.h @@ -12,7 +12,7 @@ private: } pid_t pid; - unsigned count { 1 }; + unsigned count { 0 }; Region* region { nullptr }; }; public: @@ -33,9 +33,9 @@ public: } bool is_shared_with(pid_t peer_pid); - void* get_address(Process& process); + void* ref_for_process_and_get_address(Process& process); void share_with(pid_t peer_pid); - void release(Process& process); + void deref_for_process(Process& process); void disown(pid_t pid); size_t size() const { return m_vmo->size(); } void destroy_if_unused(); @@ -45,6 +45,7 @@ public: bool m_writable { true }; NonnullRefPtr m_vmo; Vector m_refs; + unsigned m_total_refs { 0 }; }; Lockable>>& shared_buffers();