summaryrefslogtreecommitdiff
path: root/apps/buffering.c
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2011-02-10 05:56:21 +0000
committerMichael Sevakis <jethead71@rockbox.org>2011-02-10 05:56:21 +0000
commit88d91faba5df82e70abfd95b60c96b4a0bd53744 (patch)
tree98bfd167a0f7a88d50d0fe9c65e066d28a57cb47 /apps/buffering.c
parent2007d67bce9b4345ea7f842300dd406cf85c32df (diff)
downloadrockbox-88d91faba5df82e70abfd95b60c96b4a0bd53744.tar.gz
rockbox-88d91faba5df82e70abfd95b60c96b4a0bd53744.zip
buffering: Don't execute move-handle-ony case if handle is of metadata type (atomic) and must be kept fully buffered. Manage handle corruption guard and handle buffering with one set of logic which allows reading of the maximum amount of data without overflow. 'FIXME' regarding handle corruption guard is really part of expected operation when thread that does the handle closing hasn't yet performed the delegated task before rebuffering starts.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29270 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/buffering.c')
-rw-r--r--apps/buffering.c38
1 files changed, 17 insertions, 21 deletions
diff --git a/apps/buffering.c b/apps/buffering.c
index 1482d6790b..14db47bb91 100644
--- a/apps/buffering.c
+++ b/apps/buffering.c
@@ -666,31 +666,25 @@ static bool buffer_handle(int handle_id)
666 while (h->filerem > 0 && !stop) 666 while (h->filerem > 0 && !stop)
667 { 667 {
668 /* max amount to copy */ 668 /* max amount to copy */
669 size_t copy_n = MIN( MIN(h->filerem, BUFFERING_DEFAULT_FILECHUNK), 669 ssize_t copy_n = MIN( MIN(h->filerem, BUFFERING_DEFAULT_FILECHUNK),
670 buffer_len - h->widx); 670 buffer_len - h->widx);
671 uintptr_t offset = h->next ? ringbuf_offset(h->next) : buf_ridx;
672 ssize_t overlap = ringbuf_add_cross(h->widx, copy_n, offset);
671 673
672 ssize_t overlap; 674 if (!h->next)
673 uintptr_t next_handle = ringbuf_offset(h->next); 675 overlap++; /* sub one more below to avoid buffer overflow */
674 676
675 /* stop copying if it would overwrite the reading position */ 677 if (overlap > 0)
676 if (ringbuf_add_cross(h->widx, copy_n, buf_ridx) >= 0)
677 return false;
678
679 /* FIXME: This would overwrite the next handle
680 * If this is true, then there's a handle even though we have still
681 * data to buffer. This should NEVER EVER happen! (but it does :( ) */
682 if (h->next && (overlap
683 = ringbuf_add_cross(h->widx, copy_n, next_handle)) > 0)
684 { 678 {
685 /* stop buffering data for now and post-pone buffering the rest */ 679 /* read only up to available space and stop if it would overwrite
680 the reading position or the next handle */
686 stop = true; 681 stop = true;
687 DEBUGF( "%s(): Preventing handle corruption: h1.id:%d h2.id:%d"
688 " copy_n:%lu overlap:%ld h1.filerem:%lu\n", __func__,
689 h->id, h->next->id, (unsigned long)copy_n, (long)overlap,
690 (unsigned long)h->filerem);
691 copy_n -= overlap; 682 copy_n -= overlap;
692 } 683 }
693 684
685 if (copy_n <= 0)
686 return false; /* no space for read */
687
694 /* rc is the actual amount read */ 688 /* rc is the actual amount read */
695 int rc = read(h->fd, &buffer[h->widx], copy_n); 689 int rc = read(h->fd, &buffer[h->widx], copy_n);
696 690
@@ -830,12 +824,14 @@ static void shrink_handle(struct memory_handle *h)
830 if (!h) 824 if (!h)
831 return; 825 return;
832 826
833 if (h->next && h->filerem == 0 && 827 if (h->type == TYPE_ID3 || h->type == TYPE_CUESHEET ||
834 (h->type == TYPE_ID3 || h->type == TYPE_CUESHEET || 828 h->type == TYPE_BITMAP || h->type == TYPE_CODEC ||
835 h->type == TYPE_BITMAP || h->type == TYPE_CODEC || 829 h->type == TYPE_ATOMIC_AUDIO)
836 h->type == TYPE_ATOMIC_AUDIO))
837 { 830 {
838 /* metadata handle: we can move all of it */ 831 /* metadata handle: we can move all of it */
832 if (!h->next || h->filerem != 0)
833 return; /* Last handle or not finished loading */
834
839 uintptr_t handle_distance = 835 uintptr_t handle_distance =
840 ringbuf_sub(ringbuf_offset(h->next), h->data); 836 ringbuf_sub(ringbuf_offset(h->next), h->data);
841 delta = handle_distance - h->available; 837 delta = handle_distance - h->available;