mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 03:37:43 +00:00
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.
This commit is contained in:
parent
b6200a3ed8
commit
f816abcbad
2 changed files with 24 additions and 9 deletions
|
@ -17,22 +17,36 @@ inline void DoubleBuffer::compute_lockfree_metadata()
|
||||||
m_space_for_writing = m_capacity - m_write_buffer->size;
|
m_space_for_writing = m_capacity - m_write_buffer->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OwnPtr<DoubleBuffer> 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::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<KBuffer> storage)
|
||||||
: m_write_buffer(&m_buffer1)
|
: m_write_buffer(&m_buffer1)
|
||||||
, m_read_buffer(&m_buffer2)
|
, 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_capacity(capacity)
|
||||||
{
|
{
|
||||||
m_buffer1.data = m_storage.data();
|
m_buffer1.data = m_storage->data();
|
||||||
m_buffer1.size = 0;
|
m_buffer1.size = 0;
|
||||||
m_buffer2.data = m_storage.data() + capacity;
|
m_buffer2.data = m_storage->data() + capacity;
|
||||||
m_buffer2.size = 0;
|
m_buffer2.size = 0;
|
||||||
m_space_for_writing = capacity;
|
m_space_for_writing = capacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DoubleBuffer::flip()
|
void DoubleBuffer::flip()
|
||||||
{
|
{
|
||||||
if (m_storage.is_null())
|
if (m_storage->is_null())
|
||||||
return;
|
return;
|
||||||
VERIFY(m_read_buffer_index == m_read_buffer->size);
|
VERIFY(m_read_buffer_index == m_read_buffer->size);
|
||||||
swap(m_read_buffer, m_write_buffer);
|
swap(m_read_buffer, m_write_buffer);
|
||||||
|
@ -43,7 +57,7 @@ void DoubleBuffer::flip()
|
||||||
|
|
||||||
KResultOr<size_t> DoubleBuffer::write(const UserOrKernelBuffer& data, size_t size)
|
KResultOr<size_t> DoubleBuffer::write(const UserOrKernelBuffer& data, size_t size)
|
||||||
{
|
{
|
||||||
if (!size || m_storage.is_null())
|
if (!size || m_storage->is_null())
|
||||||
return 0;
|
return 0;
|
||||||
MutexLocker locker(m_lock);
|
MutexLocker locker(m_lock);
|
||||||
size_t bytes_to_write = min(size, m_space_for_writing);
|
size_t bytes_to_write = min(size, m_space_for_writing);
|
||||||
|
@ -59,7 +73,7 @@ KResultOr<size_t> DoubleBuffer::write(const UserOrKernelBuffer& data, size_t siz
|
||||||
|
|
||||||
KResultOr<size_t> DoubleBuffer::read(UserOrKernelBuffer& data, size_t size)
|
KResultOr<size_t> DoubleBuffer::read(UserOrKernelBuffer& data, size_t size)
|
||||||
{
|
{
|
||||||
if (!size || m_storage.is_null())
|
if (!size || m_storage->is_null())
|
||||||
return 0;
|
return 0;
|
||||||
MutexLocker locker(m_lock);
|
MutexLocker locker(m_lock);
|
||||||
if (m_read_buffer_index >= m_read_buffer->size && m_write_buffer->size != 0)
|
if (m_read_buffer_index >= m_read_buffer->size && m_write_buffer->size != 0)
|
||||||
|
@ -78,7 +92,7 @@ KResultOr<size_t> DoubleBuffer::read(UserOrKernelBuffer& data, size_t size)
|
||||||
|
|
||||||
KResultOr<size_t> DoubleBuffer::peek(UserOrKernelBuffer& data, size_t size)
|
KResultOr<size_t> DoubleBuffer::peek(UserOrKernelBuffer& data, size_t size)
|
||||||
{
|
{
|
||||||
if (!size || m_storage.is_null())
|
if (!size || m_storage->is_null())
|
||||||
return 0;
|
return 0;
|
||||||
MutexLocker locker(m_lock);
|
MutexLocker locker(m_lock);
|
||||||
if (m_read_buffer_index >= m_read_buffer->size && m_write_buffer->size != 0) {
|
if (m_read_buffer_index >= m_read_buffer->size && m_write_buffer->size != 0) {
|
||||||
|
|
|
@ -16,8 +16,8 @@ namespace Kernel {
|
||||||
|
|
||||||
class DoubleBuffer {
|
class DoubleBuffer {
|
||||||
public:
|
public:
|
||||||
|
[[nodiscard]] static OwnPtr<DoubleBuffer> try_create(size_t capacity = 65536);
|
||||||
explicit DoubleBuffer(size_t capacity = 65536);
|
explicit DoubleBuffer(size_t capacity = 65536);
|
||||||
|
|
||||||
[[nodiscard]] KResultOr<size_t> write(const UserOrKernelBuffer&, size_t);
|
[[nodiscard]] KResultOr<size_t> write(const UserOrKernelBuffer&, size_t);
|
||||||
[[nodiscard]] KResultOr<size_t> write(const u8* data, size_t size)
|
[[nodiscard]] KResultOr<size_t> write(const u8* data, size_t size)
|
||||||
{
|
{
|
||||||
|
@ -47,6 +47,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
explicit DoubleBuffer(size_t capacity, NonnullOwnPtr<KBuffer> storage);
|
||||||
void flip();
|
void flip();
|
||||||
void compute_lockfree_metadata();
|
void compute_lockfree_metadata();
|
||||||
|
|
||||||
|
@ -60,7 +61,7 @@ private:
|
||||||
InnerBuffer m_buffer1;
|
InnerBuffer m_buffer1;
|
||||||
InnerBuffer m_buffer2;
|
InnerBuffer m_buffer2;
|
||||||
|
|
||||||
KBuffer m_storage;
|
NonnullOwnPtr<KBuffer> m_storage;
|
||||||
Function<void()> m_unblock_callback;
|
Function<void()> m_unblock_callback;
|
||||||
size_t m_capacity { 0 };
|
size_t m_capacity { 0 };
|
||||||
size_t m_read_buffer_index { 0 };
|
size_t m_read_buffer_index { 0 };
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue