summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Martitz <kugel@rockbox.org>2014-02-24 23:07:37 +0100
committerThomas Martitz <kugel@rockbox.org>2014-02-24 23:07:37 +0100
commitc27c3f10fd8c32e837c1f11176dc7223542bda6d (patch)
tree5c5cf1900071c8dac231409364f9948d4f6bc48f
parent3a3d26eee223f5d7307b9ab31d0dee93c82a41f5 (diff)
downloadrockbox-c27c3f10fd8c32e837c1f11176dc7223542bda6d.tar.gz
rockbox-c27c3f10fd8c32e837c1f11176dc7223542bda6d.zip
hosted/multidrive: Speed up readdir()/get_dir_info().
The two functions need to check whether they are called for a specific path to implement the virtual mount point for the external storage. This is statistically rare and a hit on the common case. Therefore speed up the common case by performing integer comparision first, and only expensive string construction and comparision if that succeeds. Change-Id: I3c41fe073e1f4f8eb62d2b8556a36937c9cb8290
-rw-r--r--firmware/common/rbpaths.c49
-rw-r--r--firmware/export/rbpaths.h6
2 files changed, 37 insertions, 18 deletions
diff --git a/firmware/common/rbpaths.c b/firmware/common/rbpaths.c
index dba39476fc..c59ef7cf65 100644
--- a/firmware/common/rbpaths.c
+++ b/firmware/common/rbpaths.c
@@ -28,6 +28,7 @@
28#include <unistd.h> 28#include <unistd.h>
29#include "config.h" 29#include "config.h"
30#include "rbpaths.h" 30#include "rbpaths.h"
31#include "crc32.h"
31#include "file.h" /* MAX_PATH */ 32#include "file.h" /* MAX_PATH */
32#include "logf.h" 33#include "logf.h"
33#include "gcc_extensions.h" 34#include "gcc_extensions.h"
@@ -52,9 +53,11 @@
52 53
53#if (CONFIG_PLATFORM & PLATFORM_ANDROID) 54#if (CONFIG_PLATFORM & PLATFORM_ANDROID)
54static const char rbhome[] = "/sdcard"; 55static const char rbhome[] = "/sdcard";
55#endif 56#elif (CONFIG_PLATFORM & (PLATFORM_SDL|PLATFORM_MAEMO|PLATFORM_PANDORA)) && !defined(__PCTOOL__)
56#if (CONFIG_PLATFORM & (PLATFORM_SDL|PLATFORM_MAEMO|PLATFORM_PANDORA)) && !defined(__PCTOOL__)
57const char *rbhome; 57const char *rbhome;
58#else
59/* YPR0, YPR1 */
60static const char rbhome[] = HOME_DIR;
58#endif 61#endif
59 62
60#if !(defined(SAMSUNG_YPR0) || defined(SAMSUNG_YPR1)) && !defined(__PCTOOL__) 63#if !(defined(SAMSUNG_YPR0) || defined(SAMSUNG_YPR1)) && !defined(__PCTOOL__)
@@ -62,9 +65,6 @@ const char *rbhome;
62 * over the ones where Rockbox is installed to. Classic example would be 65 * over the ones where Rockbox is installed to. Classic example would be
63 * $HOME/.config/rockbox.org vs /usr/share/rockbox */ 66 * $HOME/.config/rockbox.org vs /usr/share/rockbox */
64#define HAVE_SPECIAL_DIRS 67#define HAVE_SPECIAL_DIRS
65#define IS_HOME(p) (!strcmp(p, rbhome))
66#else
67#define IS_HOME(p) (!strcmp(p, HOME_DIR))
68#endif 68#endif
69 69
70/* flags for get_user_file_path() */ 70/* flags for get_user_file_path() */
@@ -75,6 +75,7 @@ const char *rbhome;
75#define IS_FILE (1<<1) 75#define IS_FILE (1<<1)
76 76
77#ifdef HAVE_MULTIDRIVE 77#ifdef HAVE_MULTIDRIVE
78static uint32_t rbhome_hash;
78/* A special link is created under e.g. HOME_DIR/<microSD1>, e.g. to access 79/* A special link is created under e.g. HOME_DIR/<microSD1>, e.g. to access
79 * external storage in a convinient location, much similar to the mount 80 * external storage in a convinient location, much similar to the mount
80 * point on our native targets. Here they are treated as symlink (one which 81 * point on our native targets. Here they are treated as symlink (one which
@@ -103,9 +104,9 @@ static const char *handle_special_links(const char* link, unsigned flags,
103} 104}
104#endif 105#endif
105 106
106#ifdef HAVE_SPECIAL_DIRS
107void paths_init(void) 107void paths_init(void)
108{ 108{
109#ifdef HAVE_SPECIAL_DIRS
109 /* make sure $HOME/.config/rockbox.org exists, it's needed for config.cfg */ 110 /* make sure $HOME/.config/rockbox.org exists, it's needed for config.cfg */
110#if (CONFIG_PLATFORM & PLATFORM_ANDROID) 111#if (CONFIG_PLATFORM & PLATFORM_ANDROID)
111 mkdir("/sdcard/rockbox", 0777); 112 mkdir("/sdcard/rockbox", 0777);
@@ -133,9 +134,14 @@ void paths_init(void)
133 snprintf(config_dir, sizeof(config_dir), "%s/.config/rockbox.org/rocks.data", home); 134 snprintf(config_dir, sizeof(config_dir), "%s/.config/rockbox.org/rocks.data", home);
134 mkdir(config_dir, 0777); 135 mkdir(config_dir, 0777);
135#endif 136#endif
137#endif /* HAVE_SPECIAL_DIRS */
136 138
139#ifdef HAVE_MULTIDRIVE
140 rbhome_hash = crc_32((const void *) rbhome, strlen(rbhome), 0xffffffff);
141#endif /* HAVE_MULTIDRIVE */
137} 142}
138 143
144#ifdef HAVE_SPECIAL_DIRS
139static bool try_path(const char* filename, unsigned flags) 145static bool try_path(const char* filename, unsigned flags)
140{ 146{
141 if (flags & IS_FILE) 147 if (flags & IS_FILE)
@@ -189,8 +195,6 @@ static const char* _get_user_file_path(const char *path,
189 return ret; 195 return ret;
190} 196}
191 197
192#elif !defined(paths_init)
193void paths_init(void) { }
194#endif 198#endif
195 199
196static const char* handle_special_dirs(const char* dir, unsigned flags, 200static const char* handle_special_dirs(const char* dir, unsigned flags,
@@ -261,7 +265,14 @@ int app_rename(const char *old, const char *new)
261 * get_dir_info() */ 265 * get_dir_info() */
262struct __dir { 266struct __dir {
263 DIR *dir; 267 DIR *dir;
264 IF_MD(int volumes_returned); 268#ifdef HAVE_MULTIDRIVE
269 int volumes_returned;
270 /* A crc of rbhome is used to speed op the common case where
271 * readdir()/get_dir_info() is called on non-rbhome paths, because
272 * each call needs to check against rbhome for the virtual
273 * mount point of the external storage */
274 uint32_t path_hash;
275#endif
265 char path[]; 276 char path[];
266}; 277};
267 278
@@ -278,7 +289,9 @@ struct dirinfo dir_get_info(DIR* _parent, struct dirent *dir)
278#ifdef HAVE_MULTIDRIVE 289#ifdef HAVE_MULTIDRIVE
279 char vol_string[VOL_ENUM_POS + 8]; 290 char vol_string[VOL_ENUM_POS + 8];
280 sprintf(vol_string, VOL_NAMES, 1); 291 sprintf(vol_string, VOL_NAMES, 1);
281 if (!strcmp(vol_string, dir->d_name)) 292 if (UNLIKELY(rbhome_hash == parent->path_hash) &&
293 /* compare path anyway because of possible hash collision */
294 !strcmp(vol_string, dir->d_name))
282 { 295 {
283 ret.attribute = ATTR_LINK; 296 ret.attribute = ATTR_LINK;
284 strcpy(path, MULTIDRIVE_DIR); 297 strcpy(path, MULTIDRIVE_DIR);
@@ -314,9 +327,11 @@ struct dirinfo dir_get_info(DIR* _parent, struct dirent *dir)
314 327
315DIR* app_opendir(const char *_name) 328DIR* app_opendir(const char *_name)
316{ 329{
330 size_t name_len;
317 char realpath[MAX_PATH]; 331 char realpath[MAX_PATH];
318 const char *name = handle_special_dirs(_name, 0, realpath, sizeof(realpath)); 332 const char *name = handle_special_dirs(_name, 0, realpath, sizeof(realpath));
319 char *buf = malloc(sizeof(struct __dir) + strlen(name)+1); 333 name_len = strlen(name);
334 char *buf = malloc(sizeof(struct __dir) + name_len+1);
320 if (!buf) 335 if (!buf)
321 return NULL; 336 return NULL;
322 337
@@ -331,7 +346,11 @@ DIR* app_opendir(const char *_name)
331 free(buf); 346 free(buf);
332 return NULL; 347 return NULL;
333 } 348 }
334 IF_MD(this->volumes_returned = 0); 349#ifdef HAVE_MULTIDRIVE
350 this->volumes_returned = 0;
351 this->path_hash = crc_32((const void *)this->path, name_len, 0xffffffff);
352#endif
353
335 return (DIR*)this; 354 return (DIR*)this;
336} 355}
337 356
@@ -350,9 +369,11 @@ struct dirent* app_readdir(DIR* dir)
350#ifdef HAVE_MULTIDRIVE 369#ifdef HAVE_MULTIDRIVE
351 /* this is not MT-safe but OK according to man readdir */ 370 /* this is not MT-safe but OK according to man readdir */
352 static struct dirent voldir; 371 static struct dirent voldir;
353 if (d->volumes_returned < (NUM_VOLUMES-1) 372 if (UNLIKELY(rbhome_hash == d->path_hash)
373 && d->volumes_returned < (NUM_VOLUMES-1)
354 && volume_present(d->volumes_returned+1) 374 && volume_present(d->volumes_returned+1)
355 && IS_HOME(d->path)) 375 /* compare path anyway because of possible hash collision */
376 && !strcmp(d->path, rbhome))
356 { 377 {
357 d->volumes_returned += 1; 378 d->volumes_returned += 1;
358 sprintf(voldir.d_name, VOL_NAMES, d->volumes_returned); 379 sprintf(voldir.d_name, VOL_NAMES, d->volumes_returned);
diff --git a/firmware/export/rbpaths.h b/firmware/export/rbpaths.h
index 1f7e1a2643..3600709482 100644
--- a/firmware/export/rbpaths.h
+++ b/firmware/export/rbpaths.h
@@ -55,8 +55,6 @@
55#define PLUGIN_DIR ROCKBOX_DIR "/rocks" 55#define PLUGIN_DIR ROCKBOX_DIR "/rocks"
56#define CODECS_DIR ROCKBOX_DIR "/codecs" 56#define CODECS_DIR ROCKBOX_DIR "/codecs"
57 57
58#define paths_init()
59
60#else /* APPLICATION */ 58#else /* APPLICATION */
61 59
62#define HOME_DIR "<HOME>" /* replaced at runtime */ 60#define HOME_DIR "<HOME>" /* replaced at runtime */
@@ -68,8 +66,6 @@
68#define CODECS_DIR ROCKBOX_LIBRARY_PATH "/rockbox/codecs" 66#define CODECS_DIR ROCKBOX_LIBRARY_PATH "/rockbox/codecs"
69#endif 67#endif
70 68
71extern void paths_init(void);
72
73#endif /* !APPLICATION || SAMSUNG_YPR0 */ 69#endif /* !APPLICATION || SAMSUNG_YPR0 */
74 70
75#define HOME_DIR_LEN (sizeof(HOME_DIR)-1) 71#define HOME_DIR_LEN (sizeof(HOME_DIR)-1)
@@ -91,6 +87,8 @@ int app_mkdir(const char* name);
91int app_rmdir(const char* name); 87int app_rmdir(const char* name);
92ssize_t app_readlink(const char *path, char *buf, size_t bufsiz); 88ssize_t app_readlink(const char *path, char *buf, size_t bufsiz);
93 89
90extern void paths_init(void);
91
94#endif 92#endif
95 93
96#define REC_BASE_DIR HOME_DIR 94#define REC_BASE_DIR HOME_DIR