Skip to content
Snippets Groups Projects
Commit 198be023 authored by schneider's avatar schneider
Browse files

Merge branch 'schneider/stream-locks' into 'master'

fix(stream): Properly release locks

See merge request card10/firmware!224
parents d4ada0b7 d2958d41
No related branches found
No related tags found
1 merge request!224fix(stream): Properly release locks
Pipeline #3237 passed with warnings
...@@ -24,50 +24,63 @@ int stream_init() ...@@ -24,50 +24,63 @@ int stream_init()
int stream_register(int sd, struct stream_info *stream) int stream_register(int sd, struct stream_info *stream)
{ {
int ret = 0;
if (xSemaphoreTake(stream_table_lock, STREAM_MUTEX_WAIT) != pdTRUE) { if (xSemaphoreTake(stream_table_lock, STREAM_MUTEX_WAIT) != pdTRUE) {
LOG_WARN("stream", "Lock contention error"); LOG_WARN("stream", "Lock contention error");
return -EBUSY; ret = -EBUSY;
goto out;
} }
if (sd < 0 || sd >= SD_MAX) { if (sd < 0 || sd >= SD_MAX) {
return -EINVAL; ret = -EINVAL;
goto out_release;
} }
if (stream_table[sd] != NULL) { if (stream_table[sd] != NULL) {
/* Stream already registered */ /* Stream already registered */
return -EACCES; ret = -EACCES;
goto out_release;
} }
stream_table[sd] = stream; stream_table[sd] = stream;
out_release:
xSemaphoreGive(stream_table_lock); xSemaphoreGive(stream_table_lock);
return 0; out:
return ret;
} }
int stream_deregister(int sd, struct stream_info *stream) int stream_deregister(int sd, struct stream_info *stream)
{ {
int ret = 0;
if (xSemaphoreTake(stream_table_lock, STREAM_MUTEX_WAIT) != pdTRUE) { if (xSemaphoreTake(stream_table_lock, STREAM_MUTEX_WAIT) != pdTRUE) {
LOG_WARN("stream", "Lock contention error"); LOG_WARN("stream", "Lock contention error");
return -EBUSY; ret = -EBUSY;
goto out;
} }
if (sd < 0 || sd >= SD_MAX) { if (sd < 0 || sd >= SD_MAX) {
return -EINVAL; ret = -EINVAL;
goto out_release;
} }
if (stream_table[sd] != stream) { if (stream_table[sd] != stream) {
/* Stream registered by someone else */ /* Stream registered by someone else */
return -EACCES; ret = -EACCES;
goto out_release;
} }
stream_table[sd] = NULL; stream_table[sd] = NULL;
out_release:
xSemaphoreGive(stream_table_lock); xSemaphoreGive(stream_table_lock);
return 0; out:
return ret;
} }
int epic_stream_read(int sd, void *buf, size_t count) int epic_stream_read(int sd, void *buf, size_t count)
{ {
int ret = 0;
/* /*
* TODO: In theory, multiple reads on different streams can happen * TODO: In theory, multiple reads on different streams can happen
* simulaneously. I don't know what the most efficient implementation * simulaneously. I don't know what the most efficient implementation
...@@ -75,29 +88,33 @@ int epic_stream_read(int sd, void *buf, size_t count) ...@@ -75,29 +88,33 @@ int epic_stream_read(int sd, void *buf, size_t count)
*/ */
if (xSemaphoreTake(stream_table_lock, STREAM_MUTEX_WAIT) != pdTRUE) { if (xSemaphoreTake(stream_table_lock, STREAM_MUTEX_WAIT) != pdTRUE) {
LOG_WARN("stream", "Lock contention error"); LOG_WARN("stream", "Lock contention error");
return -EBUSY; ret = -EBUSY;
goto out;
} }
if (sd < 0 || sd >= SD_MAX) { if (sd < 0 || sd >= SD_MAX) {
return -EBADF; ret = -EBADF;
goto out_release;
} }
struct stream_info *stream = stream_table[sd]; struct stream_info *stream = stream_table[sd];
if (stream == NULL) { if (stream == NULL) {
return -ENODEV; ret = -ENODEV;
goto out_release;
} }
/* Poll the stream, if a poll_stream function exists */ /* Poll the stream, if a poll_stream function exists */
if (stream->poll_stream != NULL) { if (stream->poll_stream != NULL) {
int ret = stream->poll_stream(); int ret = stream->poll_stream();
if (ret < 0) { if (ret < 0) {
return ret; goto out_release;
} }
} }
/* Check buffer size is a multiple of the data packet size */ /* Check buffer size is a multiple of the data packet size */
if (count % stream->item_size != 0) { if (count % stream->item_size != 0) {
return -EINVAL; ret = -EINVAL;
goto out_release;
} }
size_t i; size_t i;
...@@ -107,6 +124,10 @@ int epic_stream_read(int sd, void *buf, size_t count) ...@@ -107,6 +124,10 @@ int epic_stream_read(int sd, void *buf, size_t count)
} }
} }
ret = i / stream->item_size;
out_release:
xSemaphoreGive(stream_table_lock); xSemaphoreGive(stream_table_lock);
return i / stream->item_size; out:
return ret;
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment