diff --git a/headers/private/kernel/util/ring_buffer.h b/headers/private/kernel/util/ring_buffer.h index fd1b78000f..90627b0276 100644 --- a/headers/private/kernel/util/ring_buffer.h +++ b/headers/private/kernel/util/ring_buffer.h @@ -44,6 +44,7 @@ ssize_t ring_buffer_user_write(struct ring_buffer *buffer, const uint8 *data, ss size_t ring_buffer_peek(struct ring_buffer *buffer, size_t offset, void *data, size_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); #ifdef __cplusplus } diff --git a/src/add-ons/kernel/network/protocols/unix/UnixFifo.cpp b/src/add-ons/kernel/network/protocols/unix/UnixFifo.cpp index 6ceb9af648..84b4db25ab 100644 --- a/src/add-ons/kernel/network/protocols/unix/UnixFifo.cpp +++ b/src/add-ons/kernel/network/protocols/unix/UnixFifo.cpp @@ -316,8 +316,20 @@ UnixBufferQueue::Write(UnixRequest& request) status_t UnixBufferQueue::SetCapacity(size_t capacity) { -// TODO:... -return B_ERROR; + if (capacity <= fCapacity) + return B_OK; + + ring_buffer* newBuffer = create_ring_buffer(capacity); + if (newBuffer == NULL) + return B_NO_MEMORY; + + ring_buffer_move(newBuffer, ring_buffer_readable(fBuffer), fBuffer); + delete_ring_buffer(fBuffer); + + fBuffer = newBuffer; + fCapacity = capacity; + + return B_OK; } diff --git a/src/system/kernel/util/ring_buffer.cpp b/src/system/kernel/util/ring_buffer.cpp index b234ccd3c3..2b7cb01f51 100644 --- a/src/system/kernel/util/ring_buffer.cpp +++ b/src/system/kernel/util/ring_buffer.cpp @@ -302,6 +302,47 @@ ring_buffer_get_vecs(struct ring_buffer* buffer, struct iovec* vecs) } +/*! Moves data from one ring buffer to another. + + \param to The destination ring buffer. + \param length The maximum number of bytes to move. + \param from The source ring buffer. + \return The number of bytes actually moved. +*/ +size_t +ring_buffer_move(struct ring_buffer *to, ssize_t length, + struct ring_buffer *from) +{ + if (length > from->in) + length = from->in; + + if (length > (to->size - to->in)) + length = to->size - to->in; + + size_t bytesMoved = 0; + + if ((from->first + length) <= from->size) { + // simple move + bytesMoved = ring_buffer_write(to, from->buffer + from->first, length); + } else { + // need to move both ends + size_t upper = from->size - from->first; + size_t lower = length - upper; + + bytesMoved = ring_buffer_write(to, from->buffer + from->first, upper); + if (bytesMoved == upper) { + // only continue writing if the first part was completely written + bytesMoved += ring_buffer_write(to, from->buffer, lower); + } + } + + from->first = (from->first + bytesMoved) % from->size; + from->in -= bytesMoved; + + return bytesMoved; +} + + #if 0 /** Sends the contents of the ring buffer to a port. * The buffer will be empty afterwards only if sending the data actually works.