ringbuffer: better operations

This commit is contained in:
Matheus
2024-08-21 23:40:01 -03:00
parent fb24745071
commit 13d34e49ae
+47 -39
View File
@@ -2,6 +2,7 @@
#include <kernel/vmm.h> #include <kernel/vmm.h>
#include <util.h> #include <util.h>
#include <errno.h> #include <errno.h>
#include <string.h>
int ringbuffer_init(ringbuffer_t *ringbuffer, size_t size) { int ringbuffer_init(ringbuffer_t *ringbuffer, size_t size) {
ringbuffer->data = vmm_map(NULL, ROUND_UP(size, PAGE_SIZE), VMM_FLAGS_ALLOCATE, ARCH_MMU_FLAGS_WRITE | ARCH_MMU_FLAGS_READ | ARCH_MMU_FLAGS_NOEXEC, NULL); ringbuffer->data = vmm_map(NULL, ROUND_UP(size, PAGE_SIZE), VMM_FLAGS_ALLOCATE, ARCH_MMU_FLAGS_WRITE | ARCH_MMU_FLAGS_READ | ARCH_MMU_FLAGS_NOEXEC, NULL);
@@ -25,56 +26,63 @@ size_t ringbuffer_truncate(ringbuffer_t *ringbuffer, size_t count) {
} }
size_t ringbuffer_read(ringbuffer_t *ringbuffer, void *buffer, size_t count) { size_t ringbuffer_read(ringbuffer_t *ringbuffer, void *buffer, size_t count) {
uint8_t *ptr = buffer; size_t datacount = RINGBUFFER_DATACOUNT(ringbuffer);
size_t readc = 0; count = min(count, datacount);
for (; readc < count; ++readc) { size_t firstpassoffset = ringbuffer->read % ringbuffer->size;
if (ringbuffer->read == ringbuffer->write) size_t firstpassremaining = ringbuffer->size - firstpassoffset;
break; size_t firstpasscount = min(count, firstpassremaining);
uintmax_t readoffset = ringbuffer->read % ringbuffer->size; memcpy(buffer, (void *)((uintptr_t)ringbuffer->data + firstpassoffset), firstpasscount);
*ptr++ = *((uint8_t *)ringbuffer->data + readoffset);
++ringbuffer->read; if (firstpasscount == count)
} goto leave;
return readc;
memcpy((void *)((uintptr_t)buffer + firstpasscount), ringbuffer->data, count - firstpasscount);
leave:
ringbuffer->read += count;
return count;
} }
size_t ringbuffer_peek(ringbuffer_t *ringbuffer, void *buffer, uintmax_t offset, size_t count) { size_t ringbuffer_peek(ringbuffer_t *ringbuffer, void *buffer, uintmax_t offset, size_t count) {
uint8_t *ptr = buffer; size_t datacount = RINGBUFFER_DATACOUNT(ringbuffer);
size_t freespace = RINGBUFFER_SIZE(ringbuffer) - datacount;
uintmax_t read = ringbuffer->read; if (offset >= datacount)
uintmax_t write = ringbuffer->write;
uintmax_t curroff = 0;
for (; curroff < offset; ++curroff) {
if (read == write)
return 0; return 0;
++read; uintmax_t read = ringbuffer->read + min(offset, freespace);
}
size_t readc = 0; size_t offsetdatacount = datacount - offset;
for (; readc < count; ++readc) { count = min(count, offsetdatacount);
if (read == write) size_t firstpassoffset = read % ringbuffer->size;
break; size_t firstpassremaining = ringbuffer->size - firstpassoffset;
size_t firstpasscount = min(count, firstpassremaining);
uintmax_t readoffset = read % ringbuffer->size; memcpy(buffer, (void *)((uintptr_t)ringbuffer->data + firstpassoffset), firstpasscount);
*ptr++ = *((uint8_t *)ringbuffer->data + readoffset);
++read;
}
return readc; if (firstpasscount == count)
return count;
memcpy((void *)((uintptr_t)buffer + firstpasscount), ringbuffer->data, count - firstpasscount);
return count;
} }
size_t ringbuffer_write(ringbuffer_t *ringbuffer, void *buffer, size_t count) { size_t ringbuffer_write(ringbuffer_t *ringbuffer, void *buffer, size_t count) {
uint8_t *ptr = buffer; size_t freespace = RINGBUFFER_SIZE(ringbuffer) - RINGBUFFER_DATACOUNT(ringbuffer);
size_t writec = 0; count = min(count, freespace);
for (;writec < count; ++writec) { size_t firstpassoffset = ringbuffer->write % ringbuffer->size;
if (ringbuffer->write == ringbuffer->read + ringbuffer->size) size_t firstpassremaining = ringbuffer->size - firstpassoffset;
break; size_t firstpasscount = min(count, firstpassremaining);
uintmax_t writeoffset = ringbuffer->write % ringbuffer->size; memcpy((void *)((uintptr_t)ringbuffer->data + firstpassoffset), buffer, firstpasscount);
*((uint8_t *)ringbuffer->data + writeoffset) = *ptr++;
++ringbuffer->write; if (firstpasscount == count)
} goto leave;
return writec;
memcpy(ringbuffer->data, (void *)((uintptr_t)buffer + firstpasscount), count - firstpasscount);
leave:
ringbuffer->write += count;
return count;
} }