From 53b1af7a61898ac76a94018fc1863c2a2abf9d3c Mon Sep 17 00:00:00 2001 From: Amaury Pouly Date: Tue, 16 Feb 2010 22:49:11 +0000 Subject: [PATCH] -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 --- firmware/common/dircache.c | 95 ++++++++++++++++++------------------- firmware/include/dir.h | 2 +- firmware/include/dircache.h | 17 +++++-- 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; static unsigned long appflags = 0; static struct event_queue dircache_queue; -static long dircache_stack[(DEFAULT_STACK_SIZE + 0x900)/sizeof(long)]; +static long dircache_stack[(DEFAULT_STACK_SIZE + 0x200)/sizeof(long)]; static const char dircache_thread_name[] = "dircache"; static struct fdbind_queue fdbind_cache[MAX_PENDING_BINDINGS]; @@ -270,6 +270,9 @@ static int sab_process_dir(unsigned long startcluster, struct dircache_entry *ce return rc; } +/* used during the generation */ +static struct fat_dir sab_fat_dir; + static int dircache_scan_and_build(IF_MV2(int volume,) struct dircache_entry *ce) { 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 } #endif - struct fat_dir dir; /* allocate on stack once for all scan */ struct fat_direntry direntry; /* ditto */ #ifdef HAVE_MULTIVOLUME sab.volume = volume; #endif - sab.dir = &dir; + sab.dir = &sab_fat_dir; sab.direntry = &direntry; return sab_process_dir(0, ce); @@ -615,7 +617,7 @@ static int dircache_do_rebuild(void) if (dircache_scan_and_build(IF_MV2(0,) dircache_root) < 0) #endif /* HAVE_MULTIVOLUME */ { - logf("dircache_travel failed"); + logf("dircache_scan_and_build failed"); cpu_boost(false); dircache_size = 0; dircache_initializing = false; @@ -765,7 +767,7 @@ void dircache_init(void) memset(opendirs, 0, sizeof(opendirs)); for (i = 0; i < MAX_OPEN_DIRS; i++) { - opendirs[i].secondary_entry.d_name = buffer_alloc(MAX_PATH); + opendirs[i].theent.d_name = buffer_alloc(MAX_PATH); } queue_init(&dircache_queue, true); @@ -1205,7 +1207,6 @@ void dircache_add_file(const char *path, long startcluster) DIR_CACHED* opendir_cached(const char* name) { - struct dircache_entry *cache_entry; int dd; DIR_CACHED* pdir = opendirs; @@ -1226,23 +1227,22 @@ DIR_CACHED* opendir_cached(const char* name) errno = EMFILE; return NULL; } + + pdir->busy = true; if (!dircache_initialized) { - pdir->regulardir = opendir_uncached(name); - if (!pdir->regulardir) - return NULL; - - pdir->busy = true; - return pdir; + pdir->internal_entry = NULL; + pdir->regulardir = opendir_uncached(name); + } + else + { + pdir->regulardir = NULL; + pdir->internal_entry = dircache_get_entry(name, true); + pdir->theent.attribute = -1; /* used to make readdir_cached aware of the first call */ } - - pdir->busy = true; - pdir->regulardir = NULL; - cache_entry = dircache_get_entry(name, true); - pdir->entry = cache_entry; - if (cache_entry == NULL) + if (pdir->internal_entry == NULL && pdir->regulardir == NULL) { pdir->busy = false; return NULL; @@ -1251,10 +1251,10 @@ DIR_CACHED* opendir_cached(const char* name) return pdir; } -struct dircache_entry* readdir_cached(DIR_CACHED* dir) +struct dirent_cached* readdir_cached(DIR_CACHED* dir) { + struct dircache_entry *ce = dir->internal_entry; struct dirent_uncached *regentry; - struct dircache_entry *ce; if (!dir->busy) return NULL; @@ -1265,41 +1265,40 @@ struct dircache_entry* readdir_cached(DIR_CACHED* dir) if (regentry == NULL) return NULL; - strlcpy(dir->secondary_entry.d_name, regentry->d_name, MAX_PATH); - dir->secondary_entry.size = regentry->size; - dir->secondary_entry.startcluster = regentry->startcluster; - dir->secondary_entry.attribute = regentry->attribute; - dir->secondary_entry.wrttime = regentry->wrttime; - dir->secondary_entry.wrtdate = regentry->wrtdate; - dir->secondary_entry.next = NULL; + strlcpy(dir->theent.d_name, regentry->d_name, MAX_PATH); + dir->theent.size = regentry->size; + dir->theent.startcluster = regentry->startcluster; + dir->theent.attribute = regentry->attribute; + dir->theent.wrttime = regentry->wrttime; + dir->theent.wrtdate = regentry->wrtdate; - return &dir->secondary_entry; + return &dir->theent; } - - do { - if (dir->entry == NULL) + + /* if theent.attribute=-1 then this is the first call */ + /* otherwise, this is is not so we first take the entry's ->next */ + /* NOTE: normal file can't have attribute=-1 */ + if(dir->theent.attribute != -1) + ce = ce->next; + /* skip unused entries */ + while(ce != NULL && ce->name_len == 0) + ce = ce->next; + + if (ce == NULL) return NULL; - ce = dir->entry; - if (ce->name_len == 0) - dir->entry = ce->next; - } while (ce->name_len == 0) ; - - dir->entry = ce->next; - - strlcpy(dir->secondary_entry.d_name, ce->d_name, MAX_PATH); - /* Can't do `dir->secondary_entry = *ce` + strlcpy(dir->theent.d_name, ce->d_name, MAX_PATH); + /* Can't do `dir->theent = *ce` because that modifies the d_name pointer. */ - dir->secondary_entry.size = ce->size; - dir->secondary_entry.startcluster = ce->startcluster; - dir->secondary_entry.attribute = ce->attribute; - dir->secondary_entry.wrttime = ce->wrttime; - dir->secondary_entry.wrtdate = ce->wrtdate; - dir->secondary_entry.next = NULL; + dir->theent.size = ce->size; + dir->theent.startcluster = ce->startcluster; + dir->theent.attribute = ce->attribute; + dir->theent.wrttime = ce->wrttime; + dir->theent.wrtdate = ce->wrtdate; dir->internal_entry = ce; //logf("-> %s", ce->name); - return &dir->secondary_entry; + return &dir->theent; } int closedir_cached(DIR_CACHED* dir) @@ -1325,7 +1324,7 @@ int mkdir_cached(const char *name) int rmdir_cached(const char* name) { int rc=rmdir_uncached(name); - if(rc>=0) + if(rc >= 0) dircache_rmdir(name); return(rc); } 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 @@ #ifdef HAVE_DIRCACHE # include "dircache.h" # define DIR DIR_CACHED -# define dirent dircache_entry +# define dirent dirent_cached # define opendir opendir_cached # define closedir closedir_cached # 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 { char *d_name; }; +struct dirent_cached { + char *d_name; + int attribute; + long size; + long startcluster; + unsigned short wrtdate; /* Last write date */ + unsigned short wrttime; /* Last write time */ +}; + typedef struct { bool busy; - struct dircache_entry *entry; - struct dircache_entry *internal_entry; - struct dircache_entry secondary_entry; + struct dirent_cached theent; /* .attribute is set to -1 on init(opendir) */ + /* the two following field can't be used at the same time so have an union */ + struct dircache_entry *internal_entry; /* the current entry in the directory */ DIR_UNCACHED *regulardir; } DIR_CACHED; @@ -111,7 +120,7 @@ void dircache_rename(const char *oldpath, const char *newpath); void dircache_add_file(const char *path, long startcluster); DIR_CACHED* opendir_cached(const char* name); -struct dircache_entry* readdir_cached(DIR_CACHED* dir); +struct dirent_cached* readdir_cached(DIR_CACHED* dir); int closedir_cached(DIR_CACHED *dir); int mkdir_cached(const char *name); int rmdir_cached(const char* name);