From cebdade610264343fe275ca3bb2a811c8d34c505 Mon Sep 17 00:00:00 2001
From: Rahix <rahix@rahix.de>
Date: Fri, 19 Jul 2019 18:23:15 +0200
Subject: [PATCH] feat(streams): Add descriptor table lock

Signed-off-by: Rahix <rahix@rahix.de>
---
 epicardium/modules/stream.c | 32 ++++++++++++++++++++++++++++++++
 epicardium/modules/stream.h |  3 +++
 2 files changed, 35 insertions(+)

diff --git a/epicardium/modules/stream.c b/epicardium/modules/stream.c
index 561c398a..b39e0c1d 100644
--- a/epicardium/modules/stream.c
+++ b/epicardium/modules/stream.c
@@ -1,18 +1,32 @@
 #include <string.h>
 
+#include "FreeRTOS.h"
+#include "semphr.h"
+
 #include "epicardium.h"
 #include "stream.h"
 
+/* Internal buffer of registered streams */
 static struct stream_info *stream_table[SD_MAX];
 
+/* Lock for modifying the stream info table */
+static StaticSemaphore_t stream_table_lock_data;
+static SemaphoreHandle_t stream_table_lock;
+
 int stream_init()
 {
 	memset(stream_table, 0x00, sizeof(stream_table));
+	stream_table_lock =
+		xSemaphoreCreateMutexStatic(&stream_table_lock_data);
 	return 0;
 }
 
 int stream_register(int sd, struct stream_info *stream)
 {
+	if (xSemaphoreTake(stream_table_lock, STREAM_MUTEX_WAIT) != pdTRUE) {
+		return -EBUSY;
+	}
+
 	if (sd < 0 || sd >= SD_MAX) {
 		return -EINVAL;
 	}
@@ -23,11 +37,17 @@ int stream_register(int sd, struct stream_info *stream)
 	}
 
 	stream_table[sd] = stream;
+
+	xSemaphoreGive(stream_table_lock);
 	return 0;
 }
 
 int stream_deregister(int sd, struct stream_info *stream)
 {
+	if (xSemaphoreTake(stream_table_lock, STREAM_MUTEX_WAIT) != pdTRUE) {
+		return -EBUSY;
+	}
+
 	if (sd < 0 || sd >= SD_MAX) {
 		return -EINVAL;
 	}
@@ -38,11 +58,22 @@ int stream_deregister(int sd, struct stream_info *stream)
 	}
 
 	stream_table[sd] = NULL;
+
+	xSemaphoreGive(stream_table_lock);
 	return 0;
 }
 
 int epic_stream_read(int sd, void *buf, size_t count)
 {
+	/*
+	 * TODO: In theory, multiple reads on different streams can happen
+	 * simulaneously.  I don't know what the most efficient implementation
+	 * of this would look like.
+	 */
+	if (xSemaphoreTake(stream_table_lock, STREAM_MUTEX_WAIT) != pdTRUE) {
+		return -EBUSY;
+	}
+
 	if (sd < 0 || sd >= SD_MAX) {
 		return -EBADF;
 	}
@@ -72,5 +103,6 @@ int epic_stream_read(int sd, void *buf, size_t count)
 		}
 	}
 
+	xSemaphoreGive(stream_table_lock);
 	return i / stream->item_size;
 }
diff --git a/epicardium/modules/stream.h b/epicardium/modules/stream.h
index 622aee40..5bce8d56 100644
--- a/epicardium/modules/stream.h
+++ b/epicardium/modules/stream.h
@@ -7,6 +7,9 @@
 #include "FreeRTOS.h"
 #include "queue.h"
 
+/* Time to wait for the descriptor table lock to become available */
+#define STREAM_MUTEX_WAIT pdMS_TO_TICKS(100)
+
 /**
  * **Stream Descriptors**:
  *
-- 
GitLab