From d1994d44a388b3c14b8570a2a3ca89e69e7c700c Mon Sep 17 00:00:00 2001 From: Mathieu Maret Date: Tue, 9 Nov 2021 20:35:55 +0100 Subject: [PATCH] Add locked ring buffer --- core/ringbuffer.c | 117 ++++++++++++++++++++++++++++++++++++++++++---- core/ringbuffer.h | 22 +++++++-- core/uaccess.c | 52 +++++++++++++++++++++ core/uaccess.h | 5 ++ 4 files changed, 181 insertions(+), 15 deletions(-) create mode 100644 core/uaccess.c create mode 100644 core/uaccess.h diff --git a/core/ringbuffer.c b/core/ringbuffer.c index ed5a050..df19546 100644 --- a/core/ringbuffer.c +++ b/core/ringbuffer.c @@ -1,6 +1,7 @@ #include "alloc.h" #include "klibc.h" #include "ringbuffer.h" +#include "synchro.h" struct ringbuffer_instance_t { int32_t wr_pos; @@ -12,12 +13,18 @@ struct ringbuffer_instance_t { ringbuffer_t ringbufferCreate(uint32_t capacity) { - ringbuffer_t inst = zalloc(1* sizeof(struct ringbuffer_instance_t)); - inst->data = zalloc(capacity * sizeof(uint8_t)); - inst->capacity = capacity; - inst->wr_pos = 0; - inst->rd_pos = 0; - inst->full = capacity == 0; + ringbuffer_t inst = zalloc(1 * sizeof(struct ringbuffer_instance_t)); + if (inst == NULL) + return NULL; + inst->data = zalloc(capacity * sizeof(uint8_t)); + if (inst->data == NULL) { + free(inst); + return NULL; + } + inst->capacity = capacity; + inst->wr_pos = 0; + inst->rd_pos = 0; + inst->full = capacity == 0; return inst; } @@ -35,19 +42,19 @@ uint32_t ringbufferUsed(ringbuffer_t instance) return (instance->wr_pos - instance->rd_pos) % instance->capacity; } -bool_t ringbufferEmpty(ringbuffer_t instance) +bool_t ringbufferIsEmpty(ringbuffer_t instance) { return (!instance->full && (instance->wr_pos == instance->rd_pos)); } -bool_t ringbufferFull(ringbuffer_t instance) +bool_t ringbufferIsFull(ringbuffer_t instance) { return instance->full; } bool_t ringbufferEnqueue(ringbuffer_t instance, uint8_t item) { - if (ringbufferFull(instance)) + if (ringbufferIsFull(instance)) return FALSE; instance->data[instance->wr_pos] = item; @@ -60,7 +67,7 @@ bool_t ringbufferEnqueue(ringbuffer_t instance, uint8_t item) bool_t ringbufferDequeue(ringbuffer_t instance, uint8_t *item) { - if (ringbufferEmpty(instance)) + if (ringbufferIsEmpty(instance)) return FALSE; instance->full = FALSE; @@ -85,3 +92,93 @@ void ringbufferDebug(ringbuffer_t instance) printf("%d/%d %d %d %s\n", ringbufferUsed(instance), ringbufferCapacity(instance), instance->wr_pos, instance->rd_pos, instance->full ? "(full)" : ""); } + +struct locked_ringbuffer_instance_t { + struct ringbuffer_instance_t *ring; + struct mutex mut; +}; + +locked_ringbuffer_t lringbufferCreate(uint32_t capacity) +{ + locked_ringbuffer_t inst = zalloc(sizeof(locked_ringbuffer_t)); + if (inst == NULL) + return NULL; + + inst->ring = ringbufferCreate(capacity); + if (inst->ring == NULL) { + free(inst); + return NULL; + } + + mutexInit(&inst->mut); + + return inst; +} + +uint32_t lringbufferCapacity(locked_ringbuffer_t instance) +{ + return instance->ring->capacity; +} + +uint32_t lringbufferUsed(locked_ringbuffer_t instance) +{ + int used; + mutexLock(&instance->mut); + used = ringbufferUsed(instance->ring); + mutexUnlock(&instance->mut); + return used; +} + +bool_t lringbufferEnqueue(locked_ringbuffer_t instance, uint8_t item) +{ + int ret; + mutexLock(&instance->mut); + ret = ringbufferEnqueue(instance->ring, item); + mutexUnlock(&instance->mut); + + return ret; +} + +bool_t lringbufferDequeue(locked_ringbuffer_t instance, uint8_t *item) +{ + int ret; + mutexLock(&instance->mut); + ret = ringbufferDequeue(instance->ring, item); + mutexUnlock(&instance->mut); + + return ret; +} + +void lringbufferDestroy(locked_ringbuffer_t instance){ + mutexFree(&instance->mut); + ringbufferDestroy(instance->ring); + instance->ring = NULL; + free(instance); +} + +void lringbufferDebug(locked_ringbuffer_t instance) +{ + mutexLock(&instance->mut); + ringbufferDebug(instance->ring); + mutexUnlock(&instance->mut); +} + +bool_t lringbufferIsEmpty(locked_ringbuffer_t instance) +{ + bool_t ret; + mutexLock(&instance->mut); + ret = ringbufferIsEmpty(instance->ring); + mutexUnlock(&instance->mut); + + return ret; +} + +bool_t lringbufferIsFull(locked_ringbuffer_t instance) +{ + bool_t ret; + mutexLock(&instance->mut); + ret = ringbufferIsFull(instance->ring); + mutexUnlock(&instance->mut); + + return ret; +} diff --git a/core/ringbuffer.h b/core/ringbuffer.h index 5337f15..9cf226d 100644 --- a/core/ringbuffer.h +++ b/core/ringbuffer.h @@ -1,15 +1,27 @@ #pragma once - #include "stdarg.h" +#include "wait.h" -typedef struct ringbuffer_instance_t* ringbuffer_t; +typedef struct ringbuffer_instance_t *ringbuffer_t; ringbuffer_t ringbufferCreate(uint32_t capacity); uint32_t ringbufferCapacity(ringbuffer_t instance); uint32_t ringbufferUsed(ringbuffer_t instance); bool_t ringbufferEnqueue(ringbuffer_t instance, uint8_t item); -bool_t ringbufferDequeue(ringbuffer_t instance, uint8_t* item); +bool_t ringbufferDequeue(ringbuffer_t instance, uint8_t *item); void ringbufferDestroy(ringbuffer_t instance); void ringbufferDebug(ringbuffer_t instance); -bool_t ringbufferEmpty(ringbuffer_t instance); -bool_t ringbufferFull(ringbuffer_t instance); +bool_t ringbufferIsEmpty(ringbuffer_t instance); +bool_t ringbufferIsFull(ringbuffer_t instance); + +typedef struct locked_ringbuffer_instance_t *locked_ringbuffer_t; + +locked_ringbuffer_t lringbufferCreate(uint32_t capacity); +uint32_t lringbufferCapacity(locked_ringbuffer_t instance); +uint32_t lringbufferUsed(locked_ringbuffer_t instance); +bool_t lringbufferEnqueue(locked_ringbuffer_t instance, uint8_t item); +bool_t lringbufferDequeue(locked_ringbuffer_t instance, uint8_t *item); +void lringbufferDestroy(locked_ringbuffer_t instance); +void lringbufferDebug(locked_ringbuffer_t instance); +bool_t lringbufferIsEmpty(locked_ringbuffer_t instance); +bool_t lringbufferIsFull(locked_ringbuffer_t instance); diff --git a/core/uaccess.c b/core/uaccess.c new file mode 100644 index 0000000..619e385 --- /dev/null +++ b/core/uaccess.c @@ -0,0 +1,52 @@ +#include "assert.h" +#include "mmuContext.h" +#include "paging.h" +#include "thread.h" +#include "uaccess.h" + +static int bindtoUserContext() +{ + struct thread *currentThread; + struct mmu_context *ctx; + + currentThread = getCurrentThread(); + assert(NULL != currentThread->process); + + /* Switch to the user's address space */ + ctx = processGetMMUContext(currentThread->process); + return threadChangeCurrentContext(ctx); +} + +static int unbindUserContext() +{ + return threadChangeCurrentContext(NULL); +} + +static int memcpyUserMemNoCheck(vaddr_t dest, vaddr_t src, size_t size) +{ + + int ret; + + ret = bindtoUserContext(); + if (ret != 0) + return ret; + + memcpy((void *)dest, (void *)src, size); + + ret = unbindUserContext(); + if (ret != 0) + return ret; + + return size; +} + +int memcpyFromUser(vaddr_t to, uaddr_t from, size_t size) +{ + + if ((uint)from < PAGING_BASE_USER_ADDRESS) + return -EPERM; + if ((uint)from > PAGING_TOP_USER_ADDRESS - size) + return -EPERM; + + return memcpyUserMemNoCheck(to, from, size); +} diff --git a/core/uaccess.h b/core/uaccess.h new file mode 100644 index 0000000..465e268 --- /dev/null +++ b/core/uaccess.h @@ -0,0 +1,5 @@ +#pragma once +#include "types.h" +#include "stdarg.h" + +int memcpyFromUser(vaddr_t to, uaddr_t from, size_t size);