diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index ca8c6fbccb..83184cce94 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -2909,6 +2909,28 @@ int Process::sys$get_shared_buffer_size(int shared_buffer_id) return shared_buffer.size(); } +int Process::sys$set_shared_buffer_volatile(int shared_buffer_id, bool state) +{ + LOCKER(shared_buffers().lock()); + auto it = shared_buffers().resource().find(shared_buffer_id); + if (it == shared_buffers().resource().end()) + return -EINVAL; + auto& shared_buffer = *(*it).value; + if (!shared_buffer.is_shared_with(m_pid)) + return -EPERM; +#ifdef SHARED_BUFFER_DEBUG + kprintf("%s(%u): Set shared buffer %d volatile: %u\n", name().characters(), pid(), shared_buffer_id, state); +#endif + if (!state) { + bool was_purged = shared_buffer.vmobject().was_purged(); + shared_buffer.vmobject().set_volatile(state); + shared_buffer.vmobject().set_was_purged(false); + return was_purged ? 1 : 0; + } + shared_buffer.vmobject().set_volatile(true); + return 0; +} + void Process::terminate_due_to_signal(u8 signal) { ASSERT_INTERRUPTS_DISABLED(); diff --git a/Kernel/Process.h b/Kernel/Process.h index e7e2a08782..53e3974dc3 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -219,6 +219,7 @@ public: int sys$release_shared_buffer(int shared_buffer_id); int sys$seal_shared_buffer(int shared_buffer_id); int sys$get_shared_buffer_size(int shared_buffer_id); + int sys$set_shared_buffer_volatile(int shared_buffer_id, bool); int sys$halt(); int sys$reboot(); int sys$set_process_icon(int icon_id); diff --git a/Kernel/SharedBuffer.h b/Kernel/SharedBuffer.h index b690c34be1..75d573b227 100644 --- a/Kernel/SharedBuffer.h +++ b/Kernel/SharedBuffer.h @@ -1,8 +1,8 @@ #pragma once #include -#include #include +#include struct SharedBuffer { private: @@ -20,7 +20,7 @@ private: public: SharedBuffer(int id, int size) : m_shared_buffer_id(id) - , m_vmobject(AnonymousVMObject::create_with_size(size)) + , m_vmobject(PurgeableVMObject::create_with_size(size)) { #ifdef SHARED_BUFFER_DEBUG dbgprintf("Created shared buffer %d of size %d\n", m_shared_buffer_id, size); @@ -44,12 +44,14 @@ public: size_t size() const { return m_vmobject->size(); } void destroy_if_unused(); void seal(); + PurgeableVMObject& vmobject() { return m_vmobject; } + const PurgeableVMObject& vmobject() const { return m_vmobject; } int id() const { return m_shared_buffer_id; } int m_shared_buffer_id { -1 }; bool m_writable { true }; bool m_global { false }; - NonnullRefPtr m_vmobject; + NonnullRefPtr m_vmobject; Vector m_refs; unsigned m_total_refs { 0 }; }; diff --git a/Kernel/Syscall.h b/Kernel/Syscall.h index a7db981c4c..fe8de7babf 100644 --- a/Kernel/Syscall.h +++ b/Kernel/Syscall.h @@ -146,7 +146,8 @@ typedef u32 socklen_t; __ENUMERATE_SYSCALL(set_thread_name) \ __ENUMERATE_SYSCALL(get_thread_name) \ __ENUMERATE_SYSCALL(madvise) \ - __ENUMERATE_SYSCALL(purge) + __ENUMERATE_SYSCALL(purge) \ + __ENUMERATE_SYSCALL(set_shared_buffer_volatile) namespace Syscall { diff --git a/Libraries/LibC/SharedBuffer.cpp b/Libraries/LibC/SharedBuffer.cpp index 1a0c3a9701..30fff21a46 100644 --- a/Libraries/LibC/SharedBuffer.cpp +++ b/Libraries/LibC/SharedBuffer.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -64,3 +65,19 @@ void SharedBuffer::seal() ASSERT_NOT_REACHED(); } } + +void SharedBuffer::set_volatile() +{ + u32 rc = syscall(SC_set_shared_buffer_volatile, m_shared_buffer_id, true); + ASSERT(rc == 0); +} + +bool SharedBuffer::set_nonvolatile() +{ + u32 rc = syscall(SC_set_shared_buffer_volatile, m_shared_buffer_id, false); + if (rc == 0) + return true; + if (rc == 1) + return false; + ASSERT_NOT_REACHED(); +} diff --git a/Libraries/LibC/SharedBuffer.h b/Libraries/LibC/SharedBuffer.h index 2d1cdfc423..e79abad00b 100644 --- a/Libraries/LibC/SharedBuffer.h +++ b/Libraries/LibC/SharedBuffer.h @@ -1,7 +1,7 @@ #pragma once -#include #include +#include class SharedBuffer : public RefCounted { public: @@ -15,6 +15,8 @@ public: int size() const { return m_size; } void* data() { return m_data; } const void* data() const { return m_data; } + void set_volatile(); + [[nodiscard]] bool set_nonvolatile(); private: SharedBuffer(int shared_buffer_id, int size, void*);