summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
authorThomas Martitz <kugel@rockbox.org>2011-08-30 21:07:46 +0000
committerThomas Martitz <kugel@rockbox.org>2011-08-30 21:07:46 +0000
commit7e14b935dfdcd808cfb0703d19a43efd11eeef16 (patch)
tree57834f71db1bbaaabf7872d8609f8254371377cf /firmware
parentc1ae789108942f3270fb90bd5a088adfee126333 (diff)
downloadrockbox-7e14b935dfdcd808cfb0703d19a43efd11eeef16.tar.gz
rockbox-7e14b935dfdcd808cfb0703d19a43efd11eeef16.zip
Dircache: Allow dircache to be enabled without reboot.
Also add two dircache function, one of which does what dircache_disable() did previously as this now also frees the dircache buffer. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30393 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r--firmware/common/dircache.c96
-rw-r--r--firmware/include/dircache.h2
2 files changed, 68 insertions, 30 deletions
diff --git a/firmware/common/dircache.c b/firmware/common/dircache.c
index 6b2260def3..c544abc567 100644
--- a/firmware/common/dircache.c
+++ b/firmware/common/dircache.c
@@ -41,6 +41,7 @@
41#include "core_alloc.h" 41#include "core_alloc.h"
42#include "dir.h" 42#include "dir.h"
43#include "storage.h" 43#include "storage.h"
44#include "audio.h"
44#if CONFIG_RTC 45#if CONFIG_RTC
45#include "time.h" 46#include "time.h"
46#include "timefuncs.h" 47#include "timefuncs.h"
@@ -845,7 +846,7 @@ static void dircache_thread(void)
845 case DIRCACHE_BUILD: 846 case DIRCACHE_BUILD:
846 thread_enabled = true; 847 thread_enabled = true;
847 if (dircache_do_rebuild() < 0) 848 if (dircache_do_rebuild() < 0)
848 core_free(dircache_handle); 849 dircache_handle = core_free(dircache_handle);
849 thread_enabled = false; 850 thread_enabled = false;
850 break ; 851 break ;
851 852
@@ -887,8 +888,8 @@ int dircache_build(int last_size)
887 remove_dircache_file(); 888 remove_dircache_file();
888#endif 889#endif
889 890
890 /* Background build, dircache has been previously allocated */ 891 /* Background build, dircache has been previously allocated and */
891 if (allocated_size > 0) 892 if (allocated_size > MAX(last_size, 0))
892 { 893 {
893 d_names_start = d_names_end; 894 d_names_start = d_names_end;
894 dircache_size = 0; 895 dircache_size = 0;
@@ -901,6 +902,9 @@ int dircache_build(int last_size)
901 return 2; 902 return 2;
902 } 903 }
903 904
905 if (dircache_handle > 0)
906 dircache_handle = core_free(dircache_handle);
907
904 if (last_size > DIRCACHE_RESERVE && last_size < DIRCACHE_LIMIT ) 908 if (last_size > DIRCACHE_RESERVE && last_size < DIRCACHE_LIMIT )
905 { 909 {
906 allocated_size = last_size + DIRCACHE_RESERVE; 910 allocated_size = last_size + DIRCACHE_RESERVE;
@@ -922,12 +926,18 @@ int dircache_build(int last_size)
922 * and their corresponding d_name from the end 926 * and their corresponding d_name from the end
923 * after generation the buffer will be compacted with DIRCACHE_RESERVE 927 * after generation the buffer will be compacted with DIRCACHE_RESERVE
924 * free bytes inbetween */ 928 * free bytes inbetween */
925 size_t got_size; 929 size_t available = audio_buffer_available();
926 dircache_handle = core_alloc_maximum("dircache", &got_size, &ops); 930 /* try to allocate at least 1MB, the more the better */
931 if (available < 1<<20) available = 1<<20;
932 if (available > DIRCACHE_LIMIT) available = DIRCACHE_LIMIT;
933
934 dircache_handle = core_alloc_ex("dircache", available, &ops);
935 if (dircache_handle <= 0)
936 return -1; /* that was not successful, should try rebooting */
927 char* buf = core_get_data(dircache_handle); 937 char* buf = core_get_data(dircache_handle);
928 dircache_root = (struct dircache_entry*)ALIGN_UP(buf, 938 dircache_root = (struct dircache_entry*)ALIGN_UP(buf,
929 sizeof(struct dircache_entry*)); 939 sizeof(struct dircache_entry*));
930 d_names_start = d_names_end = buf + got_size - 1; 940 d_names_start = d_names_end = buf + available - 1;
931 dircache_size = 0; 941 dircache_size = 0;
932 generate_dot_d_names(); 942 generate_dot_d_names();
933 943
@@ -967,30 +977,10 @@ int dircache_build(int last_size)
967 return res; 977 return res;
968fail: 978fail:
969 dircache_disable(); 979 dircache_disable();
970 core_free(dircache_handle);
971 return res; 980 return res;
972} 981}
973 982
974/** 983/**
975 * Steal the allocated dircache buffer and disable dircache.
976 */
977void* dircache_steal_buffer(size_t *size)
978{
979 dircache_disable();
980 if (dircache_size == 0)
981 {
982 *size = 0;
983 return NULL;
984 }
985
986 /* since we give up the buffer (without freeing), it must not move anymore */
987 dont_move = true;
988 *size = dircache_size + (DIRCACHE_RESERVE-reserve_used);
989
990 return dircache_root;
991}
992
993/**
994 * Main initialization function that must be called before any other 984 * Main initialization function that must be called before any other
995 * operations within the dircache. 985 * operations within the dircache.
996 */ 986 */
@@ -1085,10 +1075,10 @@ int dircache_get_build_ticks(void)
1085} 1075}
1086 1076
1087/** 1077/**
1088 * Disables the dircache. Usually called on shutdown or when 1078 * Disables dircache without freeing the buffer (so it can be re-enabled
1089 * accepting a usb connection. 1079 * afterwards with dircache_resume() or dircache_build()), usually
1090 */ 1080 * called when accepting an usb connection */
1091void dircache_disable(void) 1081void dircache_suspend(void)
1092{ 1082{
1093 int i; 1083 int i;
1094 bool cache_in_use; 1084 bool cache_in_use;
@@ -1118,6 +1108,52 @@ void dircache_disable(void)
1118} 1108}
1119 1109
1120/** 1110/**
1111 * Re-enables the dircache if previous suspended by dircache_suspend
1112 * or dircache_steal_buffer(), re-using the already allocated buffer
1113 *
1114 * Returns true if the background build is started, false otherwise
1115 * (e.g. if no buffer was previously allocated)
1116 */
1117bool dircache_resume(void)
1118{
1119 bool ret = allocated_size > 0;
1120 if (ret) /* only resume if already allocated */
1121 ret = (dircache_build(0) > 0);
1122
1123 return (allocated_size > 0);
1124}
1125
1126/**
1127 * Disables the dircache entirely. Usually called on shutdown or when
1128 * deactivated
1129 */
1130void dircache_disable(void)
1131{
1132 dircache_suspend();
1133 dircache_handle = core_free(dircache_handle);
1134 dircache_size = allocated_size = 0;
1135}
1136
1137/**
1138 * Steal the allocated dircache buffer and disable dircache.
1139 */
1140void* dircache_steal_buffer(size_t *size)
1141{
1142 dircache_suspend();
1143 if (dircache_size == 0)
1144 {
1145 *size = 0;
1146 return NULL;
1147 }
1148
1149 /* since we give up the buffer (without freeing), it must not move anymore */
1150 dont_move = true;
1151 *size = dircache_size + (DIRCACHE_RESERVE-reserve_used);
1152
1153 return dircache_root;
1154}
1155
1156/**
1121 * Usermode function to return dircache_entry index to the given path. 1157 * Usermode function to return dircache_entry index to the given path.
1122 */ 1158 */
1123static int dircache_get_entry_id_ex(const char *filename, bool go_down) 1159static int dircache_get_entry_id_ex(const char *filename, bool go_down)
diff --git a/firmware/include/dircache.h b/firmware/include/dircache.h
index 6beeeb6c23..019ccf49b7 100644
--- a/firmware/include/dircache.h
+++ b/firmware/include/dircache.h
@@ -76,6 +76,8 @@ int dircache_get_cache_size(void);
76int dircache_get_reserve_used(void); 76int dircache_get_reserve_used(void);
77int dircache_get_build_ticks(void); 77int dircache_get_build_ticks(void);
78void dircache_disable(void); 78void dircache_disable(void);
79void dircache_suspend(void);
80bool dircache_resume(void);
79int dircache_get_entry_id(const char *filename); 81int dircache_get_entry_id(const char *filename);
80size_t dircache_copy_path(int index, char *buf, size_t size); 82size_t dircache_copy_path(int index, char *buf, size_t size);
81 83