diff --git a/kernel-src/include/ringbuffer.h b/kernel-src/include/ringbuffer.h new file mode 100644 index 00000000..5c1afac2 --- /dev/null +++ b/kernel-src/include/ringbuffer.h @@ -0,0 +1,21 @@ +#ifndef _RINGBUFFER_H +#define _RINGBUFFER_H + +#include +#include + +typedef struct { + size_t size; + uintmax_t write; + uintmax_t read; + void *data; +} ringbuffer_t; + +int ringbuffer_init(ringbuffer_t *ringbuffer, size_t size); +void ringbuffer_destroy(ringbuffer_t *ringbuffer); +size_t ringbuffer_read(ringbuffer_t* ringbuffer, void *buffer, size_t count); +size_t ringbuffer_write(ringbuffer_t* ringbuffer, void *buffer, size_t count); + +#define RINGBUFFER_DATACOUNT(x) ((x)->write - (x)->read) + +#endif diff --git a/kernel-src/lib/ringbuffer.c b/kernel-src/lib/ringbuffer.c new file mode 100644 index 00000000..a71ee8dc --- /dev/null +++ b/kernel-src/lib/ringbuffer.c @@ -0,0 +1,47 @@ +#include +#include +#include +#include + +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); + if (ringbuffer->data == NULL) + return ENOMEM; + + ringbuffer->size = size; + ringbuffer->write = 0; + ringbuffer->read = 0; + return 0; +} + +void ringbuffer_destroy(ringbuffer_t *ringbuffer) { + vmm_unmap(ringbuffer->data, ROUND_UP(ringbuffer->size, PAGE_SIZE), 0); +} + +size_t ringbuffer_read(ringbuffer_t* ringbuffer, void *buffer, size_t count) { + uint8_t *ptr = buffer; + size_t readc = 0; + for (; readc < count; ++readc) { + if (ringbuffer->read == ringbuffer->write) + break; + + uintmax_t readoffset = ringbuffer->read % ringbuffer->size; + *ptr++ = *((uint8_t *)ringbuffer->data + readoffset); + ++ringbuffer->read; + } + return readc; +} + +size_t ringbuffer_write(ringbuffer_t* ringbuffer, void *buffer, size_t count) { + uint8_t *ptr = buffer; + size_t writec = 0; + for (;writec < count; ++writec) { + if (ringbuffer->write == ringbuffer->read + ringbuffer->size) + break; + + uintmax_t writeoffset = ringbuffer->write % ringbuffer->size; + *((uint8_t *)ringbuffer->data + writeoffset) = *ptr++; + ++ringbuffer->write; + } + return writec; +}