Exploring inlined mutable configuration

Currently littlefs uses a separate mutable state struct and immutable
config struct. This lets users place the config struct in ROM where
possible.

However the recent addition of LFS_STATICCFG raises the question of if
this split is still valuable.

If the config is copied into the mutable struct at runtime, this allows
a couple things:
1. Easier user interface, config can be stack allocated, no need to store
   the config struct for the lifetime of littlefs in OSs.
2. Avoids duplication when littlefs would need to change config based on
   observed superblocks, such as LFS_NAME_MAX limits
3. In theory, access to a single struct is faster/smaller as it avoids
   an additional load instruction.

Unfortunately, inlining the dynamic config runs into several issues:

1. The code size actually increases with this change! From digging into
   this it's for a couple reasons:

   - Copying the config over takes code.

   - C has notorious problems with pointer aliasing, accessing
     constants from a const struct actually allows C to assume the
     values aren't going to change in more situations.

     This suggests it may be possible to reduce the code size more by
     loading the config pointer into a variable, but I haven't explored
     this probably not-worth-it optimization.

   - Even assuming deduplication of superblock-dependent configuration,
     the config struct is significantly larger than the mutable struct,
     and it turns out combining these two exceeds the limits of
     immediate-relative-loads, discarding the possible code size
     improvement from avoiding a second dereference.

2. The implementation of dynamic configuration differs significantly from
   the static configuration. This adds mess into the compile-time #ifdefs
   needed to support both options.
This commit is contained in:
Christopher Haster
2020-11-26 10:26:51 -06:00
parent a7cdd563f6
commit f9324d1443
4 changed files with 112 additions and 89 deletions

7
lfs.h
View File

@@ -384,7 +384,7 @@ typedef struct lfs_file {
lfs_cache_t cache;
#ifndef LFS_FILE_STATICCFG
const struct lfs_file_cfg *cfg;
struct lfs_file_cfg cfg;
#endif
} lfs_file_t;
@@ -429,11 +429,8 @@ typedef struct lfs {
} free;
#ifndef LFS_STATICCFG
const struct lfs_cfg *cfg;
struct lfs_cfg cfg;
#endif
lfs_size_t name_max;
lfs_size_t file_max;
lfs_size_t attr_max;
#ifdef LFS_MIGRATE
struct lfs1 *lfs1;