summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2011-02-14 08:36:29 +0000
committerMichael Sevakis <jethead71@rockbox.org>2011-02-14 08:36:29 +0000
commit6938255b6b99f353652149057b5fe94fd0bb8f5d (patch)
tree49f2f613f7614654e90dd6b2c8508c1acced3d52
parent0fde635fb0c00641f372dfce14aff29c40e4398e (diff)
downloadrockbox-6938255b6b99f353652149057b5fe94fd0bb8f5d.tar.gz
rockbox-6938255b6b99f353652149057b5fe94fd0bb8f5d.zip
Buffering: tin cup. Update threading structure and handle rebuffer more reliably on buffer thread using a single message send.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29303 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/buffering.c583
1 files changed, 319 insertions, 264 deletions
diff --git a/apps/buffering.c b/apps/buffering.c
index f4eaf8a051..be6cf44aed 100644
--- a/apps/buffering.c
+++ b/apps/buffering.c
@@ -96,11 +96,9 @@ struct memory_handle {
96 enum data_type type; /* Type of data buffered with this handle */ 96 enum data_type type; /* Type of data buffered with this handle */
97 char path[MAX_PATH]; /* Path if data originated in a file */ 97 char path[MAX_PATH]; /* Path if data originated in a file */
98 int fd; /* File descriptor to path (-1 if closed) */ 98 int fd; /* File descriptor to path (-1 if closed) */
99 size_t start; /* Start index of the handle's data buffer, 99 size_t data; /* Start index of the handle's data buffer */
100 for use by reset_handle. */
101 size_t data; /* Start index of the handle's data */
102 volatile size_t ridx; /* Read pointer, relative to the main buffer */ 100 volatile size_t ridx; /* Read pointer, relative to the main buffer */
103 size_t widx; /* Write pointer */ 101 size_t widx; /* Write pointer, relative to the main buffer */
104 size_t filesize; /* File total length */ 102 size_t filesize; /* File total length */
105 size_t filerem; /* Remaining bytes of file NOT in buffer */ 103 size_t filerem; /* Remaining bytes of file NOT in buffer */
106 volatile size_t available; /* Available bytes to read from buffer */ 104 volatile size_t available; /* Available bytes to read from buffer */
@@ -109,6 +107,13 @@ struct memory_handle {
109}; 107};
110/* invariant: filesize == offset + available + filerem */ 108/* invariant: filesize == offset + available + filerem */
111 109
110
111struct buf_message_data
112{
113 int handle_id;
114 intptr_t data;
115};
116
112static char *buffer; 117static char *buffer;
113static char *guard_buffer; 118static char *guard_buffer;
114 119
@@ -133,14 +138,14 @@ static int num_handles; /* number of handles in the list */
133 138
134static int base_handle_id; 139static int base_handle_id;
135 140
136static struct mutex llist_mutex; 141/* Main lock for adding / removing handles */
137static struct mutex llist_mod_mutex; 142static struct mutex llist_mutex SHAREDBSS_ATTR;
138 143
139/* Handle cache (makes find_handle faster). 144/* Handle cache (makes find_handle faster).
140 This is global so that move_handle and rm_handle can invalidate it. */ 145 This is global so that move_handle and rm_handle can invalidate it. */
141static struct memory_handle *cached_handle = NULL; 146static struct memory_handle *cached_handle = NULL;
142 147
143static struct { 148static struct data_counters {
144 size_t remaining; /* Amount of data needing to be buffered */ 149 size_t remaining; /* Amount of data needing to be buffered */
145 size_t wasted; /* Amount of space available for freeing */ 150 size_t wasted; /* Amount of space available for freeing */
146 size_t buffered; /* Amount of data currently in the buffer */ 151 size_t buffered; /* Amount of data currently in the buffer */
@@ -152,8 +157,8 @@ static struct {
152enum { 157enum {
153 Q_BUFFER_HANDLE = 1, /* Request buffering of a handle, this should not be 158 Q_BUFFER_HANDLE = 1, /* Request buffering of a handle, this should not be
154 used in a low buffer situation. */ 159 used in a low buffer situation. */
155 Q_RESET_HANDLE, /* (internal) Request resetting of a handle to its 160 Q_REBUFFER_HANDLE, /* Request reset and rebuffering of a handle at a new
156 offset (the offset has to be set beforehand) */ 161 file starting position. */
157 Q_CLOSE_HANDLE, /* Request closing a handle */ 162 Q_CLOSE_HANDLE, /* Request closing a handle */
158 Q_BASE_HANDLE, /* Set the reference handle for buf_useful_data */ 163 Q_BASE_HANDLE, /* Set the reference handle for buf_useful_data */
159 164
@@ -257,9 +262,6 @@ static struct memory_handle *add_handle(size_t data_size, bool can_wrap,
257 if (num_handles >= BUF_MAX_HANDLES) 262 if (num_handles >= BUF_MAX_HANDLES)
258 return NULL; 263 return NULL;
259 264
260 mutex_lock(&llist_mutex);
261 mutex_lock(&llist_mod_mutex);
262
263 widx = buf_widx; 265 widx = buf_widx;
264 266
265 if (cur_handle && cur_handle->filerem > 0) { 267 if (cur_handle && cur_handle->filerem > 0) {
@@ -269,8 +271,6 @@ static struct memory_handle *add_handle(size_t data_size, bool can_wrap,
269 size_t req = cur_handle->filerem; 271 size_t req = cur_handle->filerem;
270 if (ringbuf_add_cross(cur_handle->widx, req, buf_ridx) >= 0) { 272 if (ringbuf_add_cross(cur_handle->widx, req, buf_ridx) >= 0) {
271 /* Not enough space to finish allocation */ 273 /* Not enough space to finish allocation */
272 mutex_unlock(&llist_mod_mutex);
273 mutex_unlock(&llist_mutex);
274 return NULL; 274 return NULL;
275 } else { 275 } else {
276 /* Allocate the remainder of the space for the current handle */ 276 /* Allocate the remainder of the space for the current handle */
@@ -298,8 +298,6 @@ static struct memory_handle *add_handle(size_t data_size, bool can_wrap,
298 overlap = ringbuf_add_cross(widx, shift + len, buf_ridx); 298 overlap = ringbuf_add_cross(widx, shift + len, buf_ridx);
299 if (overlap >= 0 && (alloc_all || (size_t)overlap >= data_size)) { 299 if (overlap >= 0 && (alloc_all || (size_t)overlap >= data_size)) {
300 /* Not enough space for required allocations */ 300 /* Not enough space for required allocations */
301 mutex_unlock(&llist_mod_mutex);
302 mutex_unlock(&llist_mutex);
303 return NULL; 301 return NULL;
304 } 302 }
305 303
@@ -310,6 +308,9 @@ static struct memory_handle *add_handle(size_t data_size, bool can_wrap,
310 struct memory_handle *new_handle = 308 struct memory_handle *new_handle =
311 (struct memory_handle *)(&buffer[buf_widx]); 309 (struct memory_handle *)(&buffer[buf_widx]);
312 310
311 /* Prevent buffering thread from looking at it */
312 new_handle->filerem = 0;
313
313 /* only advance the buffer write index of the size of the struct */ 314 /* only advance the buffer write index of the size of the struct */
314 buf_widx = ringbuf_add(buf_widx, sizeof(struct memory_handle)); 315 buf_widx = ringbuf_add(buf_widx, sizeof(struct memory_handle));
315 316
@@ -328,8 +329,6 @@ static struct memory_handle *add_handle(size_t data_size, bool can_wrap,
328 329
329 cur_handle = new_handle; 330 cur_handle = new_handle;
330 331
331 mutex_unlock(&llist_mod_mutex);
332 mutex_unlock(&llist_mutex);
333 return new_handle; 332 return new_handle;
334} 333}
335 334
@@ -340,9 +339,6 @@ static bool rm_handle(const struct memory_handle *h)
340 if (h == NULL) 339 if (h == NULL)
341 return true; 340 return true;
342 341
343 mutex_lock(&llist_mutex);
344 mutex_lock(&llist_mod_mutex);
345
346 if (h == first_handle) { 342 if (h == first_handle) {
347 first_handle = h->next; 343 first_handle = h->next;
348 if (h == cur_handle) { 344 if (h == cur_handle) {
@@ -366,8 +362,6 @@ static bool rm_handle(const struct memory_handle *h)
366 buf_widx = cur_handle->widx; 362 buf_widx = cur_handle->widx;
367 } 363 }
368 } else { 364 } else {
369 mutex_unlock(&llist_mod_mutex);
370 mutex_unlock(&llist_mutex);
371 return false; 365 return false;
372 } 366 }
373 } 367 }
@@ -377,9 +371,6 @@ static bool rm_handle(const struct memory_handle *h)
377 cached_handle = NULL; 371 cached_handle = NULL;
378 372
379 num_handles--; 373 num_handles--;
380
381 mutex_unlock(&llist_mod_mutex);
382 mutex_unlock(&llist_mutex);
383 return true; 374 return true;
384} 375}
385 376
@@ -390,19 +381,15 @@ static struct memory_handle *find_handle(int handle_id)
390 if (handle_id < 0) 381 if (handle_id < 0)
391 return NULL; 382 return NULL;
392 383
393 mutex_lock(&llist_mutex);
394
395 /* simple caching because most of the time the requested handle 384 /* simple caching because most of the time the requested handle
396 will either be the same as the last, or the one after the last */ 385 will either be the same as the last, or the one after the last */
397 if (cached_handle) 386 if (cached_handle)
398 { 387 {
399 if (cached_handle->id == handle_id) { 388 if (cached_handle->id == handle_id) {
400 mutex_unlock(&llist_mutex);
401 return cached_handle; 389 return cached_handle;
402 } else if (cached_handle->next && 390 } else if (cached_handle->next &&
403 (cached_handle->next->id == handle_id)) { 391 (cached_handle->next->id == handle_id)) {
404 cached_handle = cached_handle->next; 392 cached_handle = cached_handle->next;
405 mutex_unlock(&llist_mutex);
406 return cached_handle; 393 return cached_handle;
407 } 394 }
408 } 395 }
@@ -415,7 +402,6 @@ static struct memory_handle *find_handle(int handle_id)
415 if (m) 402 if (m)
416 cached_handle = m; 403 cached_handle = m;
417 404
418 mutex_unlock(&llist_mutex);
419 return m; 405 return m;
420} 406}
421 407
@@ -449,9 +435,6 @@ static bool move_handle(struct memory_handle **h, size_t *delta,
449 return false; 435 return false;
450 } 436 }
451 437
452 mutex_lock(&llist_mutex);
453 mutex_lock(&llist_mod_mutex);
454
455 oldpos = ringbuf_offset(src); 438 oldpos = ringbuf_offset(src);
456 newpos = ringbuf_add(oldpos, final_delta); 439 newpos = ringbuf_add(oldpos, final_delta);
457 overlap = ringbuf_add_cross(newpos, size_to_move, buffer_len); 440 overlap = ringbuf_add_cross(newpos, size_to_move, buffer_len);
@@ -477,8 +460,6 @@ static bool move_handle(struct memory_handle **h, size_t *delta,
477 correction = (correction + 3) & ~3; 460 correction = (correction + 3) & ~3;
478 if (final_delta < correction + sizeof(struct memory_handle)) { 461 if (final_delta < correction + sizeof(struct memory_handle)) {
479 /* Delta cannot end up less than the size of the struct */ 462 /* Delta cannot end up less than the size of the struct */
480 mutex_unlock(&llist_mod_mutex);
481 mutex_unlock(&llist_mutex);
482 return false; 463 return false;
483 } 464 }
484 newpos -= correction; 465 newpos -= correction;
@@ -500,8 +481,6 @@ static bool move_handle(struct memory_handle **h, size_t *delta,
500 if (m && m->next == src) { 481 if (m && m->next == src) {
501 m->next = dest; 482 m->next = dest;
502 } else { 483 } else {
503 mutex_unlock(&llist_mod_mutex);
504 mutex_unlock(&llist_mutex);
505 return false; 484 return false;
506 } 485 }
507 } 486 }
@@ -562,8 +541,6 @@ static bool move_handle(struct memory_handle **h, size_t *delta,
562 /* Update the caller with the new location of h and the distance moved */ 541 /* Update the caller with the new location of h and the distance moved */
563 *h = dest; 542 *h = dest;
564 *delta = final_delta; 543 *delta = final_delta;
565 mutex_unlock(&llist_mod_mutex);
566 mutex_unlock(&llist_mutex);
567 return true; 544 return true;
568} 545}
569 546
@@ -575,7 +552,6 @@ BUFFER SPACE MANAGEMENT
575update_data_counters: Updates the values in data_counters 552update_data_counters: Updates the values in data_counters
576buffer_is_low : Returns true if the amount of useful data in the buffer is low 553buffer_is_low : Returns true if the amount of useful data in the buffer is low
577buffer_handle : Buffer data for a handle 554buffer_handle : Buffer data for a handle
578reset_handle : Reset write position and data buffer of a handle to its offset
579rebuffer_handle : Seek to a nonbuffered part of a handle by rebuffering the data 555rebuffer_handle : Seek to a nonbuffered part of a handle by rebuffering the data
580shrink_handle : Free buffer space by moving a handle 556shrink_handle : Free buffer space by moving a handle
581fill_buffer : Call buffer_handle for all handles that have data to buffer 557fill_buffer : Call buffer_handle for all handles that have data to buffer
@@ -583,18 +559,24 @@ fill_buffer : Call buffer_handle for all handles that have data to buffer
583These functions are used by the buffering thread to manage buffer space. 559These functions are used by the buffering thread to manage buffer space.
584*/ 560*/
585 561
586static void update_data_counters(void) 562static void update_data_counters(struct data_counters *dc)
587{ 563{
588 struct memory_handle *m = find_handle(base_handle_id);
589 bool is_useful = m==NULL;
590
591 size_t buffered = 0; 564 size_t buffered = 0;
592 size_t wasted = 0; 565 size_t wasted = 0;
593 size_t remaining = 0; 566 size_t remaining = 0;
594 size_t useful = 0; 567 size_t useful = 0;
595 568
569 struct memory_handle *m;
570 bool is_useful;
571
572 if (dc == NULL)
573 dc = &data_counters;
574
596 mutex_lock(&llist_mutex); 575 mutex_lock(&llist_mutex);
597 576
577 m = find_handle(base_handle_id);
578 is_useful = m == NULL;
579
598 m = first_handle; 580 m = first_handle;
599 while (m) { 581 while (m) {
600 buffered += m->available; 582 buffered += m->available;
@@ -612,21 +594,21 @@ static void update_data_counters(void)
612 594
613 mutex_unlock(&llist_mutex); 595 mutex_unlock(&llist_mutex);
614 596
615 data_counters.buffered = buffered; 597 dc->buffered = buffered;
616 data_counters.wasted = wasted; 598 dc->wasted = wasted;
617 data_counters.remaining = remaining; 599 dc->remaining = remaining;
618 data_counters.useful = useful; 600 dc->useful = useful;
619} 601}
620 602
621static inline bool buffer_is_low(void) 603static inline bool buffer_is_low(void)
622{ 604{
623 update_data_counters(); 605 update_data_counters(NULL);
624 return data_counters.useful < (conf_watermark / 2); 606 return data_counters.useful < (conf_watermark / 2);
625} 607}
626 608
627/* Buffer data for the given handle. 609/* Q_BUFFER_HANDLE event and buffer data for the given handle.
628 Return whether or not the buffering should continue explicitly. */ 610 Return whether or not the buffering should continue explicitly. */
629static bool buffer_handle(int handle_id) 611static bool buffer_handle(int handle_id, size_t to_buffer)
630{ 612{
631 logf("buffer_handle(%d)", handle_id); 613 logf("buffer_handle(%d)", handle_id);
632 struct memory_handle *h = find_handle(handle_id); 614 struct memory_handle *h = find_handle(handle_id);
@@ -671,7 +653,7 @@ static bool buffer_handle(int handle_id)
671 h->filerem = 0; 653 h->filerem = 0;
672 h->available = sizeof(struct mp3entry); 654 h->available = sizeof(struct mp3entry);
673 h->widx += sizeof(struct mp3entry); 655 h->widx += sizeof(struct mp3entry);
674 send_event(BUFFER_EVENT_FINISHED, &h->id); 656 send_event(BUFFER_EVENT_FINISHED, &handle_id);
675 return true; 657 return true;
676 } 658 }
677 659
@@ -730,113 +712,53 @@ static bool buffer_handle(int handle_id)
730 yield(); 712 yield();
731 } 713 }
732 714
733 if (!queue_empty(&buffering_queue)) 715 if (to_buffer == 0)
734 break; 716 {
717 /* Normal buffering - check queue */
718 if(!queue_empty(&buffering_queue))
719 break;
720 }
721 else
722 {
723 if (to_buffer <= (size_t)rc)
724 break; /* Done */
725 to_buffer -= rc;
726 }
735 } 727 }
736 728
737 if (h->filerem == 0) { 729 if (h->filerem == 0) {
738 /* finished buffering the file */ 730 /* finished buffering the file */
739 close(h->fd); 731 close(h->fd);
740 h->fd = -1; 732 h->fd = -1;
741 send_event(BUFFER_EVENT_FINISHED, &h->id); 733 send_event(BUFFER_EVENT_FINISHED, &handle_id);
742 } 734 }
743 735
744 return !stop; 736 return !stop;
745} 737}
746 738
747/* Reset writing position and data buffer of a handle to its current offset. 739/* Close the specified handle id and free its allocation. */
748 Use this after having set the new offset to use. */
749static void reset_handle(int handle_id)
750{
751 size_t new_index;
752
753 logf("reset_handle(%d)", handle_id);
754
755 struct memory_handle *h = find_handle(handle_id);
756 if (!h)
757 return;
758
759 new_index = h->start;
760
761#ifdef STORAGE_WANTS_ALIGN
762 /* Align to desired storage alignment if space permits - handle could have
763 been shrunken too close to the following one after a previous rebuffer. */
764 size_t alignment_pad = STORAGE_OVERLAP(h->offset - (size_t)(&buffer[new_index]));
765 size_t offset = h->next ? ringbuf_offset(h->next) : buf_ridx;
766
767 if (ringbuf_add_cross(new_index, alignment_pad, offset) >= 0) {
768 /* Forego storage alignment this time */
769 alignment_pad = 0;
770 }
771
772 new_index = ringbuf_add(new_index, alignment_pad);
773#endif
774
775 h->ridx = h->widx = h->data = new_index;
776
777 if (h == cur_handle)
778 buf_widx = new_index;
779
780 h->available = 0;
781 h->filerem = h->filesize - h->offset;
782
783 if (h->fd >= 0) {
784 lseek(h->fd, h->offset, SEEK_SET);
785 }
786}
787
788/* Seek to a nonbuffered part of a handle by rebuffering the data. */
789static void rebuffer_handle(int handle_id, size_t newpos)
790{
791 struct memory_handle *h = find_handle(handle_id);
792 if (!h)
793 return;
794
795 /* When seeking foward off of the buffer, if it is a short seek don't
796 rebuffer the whole track, just read enough to satisfy */
797 if (newpos > h->offset && newpos - h->offset < BUFFERING_DEFAULT_FILECHUNK)
798 {
799 LOGFQUEUE("buffering >| Q_BUFFER_HANDLE %d", handle_id);
800 queue_send(&buffering_queue, Q_BUFFER_HANDLE, handle_id);
801 h->ridx = ringbuf_add(h->data, newpos - h->offset);
802 return;
803 }
804
805 h->offset = newpos;
806
807 /* Reset the handle to its new offset */
808 LOGFQUEUE("buffering >| Q_RESET_HANDLE %d", handle_id);
809 queue_send(&buffering_queue, Q_RESET_HANDLE, handle_id);
810
811 uintptr_t next = ringbuf_offset(h->next);
812 if (ringbuf_sub(next, h->data) < h->filesize - newpos)
813 {
814 /* There isn't enough space to rebuffer all of the track from its new
815 offset, so we ask the user to free some */
816 DEBUGF("%s(): space is needed\n", __func__);
817 send_event(BUFFER_EVENT_REBUFFER, &handle_id);
818 }
819
820 /* Now we ask for a rebuffer */
821 LOGFQUEUE("buffering >| Q_BUFFER_HANDLE %d", handle_id);
822 queue_send(&buffering_queue, Q_BUFFER_HANDLE, handle_id);
823}
824
825static bool close_handle(int handle_id) 740static bool close_handle(int handle_id)
826{ 741{
827 struct memory_handle *h = find_handle(handle_id); 742 bool retval = true;
743 struct memory_handle *h;
744
745 mutex_lock(&llist_mutex);
746 h = find_handle(handle_id);
828 747
829 /* If the handle is not found, it is closed */ 748 /* If the handle is not found, it is closed */
830 if (!h) 749 if (h) {
831 return true; 750 if (h->fd >= 0) {
751 close(h->fd);
752 h->fd = -1;
753 }
832 754
833 if (h->fd >= 0) { 755 /* rm_handle returns true unless the handle somehow persists after
834 close(h->fd); 756 exit */
835 h->fd = -1; 757 retval = rm_handle(h);
836 } 758 }
837 759
838 /* rm_handle returns true unless the handle somehow persists after exit */ 760 mutex_unlock(&llist_mutex);
839 return rm_handle(h); 761 return retval;
840} 762}
841 763
842/* Free buffer space by moving the handle struct right before the useful 764/* Free buffer space by moving the handle struct right before the useful
@@ -888,7 +810,6 @@ static void shrink_handle(struct memory_handle *h)
888 return; 810 return;
889 811
890 h->data = ringbuf_add(h->data, delta); 812 h->data = ringbuf_add(h->data, delta);
891 h->start = ringbuf_add(h->start, delta);
892 h->available -= delta; 813 h->available -= delta;
893 h->offset += delta; 814 h->offset += delta;
894 } 815 }
@@ -900,12 +821,13 @@ static void shrink_handle(struct memory_handle *h)
900static bool fill_buffer(void) 821static bool fill_buffer(void)
901{ 822{
902 logf("fill_buffer()"); 823 logf("fill_buffer()");
903 struct memory_handle *m; 824 struct memory_handle *m = first_handle;
904 shrink_handle(first_handle); 825
905 m = first_handle; 826 shrink_handle(m);
827
906 while (queue_empty(&buffering_queue) && m) { 828 while (queue_empty(&buffering_queue) && m) {
907 if (m->filerem > 0) { 829 if (m->filerem > 0) {
908 if (!buffer_handle(m->id)) { 830 if (!buffer_handle(m->id, 0)) {
909 m = NULL; 831 m = NULL;
910 break; 832 break;
911 } 833 }
@@ -990,7 +912,7 @@ management functions for all the actual handle management work.
990/* Reserve space in the buffer for a file. 912/* Reserve space in the buffer for a file.
991 filename: name of the file to open 913 filename: name of the file to open
992 offset: offset at which to start buffering the file, useful when the first 914 offset: offset at which to start buffering the file, useful when the first
993 (offset-1) bytes of the file aren't needed. 915 offset bytes of the file aren't needed.
994 type: one of the data types supported (audio, image, cuesheet, others 916 type: one of the data types supported (audio, image, cuesheet, others
995 user_data: user data passed possibly passed in subcalls specific to a 917 user_data: user data passed possibly passed in subcalls specific to a
996 data_type (only used for image (albumart) buffering so far ) 918 data_type (only used for image (albumart) buffering so far )
@@ -1004,33 +926,40 @@ int bufopen(const char *file, size_t offset, enum data_type type,
1004 /* currently only used for aa loading */ 926 /* currently only used for aa loading */
1005 (void)user_data; 927 (void)user_data;
1006#endif 928#endif
929 int handle_id = ERR_BUFFER_FULL;
930
931 /* No buffer refs until after the mutex_lock call! */
932
1007 if (type == TYPE_ID3) 933 if (type == TYPE_ID3)
1008 { 934 {
1009 /* ID3 case: allocate space, init the handle and return. */ 935 /* ID3 case: allocate space, init the handle and return. */
936 mutex_lock(&llist_mutex);
1010 937
1011 struct memory_handle *h = add_handle(sizeof(struct mp3entry), false, true); 938 struct memory_handle *h = add_handle(sizeof(struct mp3entry), false, true);
1012 if (!h) 939 if (h)
1013 return ERR_BUFFER_FULL; 940 {
1014 941 handle_id = h->id;
1015 h->fd = -1; 942 h->fd = -1;
1016 h->filesize = sizeof(struct mp3entry); 943 h->filesize = sizeof(struct mp3entry);
1017 h->filerem = sizeof(struct mp3entry); 944 h->offset = 0;
1018 h->offset = 0; 945 h->data = buf_widx;
1019 h->data = buf_widx; 946 h->ridx = buf_widx;
1020 h->ridx = buf_widx; 947 h->widx = buf_widx;
1021 h->widx = buf_widx; 948 h->available = 0;
1022 h->available = 0; 949 h->type = type;
1023 h->type = type; 950 strlcpy(h->path, file, MAX_PATH);
1024 strlcpy(h->path, file, MAX_PATH); 951
1025 952 buf_widx += sizeof(struct mp3entry); /* safe because the handle
1026 buf_widx += sizeof(struct mp3entry); /* safe because the handle 953 can't wrap */
1027 can't wrap */ 954 h->filerem = sizeof(struct mp3entry);
1028 955
1029 /* Inform the buffering thread that we added a handle */ 956 /* Inform the buffering thread that we added a handle */
1030 LOGFQUEUE("buffering > Q_HANDLE_ADDED %d", h->id); 957 LOGFQUEUE("buffering > Q_HANDLE_ADDED %d", handle_id);
1031 queue_post(&buffering_queue, Q_HANDLE_ADDED, h->id); 958 queue_post(&buffering_queue, Q_HANDLE_ADDED, handle_id);
959 }
1032 960
1033 return h->id; 961 mutex_unlock(&llist_mutex);
962 return handle_id;
1034 } 963 }
1035#ifdef APPLICATION 964#ifdef APPLICATION
1036 /* loading code from memory is not supported in application builds */ 965 /* loading code from memory is not supported in application builds */
@@ -1062,37 +991,40 @@ int bufopen(const char *file, size_t offset, enum data_type type,
1062 991
1063 /* Reserve extra space because alignment can move data forward */ 992 /* Reserve extra space because alignment can move data forward */
1064 size_t padded_size = STORAGE_PAD(size-adjusted_offset); 993 size_t padded_size = STORAGE_PAD(size-adjusted_offset);
994
995 mutex_lock(&llist_mutex);
996
1065 struct memory_handle *h = add_handle(padded_size, can_wrap, false); 997 struct memory_handle *h = add_handle(padded_size, can_wrap, false);
1066 if (!h) 998 if (!h)
1067 { 999 {
1068 DEBUGF("%s(): failed to add handle\n", __func__); 1000 DEBUGF("%s(): failed to add handle\n", __func__);
1001 mutex_unlock(&llist_mutex);
1069 close(fd); 1002 close(fd);
1070 return ERR_BUFFER_FULL; 1003 return ERR_BUFFER_FULL;
1071 } 1004 }
1072 1005
1006 handle_id = h->id;
1073 strlcpy(h->path, file, MAX_PATH); 1007 strlcpy(h->path, file, MAX_PATH);
1074 h->offset = adjusted_offset; 1008 h->offset = adjusted_offset;
1075 1009
1010#ifdef STORAGE_WANTS_ALIGN
1076 /* Don't bother to storage align bitmaps because they are not 1011 /* Don't bother to storage align bitmaps because they are not
1077 * loaded directly into the buffer. 1012 * loaded directly into the buffer.
1078 */ 1013 */
1079 if (type != TYPE_BITMAP) 1014 if (type != TYPE_BITMAP)
1080 { 1015 {
1081 size_t alignment_pad;
1082
1083 /* Remember where data area starts, for use by reset_handle */
1084 h->start = buf_widx;
1085
1086 /* Align to desired storage alignment */ 1016 /* Align to desired storage alignment */
1087 alignment_pad = STORAGE_OVERLAP(adjusted_offset - (size_t)(&buffer[buf_widx])); 1017 size_t alignment_pad = STORAGE_OVERLAP(adjusted_offset -
1018 (size_t)(&buffer[buf_widx]));
1088 buf_widx = ringbuf_add(buf_widx, alignment_pad); 1019 buf_widx = ringbuf_add(buf_widx, alignment_pad);
1089 } 1020 }
1021#endif /* STORAGE_WANTS_ALIGN */
1090 1022
1023 h->fd = -1;
1024 h->data = buf_widx;
1091 h->ridx = buf_widx; 1025 h->ridx = buf_widx;
1092 h->widx = buf_widx; 1026 h->widx = buf_widx;
1093 h->data = buf_widx;
1094 h->available = 0; 1027 h->available = 0;
1095 h->filerem = 0;
1096 h->type = type; 1028 h->type = type;
1097 1029
1098#ifdef HAVE_ALBUMART 1030#ifdef HAVE_ALBUMART
@@ -1100,47 +1032,55 @@ int bufopen(const char *file, size_t offset, enum data_type type,
1100 { 1032 {
1101 /* Bitmap file: we load the data instead of the file */ 1033 /* Bitmap file: we load the data instead of the file */
1102 int rc; 1034 int rc;
1103 mutex_lock(&llist_mod_mutex); /* Lock because load_bitmap yields */
1104 rc = load_image(fd, file, (struct bufopen_bitmap_data*)user_data); 1035 rc = load_image(fd, file, (struct bufopen_bitmap_data*)user_data);
1105 mutex_unlock(&llist_mod_mutex);
1106 if (rc <= 0) 1036 if (rc <= 0)
1107 { 1037 {
1108 rm_handle(h); 1038 rm_handle(h);
1109 close(fd); 1039 handle_id = ERR_FILE_ERROR;
1110 return ERR_FILE_ERROR; 1040 }
1041 else
1042 {
1043 h->filesize = rc;
1044 h->available = rc;
1045 h->widx = buf_widx + rc; /* safe because the data doesn't wrap */
1046 buf_widx += rc; /* safe too */
1111 } 1047 }
1112 h->filerem = 0;
1113 h->filesize = rc;
1114 h->available = rc;
1115 h->widx = buf_widx + rc; /* safe because the data doesn't wrap */
1116 buf_widx += rc; /* safe too */
1117 } 1048 }
1118 else 1049 else
1119#endif 1050#endif
1120 { 1051 {
1121 h->filerem = size - adjusted_offset; 1052 if (type == TYPE_CUESHEET)
1053 h->fd = fd;
1054
1122 h->filesize = size; 1055 h->filesize = size;
1123 h->available = 0; 1056 h->available = 0;
1124 h->widx = buf_widx; 1057 h->widx = buf_widx;
1058 h->filerem = size - adjusted_offset;
1125 } 1059 }
1126 1060
1127 if (type == TYPE_CUESHEET) { 1061 mutex_unlock(&llist_mutex);
1128 h->fd = fd; 1062
1063 if (type == TYPE_CUESHEET)
1064 {
1129 /* Immediately start buffering those */ 1065 /* Immediately start buffering those */
1130 LOGFQUEUE("buffering >| Q_BUFFER_HANDLE %d", h->id); 1066 LOGFQUEUE("buffering >| Q_BUFFER_HANDLE %d", handle_id);
1131 queue_send(&buffering_queue, Q_BUFFER_HANDLE, h->id); 1067 queue_send(&buffering_queue, Q_BUFFER_HANDLE, handle_id);
1132 } else { 1068 }
1069 else
1070 {
1133 /* Other types will get buffered in the course of normal operations */ 1071 /* Other types will get buffered in the course of normal operations */
1134 h->fd = -1;
1135 close(fd); 1072 close(fd);
1136 1073
1137 /* Inform the buffering thread that we added a handle */ 1074 if (handle_id >= 0)
1138 LOGFQUEUE("buffering > Q_HANDLE_ADDED %d", h->id); 1075 {
1139 queue_post(&buffering_queue, Q_HANDLE_ADDED, h->id); 1076 /* Inform the buffering thread that we added a handle */
1077 LOGFQUEUE("buffering > Q_HANDLE_ADDED %d", handle_id);
1078 queue_post(&buffering_queue, Q_HANDLE_ADDED, handle_id);
1079 }
1140 } 1080 }
1141 1081
1142 logf("bufopen: new hdl %d", h->id); 1082 logf("bufopen: new hdl %d", handle_id);
1143 return h->id; 1083 return handle_id;
1144} 1084}
1145 1085
1146/* Open a new handle from data that needs to be copied from memory. 1086/* Open a new handle from data that needs to be copied from memory.
@@ -1152,36 +1092,43 @@ int bufopen(const char *file, size_t offset, enum data_type type,
1152*/ 1092*/
1153int bufalloc(const void *src, size_t size, enum data_type type) 1093int bufalloc(const void *src, size_t size, enum data_type type)
1154{ 1094{
1155 struct memory_handle *h = add_handle(size, false, true); 1095 int handle_id = ERR_BUFFER_FULL;
1156 1096
1157 if (!h) 1097 mutex_lock(&llist_mutex);
1158 return ERR_BUFFER_FULL;
1159 1098
1160 if (src) { 1099 struct memory_handle *h = add_handle(size, false, true);
1161 if (type == TYPE_ID3 && size == sizeof(struct mp3entry)) { 1100
1162 /* specially take care of struct mp3entry */ 1101 if (h)
1163 copy_mp3entry((struct mp3entry *)&buffer[buf_widx], 1102 {
1164 (const struct mp3entry *)src); 1103 handle_id = h->id;
1165 } else { 1104
1166 memcpy(&buffer[buf_widx], src, size); 1105 if (src) {
1106 if (type == TYPE_ID3 && size == sizeof(struct mp3entry)) {
1107 /* specially take care of struct mp3entry */
1108 copy_mp3entry((struct mp3entry *)&buffer[buf_widx],
1109 (const struct mp3entry *)src);
1110 } else {
1111 memcpy(&buffer[buf_widx], src, size);
1112 }
1167 } 1113 }
1168 } 1114
1115 h->fd = -1;
1116 *h->path = 0;
1117 h->filesize = size;
1118 h->offset = 0;
1119 h->ridx = buf_widx;
1120 h->widx = buf_widx + size; /* this is safe because the data doesn't wrap */
1121 h->data = buf_widx;
1122 h->available = size;
1123 h->type = type;
1169 1124
1170 h->fd = -1; 1125 buf_widx += size; /* safe too */
1171 *h->path = 0; 1126 }
1172 h->filesize = size;
1173 h->filerem = 0;
1174 h->offset = 0;
1175 h->ridx = buf_widx;
1176 h->widx = buf_widx + size; /* this is safe because the data doesn't wrap */
1177 h->data = buf_widx;
1178 h->available = size;
1179 h->type = type;
1180 1127
1181 buf_widx += size; /* safe too */ 1128 mutex_unlock(&llist_mutex);
1182 1129
1183 logf("bufalloc: new hdl %d", h->id); 1130 logf("bufalloc: new hdl %d", handle_id);
1184 return h->id; 1131 return handle_id;
1185} 1132}
1186 1133
1187/* Close the handle. Return true for success and false for failure */ 1134/* Close the handle. Return true for success and false for failure */
@@ -1193,56 +1140,155 @@ bool bufclose(int handle_id)
1193 return queue_send(&buffering_queue, Q_CLOSE_HANDLE, handle_id); 1140 return queue_send(&buffering_queue, Q_CLOSE_HANDLE, handle_id);
1194} 1141}
1195 1142
1196/* Set reading index in handle (relatively to the start of the file). 1143/* Backend to bufseek and bufadvance. Call only in response to
1197 Access before the available data will trigger a rebuffer. 1144 Q_REBUFFER_HANDLE! */
1198 Return 0 for success and < 0 for failure: 1145static void rebuffer_handle(int handle_id, size_t newpos)
1199 -1 if the handle wasn't found
1200 -2 if the new requested position was beyond the end of the file
1201*/
1202int bufseek(int handle_id, size_t newpos)
1203{ 1146{
1204 struct memory_handle *h = find_handle(handle_id); 1147 struct memory_handle *h = find_handle(handle_id);
1205 if (!h) 1148 if (!h)
1206 return ERR_HANDLE_NOT_FOUND; 1149 {
1150 queue_reply(&buffering_queue, ERR_HANDLE_NOT_FOUND);
1151 return;
1152 }
1153
1154 /* When seeking foward off of the buffer, if it is a short seek attempt to
1155 avoid rebuffering the whole track, just read enough to satisfy */
1156 if (newpos > h->offset && newpos - h->offset < BUFFERING_DEFAULT_FILECHUNK)
1157 {
1158 size_t amount = newpos - h->offset;
1159 h->ridx = ringbuf_add(h->data, amount);
1160 if (buffer_handle(handle_id, amount + 1))
1161 {
1162 queue_reply(&buffering_queue, 0);
1163 buffer_handle(handle_id, 0); /* Ok, try the rest */
1164 return;
1165 }
1166 /* Data collision - must reset */
1167 }
1168
1169 /* Reset the handle to its new position */
1170 h->offset = newpos;
1171
1172 size_t next = h->next ? ringbuf_offset(h->next) : buf_ridx;
1173
1174#ifdef STORAGE_WANTS_ALIGN
1175 /* Strip alignment padding then redo */
1176 size_t new_index = ringbuf_add(ringbuf_offset(h), sizeof (*h));
1177
1178 /* Align to desired storage alignment if space permits - handle could have
1179 been shrunken too close to the following one after a previous rebuffer. */
1180 size_t alignment_pad =
1181 STORAGE_OVERLAP(h->offset - (size_t)(&buffer[new_index]));
1182
1183 if (ringbuf_add_cross(new_index, alignment_pad, next) >= 0)
1184 alignment_pad = 0; /* Forego storage alignment this time */
1185
1186 new_index = ringbuf_add(new_index, alignment_pad);
1187#else
1188 /* Just clear the data buffer */
1189 size_t new_index = h->data;
1190#endif /* STORAGE_WANTS_ALIGN */
1191
1192 h->ridx = h->widx = h->data = new_index;
1193
1194 if (h == cur_handle)
1195 buf_widx = new_index;
1196
1197 h->available = 0;
1198 h->filerem = h->filesize - h->offset;
1199
1200 if (h->fd >= 0)
1201 lseek(h->fd, h->offset, SEEK_SET);
1202
1203 if (h->next && ringbuf_sub(next, h->data) <= h->filesize - newpos)
1204 {
1205 /* There isn't enough space to rebuffer all of the track from its new
1206 offset, so we ask the user to free some */
1207 DEBUGF("%s(): space is needed\n", __func__);
1208 int hid = handle_id;
1209 send_event(BUFFER_EVENT_REBUFFER, &hid);
1210 }
1211
1212 /* Now we do the rebuffer */
1213 queue_reply(&buffering_queue, 0);
1214 buffer_handle(handle_id, 0);
1215}
1207 1216
1217/* Backend to bufseek and bufadvance */
1218static int seek_handle(struct memory_handle *h, size_t newpos)
1219{
1208 if (newpos > h->filesize) { 1220 if (newpos > h->filesize) {
1209 /* access beyond the end of the file */ 1221 /* access beyond the end of the file */
1210 return ERR_INVALID_VALUE; 1222 return ERR_INVALID_VALUE;
1211 } 1223 }
1212 else if (newpos < h->offset || h->offset + h->available < newpos) { 1224 else if ((newpos < h->offset || h->offset + h->available <= newpos) &&
1213 /* access before or after buffered data. A rebuffer is needed. */ 1225 (newpos < h->filesize || h->filerem > 0)) {
1214 rebuffer_handle(handle_id, newpos); 1226 /* access before or after buffered data and not to end of file or file
1227 is not buffered to the end-- a rebuffer is needed. */
1228 struct buf_message_data parm = { h->id, newpos };
1229 return queue_send(&buffering_queue, Q_REBUFFER_HANDLE,
1230 (intptr_t)&parm);
1215 } 1231 }
1216 else { 1232 else {
1217 h->ridx = ringbuf_add(h->data, newpos - h->offset); 1233 h->ridx = ringbuf_add(h->data, newpos - h->offset);
1218 } 1234 }
1235
1219 return 0; 1236 return 0;
1220} 1237}
1221 1238
1239/* Set reading index in handle (relatively to the start of the file).
1240 Access before the available data will trigger a rebuffer.
1241 Return 0 for success and < 0 for failure:
1242 -1 if the handle wasn't found
1243 -2 if the new requested position was beyond the end of the file
1244*/
1245int bufseek(int handle_id, size_t newpos)
1246{
1247 struct memory_handle *h = find_handle(handle_id);
1248 if (!h)
1249 return ERR_HANDLE_NOT_FOUND;
1250
1251 return seek_handle(h, newpos);
1252}
1253
1222/* Advance the reading index in a handle (relatively to its current position). 1254/* Advance the reading index in a handle (relatively to its current position).
1223 Return 0 for success and < 0 for failure */ 1255 Return 0 for success and < 0 for failure */
1224int bufadvance(int handle_id, off_t offset) 1256int bufadvance(int handle_id, off_t offset)
1225{ 1257{
1226 const struct memory_handle *h = find_handle(handle_id); 1258 struct memory_handle *h = find_handle(handle_id);
1227 if (!h) 1259 if (!h)
1228 return ERR_HANDLE_NOT_FOUND; 1260 return ERR_HANDLE_NOT_FOUND;
1229 1261
1230 size_t newpos = h->offset + ringbuf_sub(h->ridx, h->data) + offset; 1262 size_t newpos = h->offset + ringbuf_sub(h->ridx, h->data) + offset;
1231 return bufseek(handle_id, newpos); 1263 return seek_handle(h, newpos);
1232} 1264}
1233 1265
1234/* Used by bufread and bufgetdata to prepare the buffer and retrieve the 1266/* Used by bufread and bufgetdata to prepare the buffer and retrieve the
1235 * actual amount of data available for reading. This function explicitly 1267 * actual amount of data available for reading. This function explicitly
1236 * does not check the validity of the input handle. It does do range checks 1268 * does not check the validity of the input handle. It does do range checks
1237 * on size and returns a valid (and explicit) amount of data for reading */ 1269 * on size and returns a valid (and explicit) amount of data for reading */
1270static size_t handle_size_available(const struct memory_handle *h)
1271{
1272 /* Obtain proper distances from data start */
1273 size_t rd = ringbuf_sub(h->ridx, h->data);
1274 size_t wr = ringbuf_sub(h->widx, h->data);
1275
1276 if (LIKELY(wr > rd))
1277 return wr - rd;
1278
1279 return 0; /* ridx is ahead of or equal to widx at this time */
1280}
1281
1238static struct memory_handle *prep_bufdata(int handle_id, size_t *size, 1282static struct memory_handle *prep_bufdata(int handle_id, size_t *size,
1239 bool guardbuf_limit) 1283 bool guardbuf_limit)
1240{ 1284{
1241 struct memory_handle *h = find_handle(handle_id); 1285 struct memory_handle *h = find_handle(handle_id);
1286 size_t realsize;
1287
1242 if (!h) 1288 if (!h)
1243 return NULL; 1289 return NULL;
1244 1290
1245 size_t avail = ringbuf_sub(h->widx, h->ridx); 1291 size_t avail = handle_size_available(h);
1246 1292
1247 if (avail == 0 && h->filerem == 0) 1293 if (avail == 0 && h->filerem == 0)
1248 { 1294 {
@@ -1251,40 +1297,52 @@ static struct memory_handle *prep_bufdata(int handle_id, size_t *size,
1251 return h; 1297 return h;
1252 } 1298 }
1253 1299
1254 if (*size == 0 || *size > avail + h->filerem) 1300 realsize = *size;
1255 *size = avail + h->filerem; 1301
1302 if (realsize == 0 || realsize > avail + h->filerem)
1303 realsize = avail + h->filerem;
1256 1304
1257 if (guardbuf_limit && h->type == TYPE_PACKET_AUDIO && *size > GUARD_BUFSIZE) 1305 if (guardbuf_limit && h->type == TYPE_PACKET_AUDIO
1306 && realsize > GUARD_BUFSIZE)
1258 { 1307 {
1259 logf("data request > guardbuf"); 1308 logf("data request > guardbuf");
1260 /* If more than the size of the guardbuf is requested and this is a 1309 /* If more than the size of the guardbuf is requested and this is a
1261 * bufgetdata, limit to guard_bufsize over the end of the buffer */ 1310 * bufgetdata, limit to guard_bufsize over the end of the buffer */
1262 *size = MIN(*size, buffer_len - h->ridx + GUARD_BUFSIZE); 1311 realsize = MIN(realsize, buffer_len - h->ridx + GUARD_BUFSIZE);
1263 /* this ensures *size <= buffer_len - h->ridx + GUARD_BUFSIZE */ 1312 /* this ensures *size <= buffer_len - h->ridx + GUARD_BUFSIZE */
1264 } 1313 }
1265 1314
1266 if (h->filerem > 0 && avail < *size) 1315 if (h->filerem > 0 && avail < realsize)
1267 { 1316 {
1268 /* Data isn't ready. Request buffering */ 1317 /* Data isn't ready. Request buffering */
1269 buf_request_buffer_handle(handle_id); 1318 buf_request_buffer_handle(handle_id);
1270 /* Wait for the data to be ready */ 1319 /* Wait for the data to be ready */
1271 do 1320 do
1272 { 1321 {
1273 sleep(1); 1322 sleep(0);
1274 /* it is not safe for a non-buffering thread to sleep while 1323 /* it is not safe for a non-buffering thread to sleep while
1275 * holding a handle */ 1324 * holding a handle */
1276 h = find_handle(handle_id); 1325 h = find_handle(handle_id);
1277 if (!h) 1326 if (!h)
1278 return NULL; 1327 return NULL;
1279 avail = ringbuf_sub(h->widx, h->ridx); 1328 avail = handle_size_available(h);
1280 } 1329 }
1281 while (h->filerem > 0 && avail < *size); 1330 while (h->filerem > 0 && avail < realsize);
1282 } 1331 }
1283 1332
1284 *size = MIN(*size,avail); 1333 *size = MIN(realsize, avail);
1285 return h; 1334 return h;
1286} 1335}
1287 1336
1337
1338/* Note: It is safe for the thread responsible for handling the rebuffer
1339 * cleanup request to call bufread or bufgetdata only when the data will
1340 * be available-- not if it could be blocked waiting for it in prep_bufdata.
1341 * It should be apparent that if said thread is being forced to wait for
1342 * buffering but has not yet responded to the cleanup request, the space
1343 * can never be cleared to allow further reading of the file because it is
1344 * not listening to callbacks any longer. */
1345
1288/* Copy data from the given handle to the dest buffer. 1346/* Copy data from the given handle to the dest buffer.
1289 Return the number of bytes copied or < 0 for failure (handle not found). 1347 Return the number of bytes copied or < 0 for failure (handle not found).
1290 The caller is blocked until the requested amount of data is available. 1348 The caller is blocked until the requested amount of data is available.
@@ -1481,6 +1539,7 @@ void buffering_thread(void)
1481{ 1539{
1482 bool filling = false; 1540 bool filling = false;
1483 struct queue_event ev; 1541 struct queue_event ev;
1542 struct buf_message_data *parm;
1484 1543
1485 while (true) 1544 while (true)
1486 { 1545 {
@@ -1499,19 +1558,20 @@ void buffering_thread(void)
1499 send_event(BUFFER_EVENT_BUFFER_LOW, 0); 1558 send_event(BUFFER_EVENT_BUFFER_LOW, 0);
1500 shrink_buffer(); 1559 shrink_buffer();
1501 queue_reply(&buffering_queue, 1); 1560 queue_reply(&buffering_queue, 1);
1502 filling |= buffer_handle((int)ev.data); 1561 filling |= buffer_handle((int)ev.data, 0);
1503 break; 1562 break;
1504 1563
1505 case Q_BUFFER_HANDLE: 1564 case Q_BUFFER_HANDLE:
1506 LOGFQUEUE("buffering < Q_BUFFER_HANDLE %d", (int)ev.data); 1565 LOGFQUEUE("buffering < Q_BUFFER_HANDLE %d", (int)ev.data);
1507 queue_reply(&buffering_queue, 1); 1566 queue_reply(&buffering_queue, 1);
1508 buffer_handle((int)ev.data); 1567 buffer_handle((int)ev.data, 0);
1509 break; 1568 break;
1510 1569
1511 case Q_RESET_HANDLE: 1570 case Q_REBUFFER_HANDLE:
1512 LOGFQUEUE("buffering < Q_RESET_HANDLE %d", (int)ev.data); 1571 parm = (struct buf_message_data *)ev.data;
1513 queue_reply(&buffering_queue, 1); 1572 LOGFQUEUE("buffering < Q_REBUFFER_HANDLE %d %ld",
1514 reset_handle((int)ev.data); 1573 parm->handle_id, parm->data);
1574 rebuffer_handle(parm->handle_id, parm->data);
1515 break; 1575 break;
1516 1576
1517 case Q_CLOSE_HANDLE: 1577 case Q_CLOSE_HANDLE:
@@ -1543,7 +1603,7 @@ void buffering_thread(void)
1543 break; 1603 break;
1544 } 1604 }
1545 1605
1546 update_data_counters(); 1606 update_data_counters(NULL);
1547 1607
1548 /* If the buffer is low, call the callbacks to get new data */ 1608 /* If the buffer is low, call the callbacks to get new data */
1549 if (num_handles > 0 && data_counters.useful <= conf_watermark) 1609 if (num_handles > 0 && data_counters.useful <= conf_watermark)
@@ -1565,7 +1625,7 @@ void buffering_thread(void)
1565 if (!filling) 1625 if (!filling)
1566 shrink_buffer(); 1626 shrink_buffer();
1567 filling = fill_buffer(); 1627 filling = fill_buffer();
1568 update_data_counters(); 1628 update_data_counters(NULL);
1569 } 1629 }
1570 } 1630 }
1571#endif 1631#endif
@@ -1593,12 +1653,6 @@ void buffering_thread(void)
1593void buffering_init(void) 1653void buffering_init(void)
1594{ 1654{
1595 mutex_init(&llist_mutex); 1655 mutex_init(&llist_mutex);
1596 mutex_init(&llist_mod_mutex);
1597#ifdef HAVE_PRIORITY_SCHEDULING
1598 /* This behavior not safe atm */
1599 mutex_set_preempt(&llist_mutex, false);
1600 mutex_set_preempt(&llist_mod_mutex, false);
1601#endif
1602 1656
1603 conf_watermark = BUFFERING_DEFAULT_WATERMARK; 1657 conf_watermark = BUFFERING_DEFAULT_WATERMARK;
1604 1658
@@ -1648,11 +1702,12 @@ bool buffering_reset(char *buf, size_t buflen)
1648 1702
1649void buffering_get_debugdata(struct buffering_debug *dbgdata) 1703void buffering_get_debugdata(struct buffering_debug *dbgdata)
1650{ 1704{
1651 update_data_counters(); 1705 struct data_counters dc;
1706 update_data_counters(&dc);
1652 dbgdata->num_handles = num_handles; 1707 dbgdata->num_handles = num_handles;
1653 dbgdata->data_rem = data_counters.remaining; 1708 dbgdata->data_rem = dc.remaining;
1654 dbgdata->wasted_space = data_counters.wasted; 1709 dbgdata->wasted_space = dc.wasted;
1655 dbgdata->buffered_data = data_counters.buffered; 1710 dbgdata->buffered_data = dc.buffered;
1656 dbgdata->useful_data = data_counters.useful; 1711 dbgdata->useful_data = dc.useful;
1657 dbgdata->watermark = conf_watermark; 1712 dbgdata->watermark = conf_watermark;
1658} 1713}