From 5e0c933df0e0c4e2d82c7ba3f9973f5c81113ca7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Wed, 12 Nov 2025 19:18:58 +0100 Subject: [PATCH] Added ring_buffer_user_peek() similar to ring_buffer_peek() Change-Id: Ife183989e0c031f648feb6a4b03f1a3ffc15503c Reviewed-on: https://review.haiku-os.org/c/haiku/+/9858 Reviewed-by: waddlesplash Tested-by: Commit checker robot --- headers/private/kernel/util/ring_buffer.h | 4 +- src/system/kernel/util/ring_buffer.cpp | 70 ++++++++++++++++------- 2 files changed, 50 insertions(+), 24 deletions(-) diff --git a/headers/private/kernel/util/ring_buffer.h b/headers/private/kernel/util/ring_buffer.h index 90627b0276..d2495fd19e 100644 --- a/headers/private/kernel/util/ring_buffer.h +++ b/headers/private/kernel/util/ring_buffer.h @@ -41,8 +41,8 @@ size_t ring_buffer_read(struct ring_buffer *buffer, uint8 *data, ssize_t length) size_t ring_buffer_write(struct ring_buffer *buffer, const uint8 *data, ssize_t length); ssize_t ring_buffer_user_read(struct ring_buffer *buffer, uint8 *data, ssize_t length); ssize_t ring_buffer_user_write(struct ring_buffer *buffer, const uint8 *data, ssize_t length); -size_t ring_buffer_peek(struct ring_buffer *buffer, size_t offset, void *data, - size_t length); +size_t ring_buffer_peek(struct ring_buffer *buffer, size_t offset, void *data, size_t length); +ssize_t ring_buffer_user_peek(struct ring_buffer *buffer, size_t offset, void *data, ssize_t length); int32 ring_buffer_get_vecs(struct ring_buffer *buffer, struct iovec *vecs); size_t ring_buffer_move(struct ring_buffer *to, ssize_t length, struct ring_buffer *from); diff --git a/src/system/kernel/util/ring_buffer.cpp b/src/system/kernel/util/ring_buffer.cpp index 2b7cb01f51..b694a0b13f 100644 --- a/src/system/kernel/util/ring_buffer.cpp +++ b/src/system/kernel/util/ring_buffer.cpp @@ -120,6 +120,47 @@ write_to_buffer(struct ring_buffer *buffer, const uint8 *data, ssize_t length, } +static ssize_t +buffer_peek(struct ring_buffer* buffer, size_t offset, void* data, + ssize_t length, bool user) +{ + size_t available = buffer->in; + + if (offset >= available || length == 0) + return 0; + + if (offset + length > available) + length = available - offset; + + if ((offset += buffer->first) >= (size_t)buffer->size) + offset -= buffer->size; + + if (offset + length <= (size_t)buffer->size) { + // simple copy + if (user) { + if (user_memcpy(data, buffer->buffer + offset, length) < B_OK) + return B_BAD_ADDRESS; + } else + memcpy(data, buffer->buffer + offset, length); + } else { + // need to copy both ends + size_t upper = buffer->size - offset; + size_t lower = length - upper; + + if (user) { + if (user_memcpy(data, buffer->buffer + offset, upper) < B_OK + || user_memcpy((uint8*)data + upper, buffer->buffer, lower) < B_OK) + return B_BAD_ADDRESS; + } else { + memcpy(data, buffer->buffer + offset, upper); + memcpy((uint8*)data + upper, buffer->buffer, lower); + } + } + + return length; +} + + // #pragma mark - @@ -241,30 +282,15 @@ size_t ring_buffer_peek(struct ring_buffer* buffer, size_t offset, void* data, size_t length) { - size_t available = buffer->in; + return buffer_peek(buffer, offset, data, length, false); +} - if (offset >= available || length == 0) - return 0; - if (offset + length > available) - length = available - offset; - - if ((offset += buffer->first) >= (size_t)buffer->size) - offset -= buffer->size; - - if (offset + length <= (size_t)buffer->size) { - // simple copy - memcpy(data, buffer->buffer + offset, length); - } else { - // need to copy both ends - size_t upper = buffer->size - offset; - size_t lower = length - upper; - - memcpy(data, buffer->buffer + offset, upper); - memcpy((uint8*)data + upper, buffer->buffer, lower); - } - - return length; +ssize_t +ring_buffer_user_peek(struct ring_buffer* buffer, size_t offset, void* data, + ssize_t length) +{ + return buffer_peek(buffer, offset, data, length, true); }