summaryrefslogtreecommitdiff
path: root/Kernel
diff options
context:
space:
mode:
authorJustin <sw1tchbl4d3@sw1tchbl4d3.com>2021-04-28 23:22:21 +0200
committerAndreas Kling <kling@serenityos.org>2021-04-29 08:09:53 +0200
commit2d098c88dc64cbf58e3eb09a39fb917e78360685 (patch)
tree6c30c6f271ec26e162e60bf4f82abf9826ccca07 /Kernel
parent9bcdbe205b02078f7a6ff01d8769efe4617e60be (diff)
downloadserenity-2d098c88dc64cbf58e3eb09a39fb917e78360685.zip
Kernel: Implement peek() function for DoubleBuffer
This allows us to "peek" into a DoubleBuffer without incrementing the m_read_buffer_index, which is needed to implement MSG_PEEK.
Diffstat (limited to 'Kernel')
-rw-r--r--Kernel/DoubleBuffer.cpp21
-rw-r--r--Kernel/DoubleBuffer.h6
2 files changed, 25 insertions, 2 deletions
diff --git a/Kernel/DoubleBuffer.cpp b/Kernel/DoubleBuffer.cpp
index ef5fd497e1..2d3b39adac 100644
--- a/Kernel/DoubleBuffer.cpp
+++ b/Kernel/DoubleBuffer.cpp
@@ -44,7 +44,6 @@ ssize_t DoubleBuffer::write(const UserOrKernelBuffer& data, size_t size)
{
if (!size || m_storage.is_null())
return 0;
- VERIFY(size > 0);
Locker locker(m_lock);
size_t bytes_to_write = min(size, m_space_for_writing);
u8* write_ptr = m_write_buffer->data + m_write_buffer->size;
@@ -61,7 +60,6 @@ ssize_t DoubleBuffer::read(UserOrKernelBuffer& data, size_t size)
{
if (!size || m_storage.is_null())
return 0;
- VERIFY(size > 0);
Locker locker(m_lock);
if (m_read_buffer_index >= m_read_buffer->size && m_write_buffer->size != 0)
flip();
@@ -77,4 +75,23 @@ ssize_t DoubleBuffer::read(UserOrKernelBuffer& data, size_t size)
return (ssize_t)nread;
}
+ssize_t DoubleBuffer::peek(UserOrKernelBuffer& data, size_t size)
+{
+ if (!size || m_storage.is_null())
+ return 0;
+ Locker locker(m_lock);
+ if (m_read_buffer_index >= m_read_buffer->size && m_write_buffer->size != 0) {
+ flip();
+ }
+ if (m_read_buffer_index >= m_read_buffer->size)
+ return 0;
+ size_t nread = min(m_read_buffer->size - m_read_buffer_index, size);
+ if (!data.write(m_read_buffer->data + m_read_buffer_index, nread))
+ return -EFAULT;
+ compute_lockfree_metadata();
+ if (m_unblock_callback && m_space_for_writing > 0)
+ m_unblock_callback();
+ return (ssize_t)nread;
+}
+
}
diff --git a/Kernel/DoubleBuffer.h b/Kernel/DoubleBuffer.h
index fc3b3472db..8bf58f7532 100644
--- a/Kernel/DoubleBuffer.h
+++ b/Kernel/DoubleBuffer.h
@@ -29,6 +29,12 @@ public:
auto buffer = UserOrKernelBuffer::for_kernel_buffer(data);
return read(buffer, size);
}
+ [[nodiscard]] ssize_t peek(UserOrKernelBuffer&, size_t);
+ [[nodiscard]] ssize_t peek(u8* data, size_t size)
+ {
+ auto buffer = UserOrKernelBuffer::for_kernel_buffer(data);
+ return peek(buffer, size);
+ }
bool is_empty() const { return m_empty; }