rendered paste bodydiff --git a/apps/buffering.c b/apps/buffering.cindex 0fd0c4c..5afb560 100644--- a/apps/buffering.c+++ b/apps/buffering.c@@ -116,6 +116,7 @@ struct memory_handle { size_t filerem; /* Remaining bytes of file NOT in buffer */ volatile size_t available; /* Available bytes to read from buffer */ size_t offset; /* Offset at which we started reading the file */+ struct mutex mutex; struct memory_handle *next; }; /* invariant: filesize == offset + available + filerem */@@ -272,6 +273,7 @@ static struct memory_handle *add_handle(size_t data_size, const bool can_wrap, /* only advance the buffer write index of the size of the struct */ buf_widx = RINGBUF_ADD(buf_widx, sizeof(struct memory_handle)); + mutex_init(&new_handle->mutex); new_handle->id = cur_handle_id; /* Use += 2 instead of ++ to guarantee that the low bit is always high and * prevent the assignment of a zero id when wrapping. */@@ -601,6 +603,8 @@ static void reset_handle(int handle_id) if (!h) return; + mutex_lock(&h->mutex);+ h->widx = h->data; if (h == cur_handle) buf_widx = h->widx;@@ -610,6 +614,8 @@ static void reset_handle(int handle_id) if (h->fd >= 0) { lseek(h->fd, h->offset, SEEK_SET); }++ mutex_unlock(&h->mutex); } /* Seek to a nonbuffered part of a handle by rebuffering the data. */@@ -619,7 +625,11 @@ static void rebuffer_handle(int handle_id, size_t newpos) if (!h) return; + DEBUGF("rebuffer_handle\n");++ mutex_lock(&h->mutex); h->offset = newpos;+ mutex_unlock(&h->mutex); LOGFQUEUE("? >| buffering Q_RESET_HANDLE"); queue_send(&buffering_queue, Q_RESET_HANDLE, handle_id);@@ -627,7 +637,9 @@ static void rebuffer_handle(int handle_id, size_t newpos) LOGFQUEUE("? >| buffering Q_BUFFER_HANDLE"); queue_send(&buffering_queue, Q_BUFFER_HANDLE, handle_id); + mutex_lock(&h->mutex); h->ridx = h->data;+ mutex_unlock(&h->mutex); } static bool close_handle(int handle_id)@@ -636,11 +648,15 @@ static bool close_handle(int handle_id) if (!h) return false; + mutex_lock(&h->mutex);+ if (h->fd >= 0) { close(h->fd); h->fd = -1; } + mutex_unlock(&h->mutex);+ rm_handle(h); return true; }@@ -651,22 +667,27 @@ static void shrink_handle(int handle_id) { size_t delta; struct memory_handle *h = find_handle(handle_id);- if (!h) return; + mutex_lock(&h->mutex);+ if (h->next && (h->type == TYPE_ID3 || h->type == TYPE_CUESHEET || h->type == TYPE_IMAGE) && h->filerem == 0 ) { /* metadata handle: we can move all of it */- size_t handle_distance = + size_t handle_distance = RINGBUF_SUB((unsigned)((void *)h->next - (void*)buffer), h->data); delta = handle_distance - h->available; + mutex_unlock(&h->mutex);+ /* The value of delta might change for alignment reasons */ h = move_handle(h, &delta, h->available); if (!h) return; + mutex_lock(&h->mutex);+ size_t olddata = h->data; h->data = RINGBUF_ADD(h->data, delta); h->ridx = RINGBUF_ADD(h->ridx, delta);@@ -683,13 +704,17 @@ static void shrink_handle(int handle_id) { /* only move the handle struct */ delta = RINGBUF_SUB(h->ridx, h->data);+ mutex_unlock(&h->mutex); h = move_handle(h, &delta, 0); if (!h) return; + mutex_lock(&h->mutex); h->data = RINGBUF_ADD(h->data, delta); h->available -= delta; h->offset += delta; }++ mutex_unlock(&h->mutex); } /* Fill the buffer by buffering as much data as possible for handles that still@@ -744,6 +769,7 @@ void update_data_counters(void) m = first_handle; while (m) {+ mutex_lock(&m->mutex); data_counters.buffered += m->available; data_counters.wasted += RINGBUF_SUB(m->ridx, m->data); data_counters.remaining += m->filerem;@@ -751,6 +777,7 @@ void update_data_counters(void) if (m->id >= base_handle_id) data_counters.useful += RINGBUF_SUB(m->widx, m->ridx); + mutex_unlock(&m->mutex); m = m->next; } }@@ -800,6 +827,8 @@ int bufopen(const char *file, size_t offset, enum data_type type) return BUFFER_FULL; } + mutex_lock(&h->mutex);+ strncpy(h->path, file, MAX_PATH); h->filesize = size; h->filerem = size - offset;@@ -822,6 +851,8 @@ int bufopen(const char *file, size_t offset, enum data_type type) } logf("bufopen: new hdl %d", h->id);++ mutex_unlock(&h->mutex); return h->id; } @@ -842,6 +873,8 @@ int bufalloc(const void *src, size_t size, enum data_type type) if (!h) return BUFFER_FULL; + mutex_lock(&h->mutex);+ if (src) { if (type == TYPE_ID3 && size == sizeof(struct mp3entry)) { /* specially take care of struct mp3entry */@@ -866,6 +899,8 @@ int bufalloc(const void *src, size_t size, enum data_type type) buf_widx += size; /* safe too */ logf("bufalloc: new hdl %d", h->id);++ mutex_unlock(&h->mutex); return h->id; } @@ -890,8 +925,11 @@ int bufseek(int handle_id, size_t newpos) if (!h) return HANDLE_NOT_FOUND; + mutex_lock(&h->mutex);+ if (newpos > h->filesize) { /* access beyond the end of the file */+ mutex_unlock(&h->mutex); return INVALID_VALUE; } else if (newpos < h->offset || h->offset + h->available < newpos) {@@ -901,6 +939,8 @@ int bufseek(int handle_id, size_t newpos) else { h->ridx = RINGBUF_ADD(h->data, newpos - h->offset); }++ mutex_unlock(&h->mutex); return 0; } @@ -908,36 +948,51 @@ int bufseek(int handle_id, size_t newpos) Return 0 for success and < 0 for failure */ int bufadvance(int handle_id, off_t offset) {- const struct memory_handle *h = find_handle(handle_id);+ int ret;+ struct memory_handle *h = find_handle(handle_id); if (!h) return HANDLE_NOT_FOUND; + mutex_lock(&h->mutex); size_t newpos = h->offset + RINGBUF_SUB(h->ridx, h->data) + offset;- return bufseek(handle_id, newpos);+ ret = bufseek(handle_id, newpos);+ mutex_unlock(&h->mutex);+ return ret; } /* Copy data from the given handle to the dest buffer. Return the number of bytes copied or < 0 for failure. */ ssize_t bufread(int handle_id, size_t size, void *dest) {- const struct memory_handle *h = find_handle(handle_id);+ struct memory_handle *h = find_handle(handle_id); if (!h) return HANDLE_NOT_FOUND; + mutex_lock(&h->mutex);+ size_t ret; size_t copy_n = RINGBUF_SUB(h->widx, h->ridx); if (size == 0 && h->filerem > 0 && copy_n == 0)+ { /* Data isn't ready */+ mutex_unlock(&h->mutex); return DATA_NOT_READY;+ } if (copy_n < size && h->filerem > 0)+ { /* Data isn't ready */+ mutex_unlock(&h->mutex); return DATA_NOT_READY;+ } if (copy_n == 0 && h->filerem == 0)+ { /* File is finished reading */+ mutex_unlock(&h->mutex); return 0;+ } ret = MIN(size, copy_n); @@ -953,6 +1008,7 @@ ssize_t bufread(int handle_id, size_t size, void *dest) memcpy(dest, &buffer[h->ridx], ret); } + mutex_unlock(&h->mutex); return ret; } @@ -963,24 +1019,35 @@ ssize_t bufread(int handle_id, size_t size, void *dest) The guard buffer may be used to provide the requested size */ ssize_t bufgetdata(int handle_id, size_t size, void **data) {- const struct memory_handle *h = find_handle(handle_id);+ struct memory_handle *h = find_handle(handle_id); if (!h) return HANDLE_NOT_FOUND; + mutex_lock(&h->mutex);+ ssize_t ret; size_t copy_n = RINGBUF_SUB(h->widx, h->ridx); if (size == 0 && h->filerem > 0 && copy_n == 0)+ { /* Data isn't ready */+ mutex_unlock(&h->mutex); return DATA_NOT_READY;+ } if (copy_n < size && h->filerem > 0)+ { /* Data isn't ready */+ mutex_unlock(&h->mutex); return DATA_NOT_READY;+ } if (copy_n == 0 && h->filerem == 0)+ { /* File is finished reading */+ mutex_unlock(&h->mutex); return 0;+ } if (h->ridx + size > buffer_len && copy_n >= size) {@@ -996,6 +1063,7 @@ ssize_t bufgetdata(int handle_id, size_t size, void **data) } *data = &buffer[h->ridx];+ mutex_unlock(&h->mutex); return ret; } @@ -1019,19 +1087,28 @@ management functions for all the actual handle management work. /* Get a handle offset from a pointer */ ssize_t buf_get_offset(int handle_id, void *ptr) {- const struct memory_handle *h = find_handle(handle_id);+ ssize_t ret;+ struct memory_handle *h = find_handle(handle_id); if (!h) return HANDLE_NOT_FOUND; - return (size_t)ptr - (size_t)&buffer[h->ridx];+ mutex_lock(&h->mutex);+ ret = (size_t)ptr - (size_t)&buffer[h->ridx];+ mutex_unlock(&h->mutex);+ return ret; } ssize_t buf_handle_offset(int handle_id) {- const struct memory_handle *h = find_handle(handle_id);+ ssize_t ret;+ struct memory_handle *h = find_handle(handle_id); if (!h) return HANDLE_NOT_FOUND;- return h->offset;++ mutex_lock(&h->mutex);+ ret = h->offset;+ mutex_unlock(&h->mutex);+ return ret; } void buf_request_buffer_handle(int handle_id)