From f816abcbad4903a815612986fd9d8172bcb752c3 Mon Sep 17 00:00:00 2001 From: Brian Gianforcaro Date: Sun, 1 Aug 2021 01:40:07 -0700 Subject: [PATCH] Kernel: Add DoubleBuffer::try_create() factory method for OOM hardening We need to expose the ability for DoubleBuffer creation to expose failure, as DoubleBuffer depends on KBuffer, which also has to be able to expose failure during OOM. We will remove the non OOM API once all users have been converted. --- Kernel/DoubleBuffer.cpp | 28 +++++++++++++++++++++------- Kernel/DoubleBuffer.h | 5 +++-- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/Kernel/DoubleBuffer.cpp b/Kernel/DoubleBuffer.cpp index 269a82d544..b549b8a047 100644 --- a/Kernel/DoubleBuffer.cpp +++ b/Kernel/DoubleBuffer.cpp @@ -17,22 +17,36 @@ inline void DoubleBuffer::compute_lockfree_metadata() m_space_for_writing = m_capacity - m_write_buffer->size; } +OwnPtr DoubleBuffer::try_create(size_t capacity) +{ + auto storage = KBuffer::try_create_with_size(capacity * 2, Region::Access::Read | Region::Access::Write, "DoubleBuffer"); + if (!storage) + return {}; + + return adopt_own_if_nonnull(new (nothrow) DoubleBuffer(capacity, storage.release_nonnull())); +} + DoubleBuffer::DoubleBuffer(size_t capacity) + : DoubleBuffer(capacity, KBuffer::try_create_with_size(capacity * 2, Region::Access::Read | Region::Access::Write, "DoubleBuffer").release_nonnull()) +{ +} + +DoubleBuffer::DoubleBuffer(size_t capacity, NonnullOwnPtr storage) : m_write_buffer(&m_buffer1) , m_read_buffer(&m_buffer2) - , m_storage(KBuffer::create_with_size(capacity * 2, Region::Access::Read | Region::Access::Write, "DoubleBuffer")) + , m_storage(move(storage)) , m_capacity(capacity) { - m_buffer1.data = m_storage.data(); + m_buffer1.data = m_storage->data(); m_buffer1.size = 0; - m_buffer2.data = m_storage.data() + capacity; + m_buffer2.data = m_storage->data() + capacity; m_buffer2.size = 0; m_space_for_writing = capacity; } void DoubleBuffer::flip() { - if (m_storage.is_null()) + if (m_storage->is_null()) return; VERIFY(m_read_buffer_index == m_read_buffer->size); swap(m_read_buffer, m_write_buffer); @@ -43,7 +57,7 @@ void DoubleBuffer::flip() KResultOr DoubleBuffer::write(const UserOrKernelBuffer& data, size_t size) { - if (!size || m_storage.is_null()) + if (!size || m_storage->is_null()) return 0; MutexLocker locker(m_lock); size_t bytes_to_write = min(size, m_space_for_writing); @@ -59,7 +73,7 @@ KResultOr DoubleBuffer::write(const UserOrKernelBuffer& data, size_t siz KResultOr DoubleBuffer::read(UserOrKernelBuffer& data, size_t size) { - if (!size || m_storage.is_null()) + if (!size || m_storage->is_null()) return 0; MutexLocker locker(m_lock); if (m_read_buffer_index >= m_read_buffer->size && m_write_buffer->size != 0) @@ -78,7 +92,7 @@ KResultOr DoubleBuffer::read(UserOrKernelBuffer& data, size_t size) KResultOr DoubleBuffer::peek(UserOrKernelBuffer& data, size_t size) { - if (!size || m_storage.is_null()) + if (!size || m_storage->is_null()) return 0; MutexLocker locker(m_lock); if (m_read_buffer_index >= m_read_buffer->size && m_write_buffer->size != 0) { diff --git a/Kernel/DoubleBuffer.h b/Kernel/DoubleBuffer.h index c99ef5da40..f130bb592d 100644 --- a/Kernel/DoubleBuffer.h +++ b/Kernel/DoubleBuffer.h @@ -16,8 +16,8 @@ namespace Kernel { class DoubleBuffer { public: + [[nodiscard]] static OwnPtr try_create(size_t capacity = 65536); explicit DoubleBuffer(size_t capacity = 65536); - [[nodiscard]] KResultOr write(const UserOrKernelBuffer&, size_t); [[nodiscard]] KResultOr write(const u8* data, size_t size) { @@ -47,6 +47,7 @@ public: } private: + explicit DoubleBuffer(size_t capacity, NonnullOwnPtr storage); void flip(); void compute_lockfree_metadata(); @@ -60,7 +61,7 @@ private: InnerBuffer m_buffer1; InnerBuffer m_buffer2; - KBuffer m_storage; + NonnullOwnPtr m_storage; Function m_unblock_callback; size_t m_capacity { 0 }; size_t m_read_buffer_index { 0 };