diff options
author | Brandon Low <lostlogic@rockbox.org> | 2007-11-06 16:49:30 +0000 |
---|---|---|
committer | Brandon Low <lostlogic@rockbox.org> | 2007-11-06 16:49:30 +0000 |
commit | 9821cce484b14f6f7ecbfa6367c26ceab7ebe87e (patch) | |
tree | 0894800a40f79346d2621923d2470425b9b9ee55 | |
parent | b848c683d62e9cd506518a0c23944c6bfcbb9bfe (diff) | |
download | rockbox-9821cce484b14f6f7ecbfa6367c26ceab7ebe87e.tar.gz rockbox-9821cce484b14f6f7ecbfa6367c26ceab7ebe87e.zip |
Pull the size range checking and disk request into a separate function that both bufread and bufgetdata can use. Do better range checking to ensure that we don't get 'stuck' in the calls and warn with a logf if requests are made for which we cannot guarantee satisfaction.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@15495 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | apps/buffering.c | 85 |
1 files changed, 41 insertions, 44 deletions
diff --git a/apps/buffering.c b/apps/buffering.c index 18f3ba6900..5fd8c24122 100644 --- a/apps/buffering.c +++ b/apps/buffering.c | |||
@@ -970,51 +970,70 @@ int bufadvance(int handle_id, off_t offset) | |||
970 | return bufseek(handle_id, newpos); | 970 | return bufseek(handle_id, newpos); |
971 | } | 971 | } |
972 | 972 | ||
973 | /* Copy data from the given handle to the dest buffer. | 973 | /* Used by bufread and bufgetdata to prepare the buffer and retrieve the |
974 | Return the number of bytes copied or < 0 for failure (handle not found). | 974 | * actual amount of data available for reading. This function explicitly |
975 | The caller is blocked until the requested amount of data is available. | 975 | * does not check the validity of the input handle. It does do range checks |
976 | */ | 976 | * on size and returns a valid (and explicit) amount of data for reading */ |
977 | ssize_t bufread(int handle_id, size_t size, void *dest) | 977 | static size_t prep_bufdata(const struct memory_handle *h, size_t size) |
978 | { | 978 | { |
979 | const struct memory_handle *h = find_handle(handle_id); | ||
980 | if (!h) | ||
981 | return ERR_HANDLE_NOT_FOUND; | ||
982 | |||
983 | size_t ret; | ||
984 | size_t avail = RINGBUF_SUB(h->widx, h->ridx); | 979 | size_t avail = RINGBUF_SUB(h->widx, h->ridx); |
985 | 980 | ||
986 | if (avail == 0 && h->filerem == 0) | 981 | if (avail == 0 && h->filerem == 0) |
987 | /* File is finished reading */ | 982 | /* File is finished reading */ |
988 | return 0; | 983 | return 0; |
989 | 984 | ||
990 | if (h->filerem > 0 && (avail == 0 || avail < size)) | 985 | if (size == 0 || size > h->available + h->filerem) |
986 | size = h->available + h->filerem; | ||
987 | |||
988 | if (h->type == TYPE_PACKET_AUDIO && size > BUFFERING_DEFAULT_FILECHUNK) | ||
989 | { | ||
990 | /* If more than a filechunk is requested, log it and provide no more | ||
991 | * than the amount of data on buffer or one file chunk */ | ||
992 | logf("data request > filechunk"); | ||
993 | size = MAX(avail,BUFFERING_DEFAULT_FILECHUNK); | ||
994 | } | ||
995 | |||
996 | if (h->filerem > 0 && avail < size) | ||
991 | { | 997 | { |
992 | /* Data isn't ready. Request buffering */ | 998 | /* Data isn't ready. Request buffering */ |
993 | buf_request_buffer_handle(handle_id); | 999 | buf_request_buffer_handle(h->id); |
994 | /* Wait for the data to be ready */ | 1000 | /* Wait for the data to be ready */ |
995 | do | 1001 | do |
996 | { | 1002 | { |
997 | sleep(1); | 1003 | sleep(1); |
998 | avail = RINGBUF_SUB(h->widx, h->ridx); | 1004 | avail = RINGBUF_SUB(h->widx, h->ridx); |
999 | } | 1005 | } |
1000 | while (h->filerem > 0 && (avail == 0 || avail < size)); | 1006 | while (h->filerem > 0 && avail < size); |
1001 | } | 1007 | } |
1002 | 1008 | ||
1003 | ret = MIN(size, avail); | 1009 | return MIN(size,avail); |
1010 | } | ||
1004 | 1011 | ||
1005 | if (h->ridx + ret > buffer_len) | 1012 | /* Copy data from the given handle to the dest buffer. |
1013 | Return the number of bytes copied or < 0 for failure (handle not found). | ||
1014 | The caller is blocked until the requested amount of data is available. | ||
1015 | */ | ||
1016 | ssize_t bufread(int handle_id, size_t size, void *dest) | ||
1017 | { | ||
1018 | const struct memory_handle *h = find_handle(handle_id); | ||
1019 | if (!h) | ||
1020 | return ERR_HANDLE_NOT_FOUND; | ||
1021 | |||
1022 | size = prep_bufdata(h, size); | ||
1023 | |||
1024 | if (h->ridx + size > buffer_len) | ||
1006 | { | 1025 | { |
1007 | /* the data wraps around the end of the buffer */ | 1026 | /* the data wraps around the end of the buffer */ |
1008 | size_t read = buffer_len - h->ridx; | 1027 | size_t read = buffer_len - h->ridx; |
1009 | memcpy(dest, &buffer[h->ridx], read); | 1028 | memcpy(dest, &buffer[h->ridx], read); |
1010 | memcpy(dest+read, buffer, ret - read); | 1029 | memcpy(dest+read, buffer, size - read); |
1011 | } | 1030 | } |
1012 | else | 1031 | else |
1013 | { | 1032 | { |
1014 | memcpy(dest, &buffer[h->ridx], ret); | 1033 | memcpy(dest, &buffer[h->ridx], size); |
1015 | } | 1034 | } |
1016 | 1035 | ||
1017 | return ret; | 1036 | return size; |
1018 | } | 1037 | } |
1019 | 1038 | ||
1020 | /* Update the "data" pointer to make the handle's data available to the caller. | 1039 | /* Update the "data" pointer to make the handle's data available to the caller. |
@@ -1032,41 +1051,19 @@ ssize_t bufgetdata(int handle_id, size_t size, void **data) | |||
1032 | if (!h) | 1051 | if (!h) |
1033 | return ERR_HANDLE_NOT_FOUND; | 1052 | return ERR_HANDLE_NOT_FOUND; |
1034 | 1053 | ||
1035 | ssize_t ret; | 1054 | size = prep_bufdata(h, size); |
1036 | size_t avail = RINGBUF_SUB(h->widx, h->ridx); | ||
1037 | 1055 | ||
1038 | if (avail == 0 && h->filerem == 0) | 1056 | if (h->ridx + size > buffer_len) |
1039 | /* File is finished reading */ | ||
1040 | return 0; | ||
1041 | |||
1042 | if (h->filerem > 0 && (avail == 0 || avail < size)) | ||
1043 | { | ||
1044 | /* Data isn't ready. Request buffering */ | ||
1045 | buf_request_buffer_handle(handle_id); | ||
1046 | /* Wait for the data to be ready */ | ||
1047 | do | ||
1048 | { | ||
1049 | sleep(1); | ||
1050 | avail = RINGBUF_SUB(h->widx, h->ridx); | ||
1051 | } | ||
1052 | while (h->filerem > 0 && (avail == 0 || avail < size)); | ||
1053 | } | ||
1054 | |||
1055 | if (h->ridx + size > buffer_len && avail >= size) | ||
1056 | { | 1057 | { |
1057 | /* the data wraps around the end of the buffer : | 1058 | /* the data wraps around the end of the buffer : |
1058 | use the guard buffer to provide the requested amount of data. */ | 1059 | use the guard buffer to provide the requested amount of data. */ |
1059 | size_t copy_n = MIN(h->ridx + size - buffer_len, GUARD_BUFSIZE); | 1060 | size_t copy_n = MIN(h->ridx + size - buffer_len, GUARD_BUFSIZE); |
1060 | memcpy(guard_buffer, (unsigned char *)buffer, copy_n); | 1061 | memcpy(guard_buffer, (unsigned char *)buffer, copy_n); |
1061 | ret = buffer_len - h->ridx + copy_n; | 1062 | size = buffer_len - h->ridx + copy_n; |
1062 | } | ||
1063 | else | ||
1064 | { | ||
1065 | ret = MIN(avail, buffer_len - h->ridx); | ||
1066 | } | 1063 | } |
1067 | 1064 | ||
1068 | *data = &buffer[h->ridx]; | 1065 | *data = &buffer[h->ridx]; |
1069 | return ret; | 1066 | return size; |
1070 | } | 1067 | } |
1071 | 1068 | ||
1072 | /* | 1069 | /* |