diff --git a/Makefile b/Makefile index 4fa1cf47..fcbc9f1f 100644 --- a/Makefile +++ b/Makefile @@ -20,7 +20,8 @@ TESTS ?= $(wildcard tests/*.toml) TEST_SRC ?= \ $(SRC) \ $(filter-out %.t.c %.b.c %.a.c,$(wildcard bd/*.c)) \ - runners/test_runner.c + $(filter-out %.t.c %.b.c %.a.c,$(wildcard runners/test_*.c)) \ + $(filter-out %.t.c %.b.c %.a.c,$(wildcard tests/*.c)) TEST_RUNNER ?= $(BUILDDIR)/runners/test_runner TEST_C := \ $(TESTS:%.toml=$(BUILDDIR)/%.t.c) \ @@ -39,7 +40,8 @@ BENCHES ?= $(wildcard benches/*.toml) BENCH_SRC ?= \ $(SRC) \ $(filter-out %.t.c %.b.c %.a.c,$(wildcard bd/*.c)) \ - runners/bench_runner.c + $(filter-out %.t.c %.b.c %.a.c,$(wildcard runners/bench_*.c)) \ + $(filter-out %.t.c %.b.c %.a.c,$(wildcard benches/*.c)) BENCH_RUNNER ?= $(BUILDDIR)/runners/bench_runner BENCH_C := \ $(BENCHES:%.toml=$(BUILDDIR)/%.b.c) \ diff --git a/bd/lfs3_emubd.h b/bd/lfs3_emubd.h index 9c8eecd4..56dd027a 100644 --- a/bd/lfs3_emubd.h +++ b/bd/lfs3_emubd.h @@ -215,12 +215,10 @@ int lfs3_emubd_sync(const struct lfs3_cfg *cfg); /// Additional emubd features for testing /// -// Get total simulated runtime +// Get simulated runtime in nanoseconds lfs3_emubd_sns_t lfs3_emubd_simtime(const struct lfs3_cfg *cfg); // Reset simulation counters -// -// You probably shouldn't call this, instead diff before/after simtimes int lfs3_emubd_simreset(const struct lfs3_cfg *cfg); // Get total number of read transactions diff --git a/bd/lfs3_kiwibd.h b/bd/lfs3_kiwibd.h index f3d00c99..f459471d 100644 --- a/bd/lfs3_kiwibd.h +++ b/bd/lfs3_kiwibd.h @@ -137,12 +137,10 @@ int lfs3_kiwibd_sync(const struct lfs3_cfg *cfg); /// Additional kiwibd features /// -// Get total simulated runtime +// Get simulated runtime in nanoseconds lfs3_kiwibd_sns_t lfs3_kiwibd_simtime(const struct lfs3_cfg *cfg); // Reset simulation counters -// -// You probably shouldn't call this, instead diff before/after simtimes int lfs3_kiwibd_simreset(const struct lfs3_cfg *cfg); // Get total number of read transactions diff --git a/runners/bench_defines.h b/runners/bench_defines.h index 3d5a79a8..45d1ada3 100644 --- a/runners/bench_defines.h +++ b/runners/bench_defines.h @@ -25,10 +25,10 @@ BENCH_DEFINE(CRYSTAL_THRESH, BLOCK_SIZE/8 ) BENCH_DEFINE(LOOKGBMAP_THRESH, BLOCK_COUNT/4 ) BENCH_DEFINE(ERASE_VALUE, 0xff ) - // the default timings here are based on NOR flash, specifically - // w25q64jv: - // - // https://www.winbond.com/resource-files/W25Q256JV%20SPI%20RevQ%2002072025%20Plus.pdf + #ifndef BENCH_NAND + // default timings for NOR flash, based on w25q64jv: + // https://www.winbond.com/resource-files/ + // W25Q256JV%20SPI%20RevQ%2002072025%20Plus.pdf // // note one thing unique to NOR flash is the extreme erase cost // @@ -43,24 +43,58 @@ // progs=400000ns tPP=0.4 ms, page=256 // erases=45000000ns tSE=45 ms, sector=4096 // readed=40ns/B fR=50 MHz, quad read (20 ns * 8/4) - // progged=1484ns/B tPP=0.4 ms (((4096/256)*0.4 ms - 0.4 ms)/4096 + bus) + // progged=1484ns/B tPP=0.4 ms (((4096/256)*0.4ms - 0.4ms)/4096 + bus) // erased=0ns/B (no per-byte cost) // #ifdef BENCH_SIMPLE BENCH_DEFINE(READS_TIMING, 0 ) BENCH_DEFINE(PROGS_TIMING, 0 ) - BENCH_DEFINE(ERASES_TIMING, 0 ) + BENCH_DEFINE(ERASES_TIMING, 0 ) BENCH_DEFINE(READED_TIMING, 40 ) BENCH_DEFINE(PROGGED_TIMING, 1582 ) BENCH_DEFINE(ERASED_TIMING, 10986 ) #else BENCH_DEFINE(READS_TIMING, 0 ) BENCH_DEFINE(PROGS_TIMING, 400000 ) - BENCH_DEFINE(ERASES_TIMING, 45000000 ) + BENCH_DEFINE(ERASES_TIMING, 45000000 ) BENCH_DEFINE(READED_TIMING, 40 ) BENCH_DEFINE(PROGGED_TIMING, 1484 ) BENCH_DEFINE(ERASED_TIMING, 0 ) #endif + #else + // default timings for NAND flash, based on w25n01gv: + // https://www.winbond.com/resource-files/W25N01GV%20Rev%20R%20070323.pdf + // + // FR=104 MHz, quad read/prog (9.6 ns * 8/4) + // => +~19 ns for bus + // + // readed=31ns/B tRD1=25 us, p=2048, s=512 (25 us / 2048 + bus) + // progged=141ns/B tPP=250 us, p=2048, s=512 (250 us / 2048 + bus) + // erased=15ns/B tBE=2 ms, block=131072 (2 ms / 131072) + // + // reads=25000ns tRD1=25 us, p=2048, s=512 + // progs=250000ns tPP=250 us, p=2048, s=512 + // erases=2000000ns tBE=2 ms, block=131072 + // readed=31ns/B tRD1=25 us (((131072/2048)*25us - 25us)/131072 + bus) + // progged=139ns/B tPP=250 us (((131072/2048)*250us - 250us)/131072 + bus) + // erased=0ns/B (no per-byte cost) + // + #ifdef BENCH_SIMPLE + BENCH_DEFINE(READS_TIMING, 0 ) + BENCH_DEFINE(PROGS_TIMING, 0 ) + BENCH_DEFINE(ERASES_TIMING, 0 ) + BENCH_DEFINE(READED_TIMING, 31 ) + BENCH_DEFINE(PROGGED_TIMING, 141 ) + BENCH_DEFINE(ERASED_TIMING, 15 ) + #else + BENCH_DEFINE(READS_TIMING, 25000 ) + BENCH_DEFINE(PROGS_TIMING, 250000 ) + BENCH_DEFINE(ERASES_TIMING, 2000000 ) + BENCH_DEFINE(READED_TIMING, 31 ) + BENCH_DEFINE(PROGGED_TIMING, 139 ) + BENCH_DEFINE(ERASED_TIMING, 0 ) + #endif + #endif #ifndef BENCH_KIWIBD BENCH_DEFINE(ERASE_CYCLES, 0 ) BENCH_DEFINE(BADBLOCK_BEHAVIOR, LFS3_EMUBD_BADBLOCK_PROGERROR ) @@ -70,50 +104,76 @@ #endif -// struct lfs3_cfg fields +// struct lfs3_cfg definition #ifdef BENCH_CFG - BENCH_CFG(read_size, READ_SIZE ) - BENCH_CFG(prog_size, PROG_SIZE ) - BENCH_CFG(block_size, BLOCK_SIZE ) - BENCH_CFG(block_count, BLOCK_COUNT ) - BENCH_CFG(block_recycles, BLOCK_RECYCLES ) - BENCH_CFG(rcache_size, RCACHE_SIZE ) - BENCH_CFG(pcache_size, PCACHE_SIZE ) - BENCH_CFG(fcache_size, FCACHE_SIZE ) - BENCH_CFG(lookahead_size, LOOKAHEAD_SIZE ) - #ifdef LFS3_GBMAP - BENCH_CFG(gc_lookgbmap_thresh, GC_LOOKGBMAP_THRESH ) - BENCH_CFG(lookgbmap_thresh, LOOKGBMAP_THRESH ) - #endif - #ifdef LFS3_PREERASE - BENCH_CFG(gc_preerase_count, GC_PREERASE_COUNT ) - #endif - #ifdef LFS3_GC - BENCH_CFG(gc_flags, GC_FLAGS ) - BENCH_CFG(gc_steps, GC_STEPS ) - #endif - BENCH_CFG(gc_lookahead_thresh, GC_LOOKAHEAD_THRESH ) - BENCH_CFG(gc_compact_thresh, GC_COMPACT_THRESH ) - BENCH_CFG(shrub_size, SHRUB_SIZE ) - BENCH_CFG(fragment_size, FRAGMENT_SIZE ) - BENCH_CFG(crystal_thresh, CRYSTAL_THRESH ) + struct lfs3_cfg _cfg = { + #ifdef BENCH_CFG_CFG + BENCH_CFG_CFG + #endif + .read_size = READ_SIZE, + .prog_size = PROG_SIZE, + .block_size = BLOCK_SIZE, + .block_count = BLOCK_COUNT, + .block_recycles = BLOCK_RECYCLES, + .rcache_size = RCACHE_SIZE, + .pcache_size = PCACHE_SIZE, + .fcache_size = FCACHE_SIZE, + .lookahead_size = LOOKAHEAD_SIZE, + #ifdef LFS3_GBMAP + .gc_lookgbmap_thresh = GC_LOOKGBMAP_THRESH, + .lookgbmap_thresh = LOOKGBMAP_THRESH, + #endif + #ifdef LFS3_PREERASE + .gc_preerase_count = GC_PREERASE_COUNT, + #endif + #ifdef LFS3_GC + .gc_flags = GC_FLAGS, + .gc_steps = GC_STEPS, + #endif + .gc_lookahead_thresh = GC_LOOKAHEAD_THRESH, + .gc_compact_thresh = GC_COMPACT_THRESH, + .shrub_size = SHRUB_SIZE, + .fragment_size = FRAGMENT_SIZE, + .crystal_thresh = CRYSTAL_THRESH, + }; + struct lfs3_cfg *BENCH_CFG = &_cfg; #endif -// struct lfs3_*bd_cfg fields +// struct lfs3_*bd_cfg definition #ifdef BENCH_BDCFG - BENCH_BDCFG(erase_value, ERASE_VALUE ) - BENCH_BDCFG(reads_timing, READS_TIMING ) - BENCH_BDCFG(progs_timing, PROGS_TIMING ) - BENCH_BDCFG(erases_timing, ERASES_TIMING ) - BENCH_BDCFG(readed_timing, READED_TIMING ) - BENCH_BDCFG(progged_timing, PROGGED_TIMING ) - BENCH_BDCFG(erased_timing, ERASED_TIMING ) #ifndef BENCH_KIWIBD - BENCH_BDCFG(erase_cycles, ERASE_CYCLES ) - BENCH_BDCFG(badblock_behavior, BADBLOCK_BEHAVIOR ) - BENCH_BDCFG(powerloss_behavior, POWERLOSS_BEHAVIOR ) - BENCH_BDCFG(seed, BD_SEED ) + struct lfs3_emubd_cfg _bdcfg = { + #ifdef BENCH_BDCFG_CFG + BENCH_BDCFG_CFG + #endif + .erase_value = ERASE_VALUE, + .reads_timing = READS_TIMING, + .progs_timing = PROGS_TIMING, + .erases_timing = ERASES_TIMING, + .readed_timing = READED_TIMING, + .progged_timing = PROGGED_TIMING, + .erased_timing = ERASED_TIMING, + .erase_cycles = ERASE_CYCLES, + .badblock_behavior = BADBLOCK_BEHAVIOR, + .powerloss_behavior = POWERLOSS_BEHAVIOR, + .seed = BD_SEED, + }; + struct lfs3_emubd_cfg *BENCH_BDCFG = &_bdcfg; + #else + struct lfs3_kiwibd_cfg _bdcfg = { + #ifdef BENCH_BDCFG_CFG + BENCH_BDCFG_CFG + #endif + .erase_value = ERASE_VALUE, + .reads_timing = READS_TIMING, + .progs_timing = PROGS_TIMING, + .erases_timing = ERASES_TIMING, + .readed_timing = READED_TIMING, + .progged_timing = PROGGED_TIMING, + .erased_timing = ERASED_TIMING, + }; + struct lfs3_kiwibd_cfg *BENCH_BDCFG = &_bdcfg; #endif #endif diff --git a/runners/bench_runner.c b/runners/bench_runner.c index 1710452e..c7594351 100644 --- a/runners/bench_runner.c +++ b/runners/bench_runner.c @@ -137,7 +137,7 @@ typedef struct bench_id { // implicit defines declared here #define BENCH_DEFINE(k, v) \ intmax_t k; - #include "bench_defines.h" + #include BENCH_STRINGIFY(BENCH_DEFINES) #undef BENCH_DEFINE #define BENCH_DEFINE(k, v) \ @@ -146,13 +146,13 @@ typedef struct bench_id { (void)i; \ return v; \ } - #include "bench_defines.h" + #include BENCH_STRINGIFY(BENCH_DEFINES) #undef BENCH_DEFINE const bench_define_t bench_implicit_defines[] = { #define BENCH_DEFINE(k, v) \ {#k, &k, bench_define_##k, NULL, 1}, - #include "bench_defines.h" + #include BENCH_STRINGIFY(BENCH_DEFINES) #undef BENCH_DEFINE }; const size_t bench_implicit_define_count @@ -731,7 +731,7 @@ void bench_heap_resume(void) { #endif #ifdef BENCH_YES_HEAP -static void bench_heap_inc(size_t size) { +void bench_heap_inc(size_t size) { if (bench_heap_entered & 1) { bench_heap_watermark += size; // keep track of the deepest heap @@ -743,7 +743,7 @@ static void bench_heap_inc(size_t size) { #endif #ifdef BENCH_YES_HEAP -static void bench_heap_dec(size_t size) { +void bench_heap_dec(size_t size) { if (bench_heap_entered & 1) { assert(bench_heap_watermark >= size); bench_heap_watermark -= size; @@ -842,12 +842,12 @@ typedef struct bench_record { bench_ns_t last_simtime; } bench_record_t; -static struct lfs3_cfg *bench_cfg = NULL; +static const struct lfs3_cfg *bench_cfg = NULL; static bench_record_t *bench_records; size_t bench_record_count; size_t bench_record_capacity; -void bench_reset(struct lfs3_cfg *cfg) { +void bench_reset(const struct lfs3_cfg *cfg) { bench_cfg = cfg; bench_record_count = 0; } @@ -1807,49 +1807,36 @@ void perm_run( lfs3_kiwibd_t bd; #endif - struct lfs3_cfg cfg = { - .context = &bd, - .read = bench_bd_read, - .prog = bench_bd_prog, - .erase = bench_bd_erase, - .sync = bench_bd_sync, - #define BENCH_CFG(k, v) \ - .k = v, - #include "bench_defines.h" - #undef BENCH_CFG - }; + #define BENCH_CFG CFG + #define BENCH_CFG_CFG \ + .context = &bd, \ + .read = bench_bd_read, \ + .prog = bench_bd_prog, \ + .erase = bench_bd_erase, \ + .sync = bench_bd_sync, + #include BENCH_STRINGIFY(BENCH_DEFINES) + #undef BENCH_CFG_CFG + #undef BENCH_CFG - // using emubd? + #define BENCH_BDCFG BDCFG + #define BENCH_BDCFG_CFG \ + .read_sleep = bench_read_sleep, \ + .prog_sleep = bench_prog_sleep, \ + .erase_sleep = bench_erase_sleep, + #include BENCH_STRINGIFY(BENCH_DEFINES) + #undef BENCH_BDCFG_CFG + #undef BENCH_BDCFG + + // init emubd? #ifndef BENCH_KIWIBD - struct lfs3_emubd_cfg bdcfg = { - .read_sleep = bench_read_sleep, - .prog_sleep = bench_prog_sleep, - .erase_sleep = bench_erase_sleep, - #define BENCH_BDCFG(k, v) \ - .k = v, - #include "bench_defines.h" - #undef BENCH_CFG - }; - - int err = lfs3_emubd_createcfg(&cfg, bench_disk_path, &bdcfg); + int err = lfs3_emubd_createcfg(CFG, bench_disk_path, BDCFG); if (err) { fprintf(stderr, "error: could not create emubd: %d\n", err); exit(-1); } - - // using kiwibd? + // init kiwibd? #else - struct lfs3_kiwibd_cfg bdcfg = { - .read_sleep = bench_read_sleep, - .prog_sleep = bench_prog_sleep, - .erase_sleep = bench_erase_sleep, - #define BENCH_BDCFG(k, v) \ - .k = v, - #include "bench_defines.h" - #undef BENCH_CFG - }; - - int err = lfs3_kiwibd_createcfg(&cfg, bench_disk_path, &bdcfg); + int err = lfs3_kiwibd_createcfg(CFG, bench_disk_path, BDCFG); if (err) { fprintf(stderr, "error: could not create kiwibd: %d\n", err); exit(-1); @@ -1860,7 +1847,7 @@ void perm_run( printf("running "); perm_printid(suite, case_); printf("\n"); - bench_reset(&cfg); + bench_reset(CFG); #ifdef BENCH_YES_STACK bench_stack_enter(); #endif @@ -1868,7 +1855,7 @@ void perm_run( bench_heap_enter(); #endif - case_->run(&cfg); + case_->run(CFG); #ifdef BENCH_YES_HEAP bench_heap_exit(); @@ -1882,13 +1869,13 @@ void perm_run( // cleanup #ifndef BENCH_KIWIBD - err = lfs3_emubd_destroy(&cfg); + err = lfs3_emubd_destroy(CFG); if (err) { fprintf(stderr, "error: could not destroy emubd: %d\n", err); exit(-1); } #else - err = lfs3_kiwibd_destroy(&cfg); + err = lfs3_kiwibd_destroy(CFG); if (err) { fprintf(stderr, "error: could not destroy kiwibd: %d\n", err); exit(-1); diff --git a/runners/bench_runner.h b/runners/bench_runner.h index 4e5be2fd..072bbb75 100644 --- a/runners/bench_runner.h +++ b/runners/bench_runner.h @@ -7,6 +7,24 @@ #ifndef BENCH_RUNNER_H #define BENCH_RUNNER_H +#define BENCH_STRINGIFY_(x) #x +#define BENCH_STRINGIFY(x) BENCH_STRINGIFY_(x) + +// the default BENCH_DEFINES path can be overridden to add shims for +// other filesystems out-of-tree +// +// note this is an unusual header file! instead of being included once, +// BENCH_DEFINES is included several times with various "query macros" +// defined before inclusion: +// +// - BENCH_INCLUDE - common includes (optional) +// - BENCH_DEFINE(name, value) - name and default values for bench defines +// - BENCH_CFG[+_CFG] - struct lfs3_cfg definition +// - BENCH_BDCFG[+_CFG] - struct lfs3_*bd_cfg definition +// +#ifndef BENCH_DEFINES +#define BENCH_DEFINES runners/bench_defines.h +#endif // default to using kiwibd for benches #if !defined(BENCH_EMUBD) && !defined(BENCH_KIWIBD) @@ -37,28 +55,18 @@ void bench_trace(const char *fmt, ...); #define LFS3_EMUBD_TRACE(...) LFS3_TRACE_(__VA_ARGS__, "") #define LFS3_KIWIBD_TRACE(...) LFS3_TRACE_(__VA_ARGS__, "") -// BENCH_START/BENCH_STOP macros measure readed/progged/erased bytes -// through emubd -void bench_start(const char *probe); -void bench_stop(const char *probe, uintmax_t n); - -#define BENCH_START(probe) bench_start(probe) -#define BENCH_STOP(probe, n) bench_stop(probe, n) - -// BENCH_RESULT/BENCH_FRESULT allow for explicit non-io measurements -void bench_result(const char *probe, uintmax_t n, uintmax_t result); -void bench_fresult(const char *probe, uintmax_t n, double result); - -#define BENCH_RESULT(probe, n, result) bench_result(probe, n, result) -#define BENCH_FRESULT(probe, n, result) bench_fresult(probe, n, result) - // note these are indirectly included in any generated files +#define BENCH_INCLUDE + #include BENCH_STRINGIFY(BENCH_DEFINES) +#undef BENCH_INCLUDE + #ifndef BENCH_KIWIBD #include "bd/lfs3_emubd.h" #else #include "bd/lfs3_kiwibd.h" #endif +#include "lfs3_util.h" #include #include @@ -93,7 +101,7 @@ struct bench_case { size_t permutations; bool (*if_)(void); - void (*run)(struct lfs3_cfg *cfg); + void (*run)(const struct lfs3_cfg *cfg); }; struct bench_suite { @@ -112,6 +120,22 @@ extern const struct bench_suite *const bench_suites[]; extern const size_t bench_suite_count; +// BENCH_START/BENCH_STOP macros measure readed/progged/erased bytes +// through emubd +void bench_start(const char *probe); +void bench_stop(const char *probe, uintmax_t n); + +#define BENCH_START(probe) bench_start(probe) +#define BENCH_STOP(probe, n) bench_stop(probe, n) + +// BENCH_RESULT/BENCH_FRESULT allow for explicit non-io measurements +void bench_result(const char *probe, uintmax_t n, uintmax_t result); +void bench_fresult(const char *probe, uintmax_t n, double result); + +#define BENCH_RESULT(probe, n, result) bench_result(probe, n, result) +#define BENCH_FRESULT(probe, n, result) bench_fresult(probe, n, result) + + // deterministic prng for pseudo-randomness in benches uint32_t bench_prng(uint32_t *state); @@ -145,18 +169,22 @@ size_t bench_heap(void); size_t bench_heap_current(void); void bench_heap_pause(void); void bench_heap_resume(void); +void bench_heap_inc(size_t size); +void bench_heap_dec(size_t size); #define BENCH_HEAP() bench_heap() #define BENCH_HEAP_CURRENT() bench_heap_current() #define BENCH_HEAP_PAUSE() bench_heap_pause() #define BENCH_HEAP_RESUME() bench_heap_resume() +#define BENCH_HEAP_INC(size) bench_heap_inc(size) +#define BENCH_HEAP_DEC(size) bench_heap_dec(size) #endif // declare implicit defines as global intmax_ts #define BENCH_DEFINE(k, v) \ extern intmax_t k; - #include "bench_defines.h" + #include BENCH_STRINGIFY(BENCH_DEFINES) #undef BENCH_DEFINE diff --git a/runners/test_defines.h b/runners/test_defines.h index 525df9fb..3adad7e2 100644 --- a/runners/test_defines.h +++ b/runners/test_defines.h @@ -34,44 +34,64 @@ #endif -// struct lfs3_cfg fields +// struct lfs3_cfg definition #ifdef TEST_CFG - TEST_CFG(read_size, READ_SIZE ) - TEST_CFG(prog_size, PROG_SIZE ) - TEST_CFG(block_size, BLOCK_SIZE ) - TEST_CFG(block_count, BLOCK_COUNT ) - TEST_CFG(block_recycles, BLOCK_RECYCLES ) - TEST_CFG(rcache_size, RCACHE_SIZE ) - TEST_CFG(pcache_size, PCACHE_SIZE ) - TEST_CFG(fcache_size, FCACHE_SIZE ) - TEST_CFG(lookahead_size, LOOKAHEAD_SIZE ) - #ifdef LFS3_GBMAP - TEST_CFG(gc_lookgbmap_thresh, GC_LOOKGBMAP_THRESH ) - TEST_CFG(lookgbmap_thresh, LOOKGBMAP_THRESH ) - #endif - #ifdef LFS3_PREERASE - TEST_CFG(gc_preerase_count, GC_PREERASE_COUNT ) - #endif - #ifdef LFS3_GC - TEST_CFG(gc_flags, GC_FLAGS ) - TEST_CFG(gc_steps, GC_STEPS ) - #endif - TEST_CFG(gc_lookahead_thresh, GC_LOOKAHEAD_THRESH ) - TEST_CFG(gc_compact_thresh, GC_COMPACT_THRESH ) - TEST_CFG(shrub_size, SHRUB_SIZE ) - TEST_CFG(fragment_size, FRAGMENT_SIZE ) - TEST_CFG(crystal_thresh, CRYSTAL_THRESH ) + struct lfs3_cfg _cfg = { + #ifdef TEST_CFG_CFG + TEST_CFG_CFG + #endif + .read_size = READ_SIZE, + .prog_size = PROG_SIZE, + .block_size = BLOCK_SIZE, + .block_count = BLOCK_COUNT, + .block_recycles = BLOCK_RECYCLES, + .rcache_size = RCACHE_SIZE, + .pcache_size = PCACHE_SIZE, + .fcache_size = FCACHE_SIZE, + .lookahead_size = LOOKAHEAD_SIZE, + #ifdef LFS3_GBMAP + .gc_lookgbmap_thresh = GC_LOOKGBMAP_THRESH, + .lookgbmap_thresh = LOOKGBMAP_THRESH, + #endif + #ifdef LFS3_PREERASE + .gc_preerase_count = GC_PREERASE_COUNT, + #endif + #ifdef LFS3_GC + .gc_flags = GC_FLAGS, + .gc_steps = GC_STEPS, + #endif + .gc_lookahead_thresh = GC_LOOKAHEAD_THRESH, + .gc_compact_thresh = GC_COMPACT_THRESH, + .shrub_size = SHRUB_SIZE, + .fragment_size = FRAGMENT_SIZE, + .crystal_thresh = CRYSTAL_THRESH, + }; + struct lfs3_cfg *TEST_CFG = &_cfg; #endif -// struct lfs3_*bd_cfg fields +// struct lfs3_*bd_cfg definition #ifdef TEST_BDCFG - TEST_BDCFG(erase_value, ERASE_VALUE ) #ifndef TEST_KIWIBD - TEST_BDCFG(erase_cycles, ERASE_CYCLES ) - TEST_BDCFG(badblock_behavior, BADBLOCK_BEHAVIOR ) - TEST_BDCFG(powerloss_behavior, POWERLOSS_BEHAVIOR ) - TEST_BDCFG(seed, BD_SEED ) + struct lfs3_emubd_cfg _bdcfg = { + #ifdef TEST_BDCFG_CFG + TEST_BDCFG_CFG + #endif + .erase_value = ERASE_VALUE, + .erase_cycles = ERASE_CYCLES, + .badblock_behavior = BADBLOCK_BEHAVIOR, + .powerloss_behavior = POWERLOSS_BEHAVIOR, + .seed = BD_SEED, + }; + struct lfs3_emubd_cfg *TEST_BDCFG = &_bdcfg; + #else + struct lfs3_kiwibd_cfg _bdcfg = { + #ifdef TEST_BDCFG_CFG + TEST_BDCFG_CFG + #endif + .erase_value = ERASE_VALUE, + }; + struct lfs3_kiwibd_cfg *TEST_BDCFG = &_bdcfg; #endif #endif diff --git a/runners/test_runner.c b/runners/test_runner.c index b47103ee..efe7a59b 100644 --- a/runners/test_runner.c +++ b/runners/test_runner.c @@ -148,7 +148,7 @@ typedef struct test_id { // implicit defines declared here #define TEST_DEFINE(k, v) \ intmax_t k; - #include "test_defines.h" + #include TEST_STRINGIFY(TEST_DEFINES) #undef TEST_DEFINE #define TEST_DEFINE(k, v) \ @@ -157,13 +157,13 @@ typedef struct test_id { (void)i; \ return v; \ } - #include "test_defines.h" + #include TEST_STRINGIFY(TEST_DEFINES) #undef TEST_DEFINE const test_define_t test_implicit_defines[] = { #define TEST_DEFINE(k, v) \ {#k, &k, test_define_##k, NULL, 1}, - #include "test_defines.h" + #include TEST_STRINGIFY(TEST_DEFINES) #undef TEST_DEFINE }; const size_t test_implicit_define_count @@ -747,7 +747,7 @@ void test_heap_resume(void) { #endif #ifdef TEST_YES_HEAP -static void test_heap_inc(size_t size) { +void test_heap_inc(size_t size) { if (test_heap_entered & 1) { test_heap_watermark += size; // keep track of the deepest heap @@ -759,7 +759,7 @@ static void test_heap_inc(size_t size) { #endif #ifdef TEST_YES_HEAP -static void test_heap_dec(size_t size) { +void test_heap_dec(size_t size) { if (test_heap_entered & 1) { assert(test_heap_watermark >= size); test_heap_watermark -= size; @@ -1646,49 +1646,36 @@ static void run_powerloss_none( lfs3_kiwibd_t bd; #endif - struct lfs3_cfg cfg = { - .context = &bd, - .read = test_bd_read, - .prog = test_bd_prog, - .erase = test_bd_erase, - .sync = test_bd_sync, - #define TEST_CFG(k, v) \ - .k = v, - #include "test_defines.h" - #undef TEST_CFG - }; + #define TEST_CFG CFG + #define TEST_CFG_CFG \ + .context = &bd, \ + .read = test_bd_read, \ + .prog = test_bd_prog, \ + .erase = test_bd_erase, \ + .sync = test_bd_sync, + #include TEST_STRINGIFY(TEST_DEFINES) + #undef TEST_CFG_CFG + #undef TEST_CFG - // using emubd? + #define TEST_BDCFG BDCFG + #define TEST_BDCFG_CFG \ + .read_sleep = test_read_sleep, \ + .prog_sleep = test_prog_sleep, \ + .erase_sleep = test_erase_sleep, + #include TEST_STRINGIFY(TEST_DEFINES) + #undef TEST_BDCFG_CFG + #undef TEST_BDCFG + + // init emubd? #ifndef TEST_KIWIBD - struct lfs3_emubd_cfg bdcfg = { - .read_sleep = test_read_sleep, - .prog_sleep = test_prog_sleep, - .erase_sleep = test_erase_sleep, - #define TEST_BDCFG(k, v) \ - .k = v, - #include "test_defines.h" - #undef TEST_BDCFG - }; - - int err = lfs3_emubd_createcfg(&cfg, test_disk_path, &bdcfg); + int err = lfs3_emubd_createcfg(CFG, test_disk_path, BDCFG); if (err) { fprintf(stderr, "error: could not create emubd: %d\n", err); exit(-1); } - - // using kiwibd? + // init kiwibd? #else - struct lfs3_kiwibd_cfg bdcfg = { - .read_sleep = test_read_sleep, - .prog_sleep = test_prog_sleep, - .erase_sleep = test_erase_sleep, - #define TEST_BDCFG(k, v) \ - .k = v, - #include "test_defines.h" - #undef TEST_CFG - }; - - int err = lfs3_kiwibd_createcfg(&cfg, test_disk_path, &bdcfg); + int err = lfs3_kiwibd_createcfg(CFG, test_disk_path, BDCFG); if (err) { fprintf(stderr, "error: could not create kiwibd: %d\n", err); exit(-1); @@ -1706,7 +1693,7 @@ static void run_powerloss_none( test_heap_enter(); #endif - case_->run(&cfg); + case_->run(CFG); #ifdef TEST_YES_HEAP test_heap_exit(); @@ -1720,13 +1707,13 @@ static void run_powerloss_none( // cleanup #ifndef TEST_KIWIBD - err = lfs3_emubd_destroy(&cfg); + err = lfs3_emubd_destroy(CFG); if (err) { fprintf(stderr, "error: could not destroy emubd: %d\n", err); exit(-1); } #else - err = lfs3_kiwibd_destroy(&cfg); + err = lfs3_kiwibd_destroy(CFG); if (err) { fprintf(stderr, "error: could not destroy kiwibd: %d\n", err); exit(-1); @@ -1753,34 +1740,32 @@ static void run_powerloss_linear( lfs3_emubd_t bd; jmp_buf powerloss_jmp; - struct lfs3_cfg cfg = { - .context = &bd, - .read = test_bd_read, - .prog = test_bd_prog, - .erase = test_bd_erase, - .sync = test_bd_sync, - #define TEST_CFG(k, v) \ - .k = v, - #include "test_defines.h" - #undef TEST_CFG - }; + #define TEST_CFG CFG + #define TEST_CFG_CFG \ + .context = &bd, \ + .read = test_bd_read, \ + .prog = test_bd_prog, \ + .erase = test_bd_erase, \ + .sync = test_bd_sync, + #include TEST_STRINGIFY(TEST_DEFINES) + #undef TEST_CFG_CFG + #undef TEST_CFG - struct lfs3_emubd_cfg bdcfg = { - .read_sleep = test_read_sleep, - .prog_sleep = test_prog_sleep, - .erase_sleep = test_erase_sleep, - .power_cycles = (TEST_PLS < powerloss->cycle_count) - ? TEST_PLS+1 - : 0, - .powerloss_cb = powerloss_longjmp, - .powerloss_data = &powerloss_jmp, - #define TEST_BDCFG(k, v) \ - .k = v, - #include "test_defines.h" - #undef TEST_BDCFG - }; + #define TEST_BDCFG BDCFG + #define TEST_BDCFG_CFG \ + .read_sleep = test_read_sleep, \ + .prog_sleep = test_prog_sleep, \ + .erase_sleep = test_erase_sleep, \ + .power_cycles = (TEST_PLS < powerloss->cycle_count) \ + ? TEST_PLS+1 \ + : 0, \ + .powerloss_cb = powerloss_longjmp, \ + .powerloss_data = &powerloss_jmp, + #include TEST_STRINGIFY(TEST_DEFINES) + #undef TEST_BDCFG_CFG + #undef TEST_BDCFG - int err = lfs3_emubd_createcfg(&cfg, test_disk_path, &bdcfg); + int err = lfs3_emubd_createcfg(CFG, test_disk_path, BDCFG); if (err) { fprintf(stderr, "error: could not create emubd: %d\n", err); exit(-1); @@ -1801,7 +1786,7 @@ static void run_powerloss_linear( #endif // run the test - case_->run(&cfg); + case_->run(CFG); #ifdef TEST_YES_HEAP test_heap_exit(); @@ -1821,7 +1806,7 @@ static void run_powerloss_linear( // increment pls TEST_PLS += 1; - lfs3_emubd_setpowercycles(&cfg, (TEST_PLS < powerloss->cycle_count) + lfs3_emubd_setpowercycles(CFG, (TEST_PLS < powerloss->cycle_count) ? TEST_PLS+1 : 0); } @@ -1831,7 +1816,7 @@ static void run_powerloss_linear( printf("\n"); // cleanup - err = lfs3_emubd_destroy(&cfg); + err = lfs3_emubd_destroy(CFG); if (err) { fprintf(stderr, "error: could not destroy emubd: %d\n", err); exit(-1); @@ -1851,34 +1836,32 @@ static void run_powerloss_log( lfs3_emubd_t bd; jmp_buf powerloss_jmp; - struct lfs3_cfg cfg = { - .context = &bd, - .read = test_bd_read, - .prog = test_bd_prog, - .erase = test_bd_erase, - .sync = test_bd_sync, - #define TEST_CFG(k, v) \ - .k = v, - #include "test_defines.h" - #undef TEST_CFG - }; + #define TEST_CFG CFG + #define TEST_CFG_CFG \ + .context = &bd, \ + .read = test_bd_read, \ + .prog = test_bd_prog, \ + .erase = test_bd_erase, \ + .sync = test_bd_sync, + #include TEST_STRINGIFY(TEST_DEFINES) + #undef TEST_CFG_CFG + #undef TEST_CFG - struct lfs3_emubd_cfg bdcfg = { - .read_sleep = test_read_sleep, - .prog_sleep = test_prog_sleep, - .erase_sleep = test_erase_sleep, - .power_cycles = (TEST_PLS < powerloss->cycle_count) - ? 1 << TEST_PLS - : 0, - .powerloss_cb = powerloss_longjmp, - .powerloss_data = &powerloss_jmp, - #define TEST_BDCFG(k, v) \ - .k = v, - #include "test_defines.h" - #undef TEST_BDCFG - }; + #define TEST_BDCFG BDCFG + #define TEST_BDCFG_CFG \ + .read_sleep = test_read_sleep, \ + .prog_sleep = test_prog_sleep, \ + .erase_sleep = test_erase_sleep, \ + .power_cycles = (TEST_PLS < powerloss->cycle_count) \ + ? 1 << TEST_PLS \ + : 0, \ + .powerloss_cb = powerloss_longjmp, \ + .powerloss_data = &powerloss_jmp, + #include TEST_STRINGIFY(TEST_DEFINES) + #undef TEST_BDCFG_CFG + #undef TEST_BDCFG - int err = lfs3_emubd_createcfg(&cfg, test_disk_path, &bdcfg); + int err = lfs3_emubd_createcfg(CFG, test_disk_path, BDCFG); if (err) { fprintf(stderr, "error: could not create emubd: %d\n", err); exit(-1); @@ -1899,7 +1882,7 @@ static void run_powerloss_log( #endif // run the test - case_->run(&cfg); + case_->run(CFG); #ifdef TEST_YES_HEAP test_heap_exit(); @@ -1919,7 +1902,7 @@ static void run_powerloss_log( // increment pls TEST_PLS += 1; - lfs3_emubd_setpowercycles(&cfg, (TEST_PLS < powerloss->cycle_count) + lfs3_emubd_setpowercycles(CFG, (TEST_PLS < powerloss->cycle_count) ? 1 << TEST_PLS : 0); } @@ -1929,7 +1912,7 @@ static void run_powerloss_log( printf("\n"); // cleanup - err = lfs3_emubd_destroy(&cfg); + err = lfs3_emubd_destroy(CFG); if (err) { fprintf(stderr, "error: could not destroy emubd: %d\n", err); exit(-1); @@ -1949,34 +1932,32 @@ static void run_powerloss_cycles( lfs3_emubd_t bd; jmp_buf powerloss_jmp; - struct lfs3_cfg cfg = { - .context = &bd, - .read = test_bd_read, - .prog = test_bd_prog, - .erase = test_bd_erase, - .sync = test_bd_sync, - #define TEST_CFG(k, v) \ - .k = v, - #include "test_defines.h" - #undef TEST_CFG - }; + #define TEST_CFG CFG + #define TEST_CFG_CFG \ + .context = &bd, \ + .read = test_bd_read, \ + .prog = test_bd_prog, \ + .erase = test_bd_erase, \ + .sync = test_bd_sync, + #include TEST_STRINGIFY(TEST_DEFINES) + #undef TEST_CFG_CFG + #undef TEST_CFG - struct lfs3_emubd_cfg bdcfg = { - .read_sleep = test_read_sleep, - .prog_sleep = test_prog_sleep, - .erase_sleep = test_erase_sleep, - .power_cycles = (TEST_PLS < powerloss->cycle_count) - ? powerloss->cycles[TEST_PLS] - : 0, - .powerloss_cb = powerloss_longjmp, - .powerloss_data = &powerloss_jmp, - #define TEST_BDCFG(k, v) \ - .k = v, - #include "test_defines.h" - #undef TEST_BDCFG - }; + #define TEST_BDCFG BDCFG + #define TEST_BDCFG_CFG \ + .read_sleep = test_read_sleep, \ + .prog_sleep = test_prog_sleep, \ + .erase_sleep = test_erase_sleep, \ + .power_cycles = (TEST_PLS < powerloss->cycle_count) \ + ? powerloss->cycles[TEST_PLS] \ + : 0, \ + .powerloss_cb = powerloss_longjmp, \ + .powerloss_data = &powerloss_jmp, + #include TEST_STRINGIFY(TEST_DEFINES) + #undef TEST_BDCFG_CFG + #undef TEST_BDCFG - int err = lfs3_emubd_createcfg(&cfg, test_disk_path, &bdcfg); + int err = lfs3_emubd_createcfg(CFG, test_disk_path, BDCFG); if (err) { fprintf(stderr, "error: could not create emubd: %d\n", err); exit(-1); @@ -1997,7 +1978,7 @@ static void run_powerloss_cycles( #endif // run the test - case_->run(&cfg); + case_->run(CFG); #ifdef TEST_YES_HEAP test_heap_exit(); @@ -2016,7 +1997,7 @@ static void run_powerloss_cycles( // increment pls TEST_PLS += 1; - lfs3_emubd_setpowercycles(&cfg, (TEST_PLS < powerloss->cycle_count) + lfs3_emubd_setpowercycles(CFG, (TEST_PLS < powerloss->cycle_count) ? powerloss->cycles[TEST_PLS] : 0); } @@ -2026,7 +2007,7 @@ static void run_powerloss_cycles( printf("\n"); // cleanup - err = lfs3_emubd_destroy(&cfg); + err = lfs3_emubd_destroy(CFG); if (err) { fprintf(stderr, "error: could not destroy emubd: %d\n", err); exit(-1); @@ -2167,31 +2148,29 @@ static void run_powerloss_exhaustive( // create block device and configuration lfs3_emubd_t bd; - struct lfs3_cfg cfg = { - .context = &bd, - .read = test_bd_read, - .prog = test_bd_prog, - .erase = test_bd_erase, - .sync = test_bd_sync, - #define TEST_CFG(k, v) \ - .k = v, - #include "test_defines.h" - #undef TEST_CFG - }; + #define TEST_CFG CFG + #define TEST_CFG_CFG \ + .context = &bd, \ + .read = test_bd_read, \ + .prog = test_bd_prog, \ + .erase = test_bd_erase, \ + .sync = test_bd_sync, + #include TEST_STRINGIFY(TEST_DEFINES) + #undef TEST_CFG_CFG + #undef TEST_CFG - struct lfs3_emubd_cfg bdcfg = { - .read_sleep = test_read_sleep, - .prog_sleep = test_prog_sleep, - .erase_sleep = test_erase_sleep, - .powerloss_cb = powerloss_exhaustive_branch, - .powerloss_data = NULL, - #define TEST_BDCFG(k, v) \ - .k = v, - #include "test_defines.h" - #undef TEST_BDCFG - }; + #define TEST_BDCFG BDCFG + #define TEST_BDCFG_CFG \ + .read_sleep = test_read_sleep, \ + .prog_sleep = test_prog_sleep, \ + .erase_sleep = test_erase_sleep, \ + .powerloss_cb = powerloss_exhaustive_branch, \ + .powerloss_data = NULL, + #include TEST_STRINGIFY(TEST_DEFINES) + #undef TEST_BDCFG_CFG + #undef TEST_BDCFG - int err = lfs3_emubd_createcfg(&cfg, test_disk_path, &bdcfg); + int err = lfs3_emubd_createcfg(CFG, test_disk_path, BDCFG); if (err) { fprintf(stderr, "error: could not create emubd: %d\n", err); exit(-1); @@ -2206,7 +2185,7 @@ static void run_powerloss_exhaustive( run_powerloss_exhaustive_layer( &(struct powerloss_exhaustive_cycles){NULL, 0, 0}, suite, case_, - &cfg, &bdcfg, powerloss->cycle_count, 0); + CFG, BDCFG, powerloss->cycle_count, 0); printf("finished "); perm_printid(suite, case_, NULL, 0); diff --git a/runners/test_runner.h b/runners/test_runner.h index 8a661eb8..666241b9 100644 --- a/runners/test_runner.h +++ b/runners/test_runner.h @@ -7,6 +7,24 @@ #ifndef TEST_RUNNER_H #define TEST_RUNNER_H +#define TEST_STRINGIFY_(x) #x +#define TEST_STRINGIFY(x) TEST_STRINGIFY_(x) + +// the default TEST_DEFINES path can be overridden to add shims for +// other filesystems out-of-tree +// +// note this is an unusual header file! instead of being included once, +// TEST_DEFINES is included several times with various "query macros" +// defined before inclusion: +// +// - TEST_INCLUDE - common includes (optional) +// - TEST_DEFINE(name, value) - name and default values for test defines +// - TEST_CFG[+_CFG] - struct lfs3_cfg definition +// - TEST_BDCFG[+_CFG] - struct lfs3_*bd_cfg definition +// +#ifndef TEST_DEFINES +#define TEST_DEFINES runners/test_defines.h +#endif // default to using emubd for tests #if !defined(TEST_EMUBD) && !defined(TEST_KIWIBD) @@ -39,11 +57,16 @@ void test_trace(const char *fmt, ...); // note these are indirectly included in any generated files +#define TEST_INCLUDE + #include TEST_STRINGIFY(TEST_DEFINES) +#undef TEST_INCLUDE + #ifndef TEST_KIWIBD #include "bd/lfs3_emubd.h" #else #include "bd/lfs3_kiwibd.h" #endif +#include "lfs3_util.h" #include #include @@ -80,7 +103,7 @@ struct test_case { size_t permutations; bool (*if_)(void); - void (*run)(struct lfs3_cfg *cfg); + void (*run)(const struct lfs3_cfg *cfg); }; struct test_suite { @@ -136,18 +159,22 @@ size_t test_heap(void); size_t test_heap_current(void); void test_heap_pause(void); void test_heap_resume(void); +void test_heap_inc(size_t size); +void test_heap_dec(size_t size); #define TEST_HEAP() test_heap() #define TEST_HEAP_CURRENT() test_heap_current() #define TEST_HEAP_PAUSE() test_heap_pause() #define TEST_HEAP_RESUME() test_heap_resume() +#define TEST_HEAP_INC(size) test_heap_inc(size) +#define TEST_HEAP_DEC(size) test_heap_dec(size) #endif // declare implicit defines as global intmax_ts #define TEST_DEFINE(k, v) \ extern intmax_t k; - #include "test_defines.h" + #include TEST_STRINGIFY(TEST_DEFINES) #undef TEST_DEFINE diff --git a/scripts/bench.py b/scripts/bench.py index 5fdf9d0d..2cdadb1e 100755 --- a/scripts/bench.py +++ b/scripts/bench.py @@ -483,7 +483,7 @@ def compile(bench_paths, **args): # create case run function f.writeln('void __bench__%s__run(' '__attribute__((unused)) ' - 'struct lfs3_cfg *CFG) {' % ( + 'const struct lfs3_cfg *CFG) {' % ( case.name)) f.writeln(4*' '+'// bench case %s' % case.name) if case.code_lineno is not None: @@ -550,7 +550,7 @@ def compile(bench_paths, **args): 'void);' % ( case.name)) f.writeln('extern void __bench__%s__run(' - 'struct lfs3_cfg *CFG);' % ( + 'const struct lfs3_cfg *CFG);' % ( case.name)) f.writeln() diff --git a/scripts/test.py b/scripts/test.py index ae570030..f67da9bf 100755 --- a/scripts/test.py +++ b/scripts/test.py @@ -495,7 +495,7 @@ def compile(test_paths, **args): # create case run function f.writeln('void __test__%s__run(' '__attribute__((unused)) ' - 'struct lfs3_cfg *CFG) {' % ( + 'const struct lfs3_cfg *CFG) {' % ( case.name)) f.writeln(4*' '+'// test case %s' % case.name) if case.code_lineno is not None: @@ -562,7 +562,7 @@ def compile(test_paths, **args): 'void);' % ( case.name)) f.writeln('extern void __test__%s__run(' - 'struct lfs3_cfg *CFG);' % ( + 'const struct lfs3_cfg *CFG);' % ( case.name)) f.writeln()