Skip to content
Snippets Groups Projects
Commit 16a248d7 authored by q3k's avatar q3k
Browse files

badge23: scope: better locking

This uses atomics to lock out concurrenct writes/reads, and fixes some
potential null pointer dereferences.
parent d65cfeaf
Branches
Tags
No related merge requests found
...@@ -5,7 +5,8 @@ typedef struct { ...@@ -5,7 +5,8 @@ typedef struct {
int16_t * buffer; int16_t * buffer;
int16_t buffer_size; int16_t buffer_size;
int16_t write_head_position; // last written value int16_t write_head_position; // last written value
volatile uint8_t is_being_read; // atomic value used to prevent simultaneous reads/writes (not a mutex!).
volatile uint32_t is_being_read;
} scope_t; } scope_t;
void init_scope(uint16_t size); void init_scope(uint16_t size);
......
#include "badge23/scope.h" #include "badge23/scope.h"
#include "esp_log.h"
#include <string.h> #include <string.h>
#include <freertos/FreeRTOS.h>
#include <freertos/atomic.h>
scope_t * scope; scope_t * scope = NULL;
static const char* TAG = "scope";
void init_scope(uint16_t size){ void init_scope(uint16_t size){
if (scope != NULL) {
return;
}
scope_t * scp = malloc(sizeof(scope_t)); scope_t * scp = malloc(sizeof(scope_t));
if(scp == NULL) scope = NULL; if(scp == NULL) {
ESP_LOGE(TAG, "scope allocation failed, out of memory");
return;
}
scp->buffer_size = size; scp->buffer_size = size;
scp->buffer = malloc(sizeof(int16_t) * scp->buffer_size); scp->buffer = malloc(sizeof(int16_t) * scp->buffer_size);
if(scp->buffer == NULL){ if(scp->buffer == NULL){
free(scp); free(scp);
scope = NULL; ESP_LOGE(TAG, "scope buffer allocation failed, out of memory");
} else { return;
}
memset(scp->buffer, 0, sizeof(int16_t) * scp->buffer_size); memset(scp->buffer, 0, sizeof(int16_t) * scp->buffer_size);
scope = scp; scope = scp;
ESP_LOGI(TAG, "initialized");
} }
static inline bool scope_being_read(void) {
return Atomic_CompareAndSwap_u32(&scope->is_being_read, 0, 0) == ATOMIC_COMPARE_AND_SWAP_FAILURE;
} }
void write_to_scope(int16_t value){ void write_to_scope(int16_t value){
if(scope->is_being_read) return; if(scope == NULL || scope_being_read()) {
if(scope == NULL) return; return;
}
scope->write_head_position++; scope->write_head_position++;
if(scope->write_head_position >= scope->buffer_size) scope->write_head_position = 0; if(scope->write_head_position >= scope->buffer_size) scope->write_head_position = 0;
scope->buffer[scope->write_head_position] = value; scope->buffer[scope->write_head_position] = value;
} }
void begin_scope_read(){ void begin_scope_read(void) {
if(scope == NULL) return; if (scope == NULL) {
scope->is_being_read = 1; //best mutex return;
}
Atomic_Increment_u32(&scope->is_being_read);
} }
void read_line_from_scope(uint16_t * line, int16_t point){ void read_line_from_scope(uint16_t * line, int16_t point){
if (scope == NULL) {
return;
}
memset(line, 0, 480); memset(line, 0, 480);
int16_t startpoint = scope->write_head_position - point; int16_t startpoint = scope->write_head_position - point;
while(startpoint < 0){ while(startpoint < 0){
...@@ -57,7 +80,9 @@ void read_line_from_scope(uint16_t * line, int16_t point){ ...@@ -57,7 +80,9 @@ void read_line_from_scope(uint16_t * line, int16_t point){
} }
} }
void end_scope_read(){ void end_scope_read(void) {
if(scope == NULL) return; if (scope == NULL) {
scope->is_being_read = 0; //best mutex return;
}
Atomic_Decrement_u32(&scope->is_being_read);
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment