diff options
Diffstat (limited to 'apps')
-rw-r--r-- | apps/buffering.c | 112 |
1 files changed, 68 insertions, 44 deletions
diff --git a/apps/buffering.c b/apps/buffering.c index f261b5a711..ee375e9172 100644 --- a/apps/buffering.c +++ b/apps/buffering.c | |||
@@ -91,17 +91,6 @@ | |||
91 | #define BUF_HANDLE_MASK 0x7FFFFFFF | 91 | #define BUF_HANDLE_MASK 0x7FFFFFFF |
92 | 92 | ||
93 | 93 | ||
94 | /* Ring buffer helper macros */ | ||
95 | /* Buffer pointer (p) plus value (v), wrapped if necessary */ | ||
96 | #define RINGBUF_ADD(p,v) (((p)+(v))<buffer_len ? (p)+(v) : (p)+(v)-buffer_len) | ||
97 | /* Buffer pointer (p) minus value (v), wrapped if necessary */ | ||
98 | #define RINGBUF_SUB(p,v) ((p>=v) ? (p)-(v) : (p)+buffer_len-(v)) | ||
99 | /* How far value (v) plus buffer pointer (p1) will cross buffer pointer (p2) */ | ||
100 | #define RINGBUF_ADD_CROSS(p1,v,p2) \ | ||
101 | ((p1<p2) ? (int)((p1)+(v))-(int)(p2) : (int)((p1)+(v)-(p2))-(int)buffer_len) | ||
102 | /* Bytes available in the buffer */ | ||
103 | #define BUF_USED RINGBUF_SUB(buf_widx, buf_ridx) | ||
104 | |||
105 | /* assert(sizeof(struct memory_handle)%4==0) */ | 94 | /* assert(sizeof(struct memory_handle)%4==0) */ |
106 | struct memory_handle { | 95 | struct memory_handle { |
107 | int id; /* A unique ID for the handle */ | 96 | int id; /* A unique ID for the handle */ |
@@ -186,6 +175,41 @@ static struct queue_sender_list buffering_queue_sender_list; | |||
186 | 175 | ||
187 | 176 | ||
188 | 177 | ||
178 | /* Ring buffer helper functions */ | ||
179 | /* Buffer pointer (p) plus value (v), wrapped if necessary */ | ||
180 | static inline uintptr_t ringbuf_add(uintptr_t p, size_t v) | ||
181 | { | ||
182 | uintptr_t res = p + v; | ||
183 | if (res >= buffer_len) | ||
184 | res -= buffer_len; /* wrap if necssary */ | ||
185 | return res; | ||
186 | } | ||
187 | |||
188 | |||
189 | /* Buffer pointer (p) minus value (v), wrapped if necessary */ | ||
190 | static inline uintptr_t ringbuf_sub(uintptr_t p, size_t v) | ||
191 | { | ||
192 | uintptr_t res = p; | ||
193 | if (p < v) | ||
194 | res += buffer_len; /* wrap */ | ||
195 | |||
196 | return res - v; | ||
197 | } | ||
198 | |||
199 | |||
200 | /* How far value (v) plus buffer pointer (p1) will cross buffer pointer (p2) */ | ||
201 | static inline ssize_t ringbuf_add_cross(uintptr_t p1, size_t v, uintptr_t p2) | ||
202 | { | ||
203 | ssize_t res = p1 + v - p2; | ||
204 | if (p1 >= p2) /* wrap if necessary */ | ||
205 | res -= buffer_len; | ||
206 | |||
207 | return res; | ||
208 | } | ||
209 | |||
210 | /* Bytes available in the buffer */ | ||
211 | #define BUF_USED ringbuf_sub(buf_widx, buf_ridx) | ||
212 | |||
189 | /* | 213 | /* |
190 | LINKED LIST MANAGEMENT | 214 | LINKED LIST MANAGEMENT |
191 | ====================== | 215 | ====================== |
@@ -239,19 +263,19 @@ static struct memory_handle *add_handle(size_t data_size, bool can_wrap, | |||
239 | a new one if there is already enough free space to finish | 263 | a new one if there is already enough free space to finish |
240 | the buffering. */ | 264 | the buffering. */ |
241 | size_t req = cur_handle->filerem + sizeof(struct memory_handle); | 265 | size_t req = cur_handle->filerem + sizeof(struct memory_handle); |
242 | if (RINGBUF_ADD_CROSS(cur_handle->widx, req, buf_ridx) >= 0) { | 266 | if (ringbuf_add_cross(cur_handle->widx, req, buf_ridx) >= 0) { |
243 | /* Not enough space */ | 267 | /* Not enough space */ |
244 | mutex_unlock(&llist_mod_mutex); | 268 | mutex_unlock(&llist_mod_mutex); |
245 | mutex_unlock(&llist_mutex); | 269 | mutex_unlock(&llist_mutex); |
246 | return NULL; | 270 | return NULL; |
247 | } else { | 271 | } else { |
248 | /* Allocate the remainder of the space for the current handle */ | 272 | /* Allocate the remainder of the space for the current handle */ |
249 | buf_widx = RINGBUF_ADD(cur_handle->widx, cur_handle->filerem); | 273 | buf_widx = ringbuf_add(cur_handle->widx, cur_handle->filerem); |
250 | } | 274 | } |
251 | } | 275 | } |
252 | 276 | ||
253 | /* align to 4 bytes up */ | 277 | /* align to 4 bytes up */ |
254 | new_widx = RINGBUF_ADD(buf_widx, 3) & ~3; | 278 | new_widx = ringbuf_add(buf_widx, 3) & ~3; |
255 | 279 | ||
256 | len = data_size + sizeof(struct memory_handle); | 280 | len = data_size + sizeof(struct memory_handle); |
257 | 281 | ||
@@ -264,10 +288,10 @@ static struct memory_handle *add_handle(size_t data_size, bool can_wrap, | |||
264 | } | 288 | } |
265 | 289 | ||
266 | /* How far we shifted buf_widx to align things, must be < buffer_len */ | 290 | /* How far we shifted buf_widx to align things, must be < buffer_len */ |
267 | shift = RINGBUF_SUB(new_widx, buf_widx); | 291 | shift = ringbuf_sub(new_widx, buf_widx); |
268 | 292 | ||
269 | /* How much space are we short in the actual ring buffer? */ | 293 | /* How much space are we short in the actual ring buffer? */ |
270 | overlap = RINGBUF_ADD_CROSS(buf_widx, shift + len, buf_ridx); | 294 | overlap = ringbuf_add_cross(buf_widx, shift + len, buf_ridx); |
271 | if (overlap >= 0 && (alloc_all || (unsigned)overlap > data_size)) { | 295 | if (overlap >= 0 && (alloc_all || (unsigned)overlap > data_size)) { |
272 | /* Not enough space for required allocations */ | 296 | /* Not enough space for required allocations */ |
273 | mutex_unlock(&llist_mod_mutex); | 297 | mutex_unlock(&llist_mod_mutex); |
@@ -283,7 +307,7 @@ static struct memory_handle *add_handle(size_t data_size, bool can_wrap, | |||
283 | (struct memory_handle *)(&buffer[buf_widx]); | 307 | (struct memory_handle *)(&buffer[buf_widx]); |
284 | 308 | ||
285 | /* only advance the buffer write index of the size of the struct */ | 309 | /* only advance the buffer write index of the size of the struct */ |
286 | buf_widx = RINGBUF_ADD(buf_widx, sizeof(struct memory_handle)); | 310 | buf_widx = ringbuf_add(buf_widx, sizeof(struct memory_handle)); |
287 | 311 | ||
288 | new_handle->id = cur_handle_id; | 312 | new_handle->id = cur_handle_id; |
289 | /* Wrap signed int is safe and 0 doesn't happen */ | 313 | /* Wrap signed int is safe and 0 doesn't happen */ |
@@ -433,9 +457,9 @@ static bool move_handle(struct memory_handle **h, size_t *delta, | |||
433 | mutex_lock(&llist_mod_mutex); | 457 | mutex_lock(&llist_mod_mutex); |
434 | 458 | ||
435 | oldpos = (void *)src - (void *)buffer; | 459 | oldpos = (void *)src - (void *)buffer; |
436 | newpos = RINGBUF_ADD(oldpos, final_delta); | 460 | newpos = ringbuf_add(oldpos, final_delta); |
437 | overlap = RINGBUF_ADD_CROSS(newpos, size_to_move, buffer_len - 1); | 461 | overlap = ringbuf_add_cross(newpos, size_to_move, buffer_len - 1); |
438 | overlap_old = RINGBUF_ADD_CROSS(oldpos, size_to_move, buffer_len -1); | 462 | overlap_old = ringbuf_add_cross(oldpos, size_to_move, buffer_len -1); |
439 | 463 | ||
440 | if (overlap > 0) { | 464 | if (overlap > 0) { |
441 | /* Some part of the struct + data would wrap, maybe ok */ | 465 | /* Some part of the struct + data would wrap, maybe ok */ |
@@ -500,8 +524,8 @@ static bool move_handle(struct memory_handle **h, size_t *delta, | |||
500 | * copy may be ok but do this for safety and because wrapped copies should | 524 | * copy may be ok but do this for safety and because wrapped copies should |
501 | * be fairly uncommon */ | 525 | * be fairly uncommon */ |
502 | 526 | ||
503 | here = (int32_t *)((RINGBUF_ADD(oldpos, size_to_move - 1) & ~3)+ (intptr_t)buffer); | 527 | here = (int32_t *)((ringbuf_add(oldpos, size_to_move - 1) & ~3)+ (intptr_t)buffer); |
504 | there =(int32_t *)((RINGBUF_ADD(newpos, size_to_move - 1) & ~3)+ (intptr_t)buffer); | 528 | there =(int32_t *)((ringbuf_add(newpos, size_to_move - 1) & ~3)+ (intptr_t)buffer); |
505 | end = (int32_t *)(( intptr_t)buffer + buffer_len - 4); | 529 | end = (int32_t *)(( intptr_t)buffer + buffer_len - 4); |
506 | begin =(int32_t *)buffer; | 530 | begin =(int32_t *)buffer; |
507 | 531 | ||
@@ -561,14 +585,14 @@ static void update_data_counters(void) | |||
561 | m = first_handle; | 585 | m = first_handle; |
562 | while (m) { | 586 | while (m) { |
563 | buffered += m->available; | 587 | buffered += m->available; |
564 | wasted += RINGBUF_SUB(m->ridx, m->data); | 588 | wasted += ringbuf_sub(m->ridx, m->data); |
565 | remaining += m->filerem; | 589 | remaining += m->filerem; |
566 | 590 | ||
567 | if (m->id == base_handle_id) | 591 | if (m->id == base_handle_id) |
568 | is_useful = true; | 592 | is_useful = true; |
569 | 593 | ||
570 | if (is_useful) | 594 | if (is_useful) |
571 | useful += RINGBUF_SUB(m->widx, m->ridx); | 595 | useful += ringbuf_sub(m->widx, m->ridx); |
572 | 596 | ||
573 | m = m->next; | 597 | m = m->next; |
574 | } | 598 | } |
@@ -643,14 +667,14 @@ static bool buffer_handle(int handle_id) | |||
643 | buffer_len - h->widx); | 667 | buffer_len - h->widx); |
644 | 668 | ||
645 | /* stop copying if it would overwrite the reading position */ | 669 | /* stop copying if it would overwrite the reading position */ |
646 | if (RINGBUF_ADD_CROSS(h->widx, copy_n, buf_ridx) >= 0) | 670 | if (ringbuf_add_cross(h->widx, copy_n, buf_ridx) >= 0) |
647 | return false; | 671 | return false; |
648 | 672 | ||
649 | /* This would read into the next handle, this is broken | 673 | /* This would read into the next handle, this is broken |
650 | if (h->next && RINGBUF_ADD_CROSS(h->widx, copy_n, | 674 | if (h->next && ringbuf_add_cross(h->widx, copy_n, |
651 | (unsigned)((void *)h->next - (void *)buffer)) > 0) { | 675 | (unsigned)((void *)h->next - (void *)buffer)) > 0) { |
652 | Try to recover by truncating this file | 676 | Try to recover by truncating this file |
653 | copy_n = RINGBUF_ADD_CROSS(h->widx, copy_n, | 677 | copy_n = ringbuf_add_cross(h->widx, copy_n, |
654 | (unsigned)((void *)h->next - (void *)buffer)); | 678 | (unsigned)((void *)h->next - (void *)buffer)); |
655 | h->filerem -= copy_n; | 679 | h->filerem -= copy_n; |
656 | h->filesize -= copy_n; | 680 | h->filesize -= copy_n; |
@@ -679,7 +703,7 @@ static bool buffer_handle(int handle_id) | |||
679 | } | 703 | } |
680 | 704 | ||
681 | /* Advance buffer */ | 705 | /* Advance buffer */ |
682 | h->widx = RINGBUF_ADD(h->widx, rc); | 706 | h->widx = ringbuf_add(h->widx, rc); |
683 | if (h == cur_handle) | 707 | if (h == cur_handle) |
684 | buf_widx = h->widx; | 708 | buf_widx = h->widx; |
685 | h->available += rc; | 709 | h->available += rc; |
@@ -726,7 +750,7 @@ static void reset_handle(int handle_id) | |||
726 | /* Align to desired storage alignment */ | 750 | /* Align to desired storage alignment */ |
727 | alignment_pad = (h->offset - (size_t)(&buffer[h->start])) | 751 | alignment_pad = (h->offset - (size_t)(&buffer[h->start])) |
728 | & STORAGE_ALIGN_MASK; | 752 | & STORAGE_ALIGN_MASK; |
729 | h->ridx = h->widx = h->data = RINGBUF_ADD(h->start, alignment_pad); | 753 | h->ridx = h->widx = h->data = ringbuf_add(h->start, alignment_pad); |
730 | 754 | ||
731 | if (h == cur_handle) | 755 | if (h == cur_handle) |
732 | buf_widx = h->widx; | 756 | buf_widx = h->widx; |
@@ -762,7 +786,7 @@ static void rebuffer_handle(int handle_id, size_t newpos) | |||
762 | queue_send(&buffering_queue, Q_RESET_HANDLE, handle_id); | 786 | queue_send(&buffering_queue, Q_RESET_HANDLE, handle_id); |
763 | 787 | ||
764 | size_t next = (unsigned)((void *)h->next - (void *)buffer); | 788 | size_t next = (unsigned)((void *)h->next - (void *)buffer); |
765 | if (RINGBUF_SUB(next, h->data) < h->filesize - newpos) | 789 | if (ringbuf_sub(next, h->data) < h->filesize - newpos) |
766 | { | 790 | { |
767 | /* There isn't enough space to rebuffer all of the track from its new | 791 | /* There isn't enough space to rebuffer all of the track from its new |
768 | offset, so we ask the user to free some */ | 792 | offset, so we ask the user to free some */ |
@@ -808,7 +832,7 @@ static void shrink_handle(struct memory_handle *h) | |||
808 | { | 832 | { |
809 | /* metadata handle: we can move all of it */ | 833 | /* metadata handle: we can move all of it */ |
810 | size_t handle_distance = | 834 | size_t handle_distance = |
811 | RINGBUF_SUB((unsigned)((void *)h->next - (void*)buffer), h->data); | 835 | ringbuf_sub((unsigned)((void *)h->next - (void*)buffer), h->data); |
812 | delta = handle_distance - h->available; | 836 | delta = handle_distance - h->available; |
813 | 837 | ||
814 | /* The value of delta might change for alignment reasons */ | 838 | /* The value of delta might change for alignment reasons */ |
@@ -816,9 +840,9 @@ static void shrink_handle(struct memory_handle *h) | |||
816 | return; | 840 | return; |
817 | 841 | ||
818 | size_t olddata = h->data; | 842 | size_t olddata = h->data; |
819 | h->data = RINGBUF_ADD(h->data, delta); | 843 | h->data = ringbuf_add(h->data, delta); |
820 | h->ridx = RINGBUF_ADD(h->ridx, delta); | 844 | h->ridx = ringbuf_add(h->ridx, delta); |
821 | h->widx = RINGBUF_ADD(h->widx, delta); | 845 | h->widx = ringbuf_add(h->widx, delta); |
822 | 846 | ||
823 | if (h->type == TYPE_ID3 && h->filesize == sizeof(struct mp3entry)) { | 847 | if (h->type == TYPE_ID3 && h->filesize == sizeof(struct mp3entry)) { |
824 | /* when moving an mp3entry we need to readjust its pointers. */ | 848 | /* when moving an mp3entry we need to readjust its pointers. */ |
@@ -834,12 +858,12 @@ static void shrink_handle(struct memory_handle *h) | |||
834 | else | 858 | else |
835 | { | 859 | { |
836 | /* only move the handle struct */ | 860 | /* only move the handle struct */ |
837 | delta = RINGBUF_SUB(h->ridx, h->data); | 861 | delta = ringbuf_sub(h->ridx, h->data); |
838 | if (!move_handle(&h, &delta, 0, true)) | 862 | if (!move_handle(&h, &delta, 0, true)) |
839 | return; | 863 | return; |
840 | 864 | ||
841 | h->data = RINGBUF_ADD(h->data, delta); | 865 | h->data = ringbuf_add(h->data, delta); |
842 | h->start = RINGBUF_ADD(h->start, delta); | 866 | h->start = ringbuf_add(h->start, delta); |
843 | h->available -= delta; | 867 | h->available -= delta; |
844 | h->offset += delta; | 868 | h->offset += delta; |
845 | } | 869 | } |
@@ -1016,7 +1040,7 @@ int bufopen(const char *file, size_t offset, enum data_type type, | |||
1016 | /* Align to desired storage alignment */ | 1040 | /* Align to desired storage alignment */ |
1017 | alignment_pad = (adjusted_offset - (size_t)(&buffer[buf_widx])) | 1041 | alignment_pad = (adjusted_offset - (size_t)(&buffer[buf_widx])) |
1018 | & STORAGE_ALIGN_MASK; | 1042 | & STORAGE_ALIGN_MASK; |
1019 | buf_widx = RINGBUF_ADD(buf_widx, alignment_pad); | 1043 | buf_widx = ringbuf_add(buf_widx, alignment_pad); |
1020 | } | 1044 | } |
1021 | 1045 | ||
1022 | h->ridx = buf_widx; | 1046 | h->ridx = buf_widx; |
@@ -1145,7 +1169,7 @@ int bufseek(int handle_id, size_t newpos) | |||
1145 | rebuffer_handle(handle_id, newpos); | 1169 | rebuffer_handle(handle_id, newpos); |
1146 | } | 1170 | } |
1147 | else { | 1171 | else { |
1148 | h->ridx = RINGBUF_ADD(h->data, newpos - h->offset); | 1172 | h->ridx = ringbuf_add(h->data, newpos - h->offset); |
1149 | } | 1173 | } |
1150 | return 0; | 1174 | return 0; |
1151 | } | 1175 | } |
@@ -1158,7 +1182,7 @@ int bufadvance(int handle_id, off_t offset) | |||
1158 | if (!h) | 1182 | if (!h) |
1159 | return ERR_HANDLE_NOT_FOUND; | 1183 | return ERR_HANDLE_NOT_FOUND; |
1160 | 1184 | ||
1161 | size_t newpos = h->offset + RINGBUF_SUB(h->ridx, h->data) + offset; | 1185 | size_t newpos = h->offset + ringbuf_sub(h->ridx, h->data) + offset; |
1162 | return bufseek(handle_id, newpos); | 1186 | return bufseek(handle_id, newpos); |
1163 | } | 1187 | } |
1164 | 1188 | ||
@@ -1173,7 +1197,7 @@ static struct memory_handle *prep_bufdata(int handle_id, size_t *size, | |||
1173 | if (!h) | 1197 | if (!h) |
1174 | return NULL; | 1198 | return NULL; |
1175 | 1199 | ||
1176 | size_t avail = RINGBUF_SUB(h->widx, h->ridx); | 1200 | size_t avail = ringbuf_sub(h->widx, h->ridx); |
1177 | 1201 | ||
1178 | if (avail == 0 && h->filerem == 0) | 1202 | if (avail == 0 && h->filerem == 0) |
1179 | { | 1203 | { |
@@ -1207,7 +1231,7 @@ static struct memory_handle *prep_bufdata(int handle_id, size_t *size, | |||
1207 | h = find_handle(handle_id); | 1231 | h = find_handle(handle_id); |
1208 | if (!h) | 1232 | if (!h) |
1209 | return NULL; | 1233 | return NULL; |
1210 | avail = RINGBUF_SUB(h->widx, h->ridx); | 1234 | avail = ringbuf_sub(h->widx, h->ridx); |
1211 | } | 1235 | } |
1212 | while (h->filerem > 0 && avail < *size); | 1236 | while (h->filerem > 0 && avail < *size); |
1213 | } | 1237 | } |
@@ -1296,7 +1320,7 @@ ssize_t bufgettail(int handle_id, size_t size, void **data) | |||
1296 | if (size > GUARD_BUFSIZE) | 1320 | if (size > GUARD_BUFSIZE) |
1297 | return ERR_INVALID_VALUE; | 1321 | return ERR_INVALID_VALUE; |
1298 | 1322 | ||
1299 | tidx = RINGBUF_SUB(h->widx, size); | 1323 | tidx = ringbuf_sub(h->widx, size); |
1300 | 1324 | ||
1301 | if (tidx + size > buffer_len) | 1325 | if (tidx + size > buffer_len) |
1302 | { | 1326 | { |
@@ -1326,7 +1350,7 @@ ssize_t bufcuttail(int handle_id, size_t size) | |||
1326 | 1350 | ||
1327 | h->available -= adjusted_size; | 1351 | h->available -= adjusted_size; |
1328 | h->filesize -= adjusted_size; | 1352 | h->filesize -= adjusted_size; |
1329 | h->widx = RINGBUF_SUB(h->widx, adjusted_size); | 1353 | h->widx = ringbuf_sub(h->widx, adjusted_size); |
1330 | if (h == cur_handle) | 1354 | if (h == cur_handle) |
1331 | buf_widx = h->widx; | 1355 | buf_widx = h->widx; |
1332 | 1356 | ||