summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmaury Pouly <pamaury@rockbox.org>2010-02-16 22:49:11 +0000
committerAmaury Pouly <pamaury@rockbox.org>2010-02-16 22:49:11 +0000
commit53b1af7a61898ac76a94018fc1863c2a2abf9d3c (patch)
treee76ff6264625ca97ccdd02348a687bda0aa38f55
parentf82c021b8b382613a8bb5e8915c218bc2277a8c1 (diff)
downloadrockbox-53b1af7a61898ac76a94018fc1863c2a2abf9d3c.tar.gz
rockbox-53b1af7a61898ac76a94018fc1863c2a2abf9d3c.zip
-Cosmetic change in a comparison
-Move fat_dir structure out of dircache stack to RAM. Reduce dircache stack size (max level depth should stay be around 20). This should fix nano2g dircache stkov of FS#10679 -Change the structure returned by readdir_cached to match the one returned by readdir_uncached: remove useless fields to save space and avoid any potential incoherence -Remove one field from the internal structure used by {opend,read,close}dir_cached because it was mostly redundant. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@24708 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/common/dircache.c95
-rw-r--r--firmware/include/dir.h2
-rw-r--r--firmware/include/dircache.h17
3 files changed, 61 insertions, 53 deletions
diff --git a/firmware/common/dircache.c b/firmware/common/dircache.c
index e6107801c3..078836147e 100644
--- a/firmware/common/dircache.c
+++ b/firmware/common/dircache.c
@@ -73,7 +73,7 @@ static unsigned int cache_build_ticks = 0;
73static unsigned long appflags = 0; 73static unsigned long appflags = 0;
74 74
75static struct event_queue dircache_queue; 75static struct event_queue dircache_queue;
76static long dircache_stack[(DEFAULT_STACK_SIZE + 0x900)/sizeof(long)]; 76static long dircache_stack[(DEFAULT_STACK_SIZE + 0x200)/sizeof(long)];
77static const char dircache_thread_name[] = "dircache"; 77static const char dircache_thread_name[] = "dircache";
78 78
79static struct fdbind_queue fdbind_cache[MAX_PENDING_BINDINGS]; 79static struct fdbind_queue fdbind_cache[MAX_PENDING_BINDINGS];
@@ -270,6 +270,9 @@ static int sab_process_dir(unsigned long startcluster, struct dircache_entry *ce
270 return rc; 270 return rc;
271} 271}
272 272
273/* used during the generation */
274static struct fat_dir sab_fat_dir;
275
273static int dircache_scan_and_build(IF_MV2(int volume,) struct dircache_entry *ce) 276static int dircache_scan_and_build(IF_MV2(int volume,) struct dircache_entry *ce)
274{ 277{
275 memset(ce, 0, sizeof(struct dircache_entry)); 278 memset(ce, 0, sizeof(struct dircache_entry));
@@ -288,12 +291,11 @@ static int dircache_scan_and_build(IF_MV2(int volume,) struct dircache_entry *ce
288 } 291 }
289#endif 292#endif
290 293
291 struct fat_dir dir; /* allocate on stack once for all scan */
292 struct fat_direntry direntry; /* ditto */ 294 struct fat_direntry direntry; /* ditto */
293#ifdef HAVE_MULTIVOLUME 295#ifdef HAVE_MULTIVOLUME
294 sab.volume = volume; 296 sab.volume = volume;
295#endif 297#endif
296 sab.dir = &dir; 298 sab.dir = &sab_fat_dir;
297 sab.direntry = &direntry; 299 sab.direntry = &direntry;
298 300
299 return sab_process_dir(0, ce); 301 return sab_process_dir(0, ce);
@@ -615,7 +617,7 @@ static int dircache_do_rebuild(void)
615 if (dircache_scan_and_build(IF_MV2(0,) dircache_root) < 0) 617 if (dircache_scan_and_build(IF_MV2(0,) dircache_root) < 0)
616#endif /* HAVE_MULTIVOLUME */ 618#endif /* HAVE_MULTIVOLUME */
617 { 619 {
618 logf("dircache_travel failed"); 620 logf("dircache_scan_and_build failed");
619 cpu_boost(false); 621 cpu_boost(false);
620 dircache_size = 0; 622 dircache_size = 0;
621 dircache_initializing = false; 623 dircache_initializing = false;
@@ -765,7 +767,7 @@ void dircache_init(void)
765 memset(opendirs, 0, sizeof(opendirs)); 767 memset(opendirs, 0, sizeof(opendirs));
766 for (i = 0; i < MAX_OPEN_DIRS; i++) 768 for (i = 0; i < MAX_OPEN_DIRS; i++)
767 { 769 {
768 opendirs[i].secondary_entry.d_name = buffer_alloc(MAX_PATH); 770 opendirs[i].theent.d_name = buffer_alloc(MAX_PATH);
769 } 771 }
770 772
771 queue_init(&dircache_queue, true); 773 queue_init(&dircache_queue, true);
@@ -1205,7 +1207,6 @@ void dircache_add_file(const char *path, long startcluster)
1205 1207
1206DIR_CACHED* opendir_cached(const char* name) 1208DIR_CACHED* opendir_cached(const char* name)
1207{ 1209{
1208 struct dircache_entry *cache_entry;
1209 int dd; 1210 int dd;
1210 DIR_CACHED* pdir = opendirs; 1211 DIR_CACHED* pdir = opendirs;
1211 1212
@@ -1226,23 +1227,22 @@ DIR_CACHED* opendir_cached(const char* name)
1226 errno = EMFILE; 1227 errno = EMFILE;
1227 return NULL; 1228 return NULL;
1228 } 1229 }
1230
1231 pdir->busy = true;
1229 1232
1230 if (!dircache_initialized) 1233 if (!dircache_initialized)
1231 { 1234 {
1232 pdir->regulardir = opendir_uncached(name); 1235 pdir->internal_entry = NULL;
1233 if (!pdir->regulardir) 1236 pdir->regulardir = opendir_uncached(name);
1234 return NULL; 1237 }
1235 1238 else
1236 pdir->busy = true; 1239 {
1237 return pdir; 1240 pdir->regulardir = NULL;
1241 pdir->internal_entry = dircache_get_entry(name, true);
1242 pdir->theent.attribute = -1; /* used to make readdir_cached aware of the first call */
1238 } 1243 }
1239
1240 pdir->busy = true;
1241 pdir->regulardir = NULL;
1242 cache_entry = dircache_get_entry(name, true);
1243 pdir->entry = cache_entry;
1244 1244
1245 if (cache_entry == NULL) 1245 if (pdir->internal_entry == NULL && pdir->regulardir == NULL)
1246 { 1246 {
1247 pdir->busy = false; 1247 pdir->busy = false;
1248 return NULL; 1248 return NULL;
@@ -1251,10 +1251,10 @@ DIR_CACHED* opendir_cached(const char* name)
1251 return pdir; 1251 return pdir;
1252} 1252}
1253 1253
1254struct dircache_entry* readdir_cached(DIR_CACHED* dir) 1254struct dirent_cached* readdir_cached(DIR_CACHED* dir)
1255{ 1255{
1256 struct dircache_entry *ce = dir->internal_entry;
1256 struct dirent_uncached *regentry; 1257 struct dirent_uncached *regentry;
1257 struct dircache_entry *ce;
1258 1258
1259 if (!dir->busy) 1259 if (!dir->busy)
1260 return NULL; 1260 return NULL;
@@ -1265,41 +1265,40 @@ struct dircache_entry* readdir_cached(DIR_CACHED* dir)
1265 if (regentry == NULL) 1265 if (regentry == NULL)
1266 return NULL; 1266 return NULL;
1267 1267
1268 strlcpy(dir->secondary_entry.d_name, regentry->d_name, MAX_PATH); 1268 strlcpy(dir->theent.d_name, regentry->d_name, MAX_PATH);
1269 dir->secondary_entry.size = regentry->size; 1269 dir->theent.size = regentry->size;
1270 dir->secondary_entry.startcluster = regentry->startcluster; 1270 dir->theent.startcluster = regentry->startcluster;
1271 dir->secondary_entry.attribute = regentry->attribute; 1271 dir->theent.attribute = regentry->attribute;
1272 dir->secondary_entry.wrttime = regentry->wrttime; 1272 dir->theent.wrttime = regentry->wrttime;
1273 dir->secondary_entry.wrtdate = regentry->wrtdate; 1273 dir->theent.wrtdate = regentry->wrtdate;
1274 dir->secondary_entry.next = NULL;
1275 1274
1276 return &dir->secondary_entry; 1275 return &dir->theent;
1277 } 1276 }
1278 1277
1279 do { 1278 /* if theent.attribute=-1 then this is the first call */
1280 if (dir->entry == NULL) 1279 /* otherwise, this is is not so we first take the entry's ->next */
1280 /* NOTE: normal file can't have attribute=-1 */
1281 if(dir->theent.attribute != -1)
1282 ce = ce->next;
1283 /* skip unused entries */
1284 while(ce != NULL && ce->name_len == 0)
1285 ce = ce->next;
1286
1287 if (ce == NULL)
1281 return NULL; 1288 return NULL;
1282 1289
1283 ce = dir->entry; 1290 strlcpy(dir->theent.d_name, ce->d_name, MAX_PATH);
1284 if (ce->name_len == 0) 1291 /* Can't do `dir->theent = *ce`
1285 dir->entry = ce->next;
1286 } while (ce->name_len == 0) ;
1287
1288 dir->entry = ce->next;
1289
1290 strlcpy(dir->secondary_entry.d_name, ce->d_name, MAX_PATH);
1291 /* Can't do `dir->secondary_entry = *ce`
1292 because that modifies the d_name pointer. */ 1292 because that modifies the d_name pointer. */
1293 dir->secondary_entry.size = ce->size; 1293 dir->theent.size = ce->size;
1294 dir->secondary_entry.startcluster = ce->startcluster; 1294 dir->theent.startcluster = ce->startcluster;
1295 dir->secondary_entry.attribute = ce->attribute; 1295 dir->theent.attribute = ce->attribute;
1296 dir->secondary_entry.wrttime = ce->wrttime; 1296 dir->theent.wrttime = ce->wrttime;
1297 dir->secondary_entry.wrtdate = ce->wrtdate; 1297 dir->theent.wrtdate = ce->wrtdate;
1298 dir->secondary_entry.next = NULL;
1299 dir->internal_entry = ce; 1298 dir->internal_entry = ce;
1300 1299
1301 //logf("-> %s", ce->name); 1300 //logf("-> %s", ce->name);
1302 return &dir->secondary_entry; 1301 return &dir->theent;
1303} 1302}
1304 1303
1305int closedir_cached(DIR_CACHED* dir) 1304int closedir_cached(DIR_CACHED* dir)
@@ -1325,7 +1324,7 @@ int mkdir_cached(const char *name)
1325int rmdir_cached(const char* name) 1324int rmdir_cached(const char* name)
1326{ 1325{
1327 int rc=rmdir_uncached(name); 1326 int rc=rmdir_uncached(name);
1328 if(rc>=0) 1327 if(rc >= 0)
1329 dircache_rmdir(name); 1328 dircache_rmdir(name);
1330 return(rc); 1329 return(rc);
1331} 1330}
diff --git a/firmware/include/dir.h b/firmware/include/dir.h
index 5aa6cde35a..9ff96e3419 100644
--- a/firmware/include/dir.h
+++ b/firmware/include/dir.h
@@ -44,7 +44,7 @@
44#ifdef HAVE_DIRCACHE 44#ifdef HAVE_DIRCACHE
45# include "dircache.h" 45# include "dircache.h"
46# define DIR DIR_CACHED 46# define DIR DIR_CACHED
47# define dirent dircache_entry 47# define dirent dirent_cached
48# define opendir opendir_cached 48# define opendir opendir_cached
49# define closedir closedir_cached 49# define closedir closedir_cached
50# define readdir readdir_cached 50# define readdir readdir_cached
diff --git a/firmware/include/dircache.h b/firmware/include/dircache.h
index b5b1b72c40..0950d0078b 100644
--- a/firmware/include/dircache.h
+++ b/firmware/include/dircache.h
@@ -76,11 +76,20 @@ struct dircache_entry {
76 char *d_name; 76 char *d_name;
77}; 77};
78 78
79struct dirent_cached {
80 char *d_name;
81 int attribute;
82 long size;
83 long startcluster;
84 unsigned short wrtdate; /* Last write date */
85 unsigned short wrttime; /* Last write time */
86};
87
79typedef struct { 88typedef struct {
80 bool busy; 89 bool busy;
81 struct dircache_entry *entry; 90 struct dirent_cached theent; /* .attribute is set to -1 on init(opendir) */
82 struct dircache_entry *internal_entry; 91 /* the two following field can't be used at the same time so have an union */
83 struct dircache_entry secondary_entry; 92 struct dircache_entry *internal_entry; /* the current entry in the directory */
84 DIR_UNCACHED *regulardir; 93 DIR_UNCACHED *regulardir;
85} DIR_CACHED; 94} DIR_CACHED;
86 95
@@ -111,7 +120,7 @@ void dircache_rename(const char *oldpath, const char *newpath);
111void dircache_add_file(const char *path, long startcluster); 120void dircache_add_file(const char *path, long startcluster);
112 121
113DIR_CACHED* opendir_cached(const char* name); 122DIR_CACHED* opendir_cached(const char* name);
114struct dircache_entry* readdir_cached(DIR_CACHED* dir); 123struct dirent_cached* readdir_cached(DIR_CACHED* dir);
115int closedir_cached(DIR_CACHED *dir); 124int closedir_cached(DIR_CACHED *dir);
116int mkdir_cached(const char *name); 125int mkdir_cached(const char *name);
117int rmdir_cached(const char* name); 126int rmdir_cached(const char* name);