From c1b86ac9db88a15dd1fba6007f737d03a8745977 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Thu, 5 Feb 2026 23:24:32 -0600 Subject: [PATCH] runners: A number of stack/heap measurement tweaks - Renamed BENCH_STACK/HEAP -> BENCH_STACK/HEAP_WATERMARK - Renamed BENCH_YES_STACK/HEAP -> BENCH_STACK/HEAP - Tweaked stack/heap watermarks to hopefully be easier to access when debugging. Now also exposed as global variables (bench_stack/heap_watermark). I considered changing BENCH_STACK/HEAP_WATERMARK to be the variable itself, to be consistent with TEST_PLS, but decided against it: 1. BENCH_STACK_CURRENT() is a bit magic in that it relies on __attribute__((noinline)) to force a new stack frame. This wouldn't really be possible with a variable. 2. TEST_PLS is at least constant from the _current run_'s perspective. This isn't true for the stack/heap watermarks. - Reworked internals a bit to hopefully be simpler --- Makefile | 8 +- benches/bench_helpers.c | 16 ---- benches/bench_wt.toml | 32 +++---- runners/bench_runner.c | 183 ++++++++++------------------------------ runners/bench_runner.h | 32 ++++--- runners/test_runner.c | 183 ++++++++++++++-------------------------- runners/test_runner.h | 32 ++++--- 7 files changed, 168 insertions(+), 318 deletions(-) diff --git a/Makefile b/Makefile index 248d6f1b..45819c2c 100644 --- a/Makefile +++ b/Makefile @@ -104,10 +104,10 @@ CFLAGS += $(foreach d,$(filter LFS3_%,$(.VARIABLES)),-D$d=$($d)) TEST_CFLAGS += -Wno-unused-function TEST_CFLAGS += -Wno-format-overflow ifdef STACK -TEST_CFLAGS += -DTEST_YES_STACK +TEST_CFLAGS += -DTEST_STACK endif ifdef HEAP -TEST_CFLAGS += -DTEST_YES_HEAP +TEST_CFLAGS += -DTEST_HEAP TEST_CFLAGS += -Wl,--wrap=malloc TEST_CFLAGS += -Wl,--wrap=free TEST_CFLAGS += -Wl,--wrap=realloc @@ -116,10 +116,10 @@ endif BENCH_CFLAGS += -Wno-unused-function BENCH_CFLAGS += -Wno-format-overflow ifndef NO_STACK -BENCH_CFLAGS += -DBENCH_YES_STACK +BENCH_CFLAGS += -DBENCH_STACK endif ifndef NO_HEAP -BENCH_CFLAGS += -DBENCH_YES_HEAP +BENCH_CFLAGS += -DBENCH_HEAP BENCH_CFLAGS += -Wl,--wrap=malloc BENCH_CFLAGS += -Wl,--wrap=free BENCH_CFLAGS += -Wl,--wrap=realloc diff --git a/benches/bench_helpers.c b/benches/bench_helpers.c index 0253605a..bc5bfa90 100644 --- a/benches/bench_helpers.c +++ b/benches/bench_helpers.c @@ -10,12 +10,8 @@ // this writes a 1 block file 2*block_count times to get it into a good // state for benchmarking int bench_helpers_warmup(lfs3_t *lfs3) { - #ifdef BENCH_YES_STACK BENCH_STACK_PAUSE(); - #endif - #ifdef BENCH_YES_HEAP BENCH_HEAP_PAUSE(); - #endif uint8_t *wbuf = malloc(BLOCK_SIZE); memset(wbuf, '1', BLOCK_SIZE); @@ -34,24 +30,16 @@ int bench_helpers_warmup(lfs3_t *lfs3) { free(wbuf); - #ifdef BENCH_YES_HEAP BENCH_HEAP_RESUME(); - #endif - #ifdef BENCH_YES_STACK BENCH_STACK_RESUME(); - #endif return 0; } // find tight disk usage uintmax_t bench_helpers_usage(lfs3_t *lfs3) { - #ifdef BENCH_YES_STACK BENCH_STACK_PAUSE(); - #endif - #ifdef BENCH_YES_HEAP BENCH_HEAP_PAUSE(); - #endif // measure disk usage // @@ -83,12 +71,8 @@ uintmax_t bench_helpers_usage(lfs3_t *lfs3) { free(usage_bmap); - #ifdef BENCH_YES_HEAP BENCH_HEAP_RESUME(); - #endif - #ifdef BENCH_YES_STACK BENCH_STACK_RESUME(); - #endif return (uintmax_t)usage * (uintmax_t)BLOCK_SIZE; } diff --git a/benches/bench_wt.toml b/benches/bench_wt.toml index af03056f..e37814e7 100644 --- a/benches/bench_wt.toml +++ b/benches/bench_wt.toml @@ -83,11 +83,11 @@ code = ''' BENCH_STOP("write", written); // report the total stack/heap usage after the benchmark - #ifdef BENCH_YES_STACK - BENCH_RESULT("stack", written, BENCH_STACK()); + #ifdef BENCH_STACK + BENCH_RESULT("stack", written, BENCH_STACK_WATERMARK()); #endif - #ifdef BENCH_YES_HEAP - BENCH_RESULT("heap", written, BENCH_HEAP()); + #ifdef BENCH_HEAP + BENCH_RESULT("heap", written, BENCH_HEAP_WATERMARK()); #endif // find the total disk usage after the benchmark @@ -144,11 +144,11 @@ code = ''' BENCH_STOP("write", written); // report the total stack/heap usage after the benchmark - #ifdef BENCH_YES_STACK - BENCH_RESULT("stack", written, BENCH_STACK()); + #ifdef BENCH_STACK + BENCH_RESULT("stack", written, BENCH_STACK_WATERMARK()); #endif - #ifdef BENCH_YES_HEAP - BENCH_RESULT("heap", written, BENCH_HEAP()); + #ifdef BENCH_HEAP + BENCH_RESULT("heap", written, BENCH_HEAP_WATERMARK()); #endif // find the total disk usage after the benchmark @@ -223,11 +223,11 @@ code = ''' BENCH_STOP("write", written); // report the total stack/heap usage after the benchmark - #ifdef BENCH_YES_STACK - BENCH_RESULT("stack", written, BENCH_STACK()); + #ifdef BENCH_STACK + BENCH_RESULT("stack", written, BENCH_STACK_WATERMARK()); #endif - #ifdef BENCH_YES_HEAP - BENCH_RESULT("heap", written, BENCH_HEAP()); + #ifdef BENCH_HEAP + BENCH_RESULT("heap", written, BENCH_HEAP_WATERMARK()); #endif // find the total disk usage after the benchmark @@ -292,11 +292,11 @@ code = ''' BENCH_STOP("write", written); // report the total stack/heap usage after the benchmark - #ifdef BENCH_YES_STACK - BENCH_RESULT("stack", written, BENCH_STACK()); + #ifdef BENCH_STACK + BENCH_RESULT("stack", written, BENCH_STACK_WATERMARK()); #endif - #ifdef BENCH_YES_HEAP - BENCH_RESULT("heap", written, BENCH_HEAP()); + #ifdef BENCH_HEAP + BENCH_RESULT("heap", written, BENCH_HEAP_WATERMARK()); #endif // find the total disk usage after the benchmark diff --git a/runners/bench_runner.c b/runners/bench_runner.c index 7ef31e50..7dbc95bb 100644 --- a/runners/bench_runner.c +++ b/runners/bench_runner.c @@ -617,98 +617,85 @@ void bench_permutation(size_t i, uint32_t *buffer, size_t size) { // stack hooks -#ifdef BENCH_YES_STACK -uint8_t *bench_stack_watermark_enter; -uint8_t *bench_stack_watermark_depth; +#ifdef BENCH_STACK +uint8_t *bench_stack_entrance = NULL; +size_t bench_stack_watermark = 0; #endif // call me when entering/exiting a bench! -#ifdef BENCH_YES_STACK +#ifdef BENCH_STACK __attribute__((noinline)) void bench_stack_enter(void) { - bench_stack_watermark_enter = __builtin_frame_address(0); - bench_stack_watermark_depth = bench_stack_watermark_enter; + bench_stack_entrance = __builtin_frame_address(0); + bench_stack_watermark = 0; } #endif -#ifdef BENCH_YES_STACK +#ifdef BENCH_STACK void bench_stack_exit(void) { // do nothing } #endif // call me when entering/exiting a bd op! -#ifdef BENCH_YES_STACK +#ifdef BENCH_STACK __attribute__((noinline)) void bench_stack_pause(void) { - uint8_t *watermark = __builtin_frame_address(0); + uint8_t *current = __builtin_frame_address(0); // keep track of the deepest stack - ssize_t depth = bench_stack_watermark_depth - bench_stack_watermark_enter; + ssize_t depth = current - bench_stack_entrance; if (depth < 0) { depth = -depth; } - ssize_t depth_ = watermark - bench_stack_watermark_enter; - if (depth_ < 0) { - depth_ = -depth_; - } - if (depth_ > depth) { - bench_stack_watermark_depth = watermark; + + if ((size_t)depth > bench_stack_watermark) { + bench_stack_watermark = depth; } } #endif -#ifdef BENCH_YES_STACK +#ifdef BENCH_STACK void bench_stack_resume(void) { // do nothing } #endif -// get the worst-case stack usage -#ifdef BENCH_YES_STACK -size_t bench_stack(void) { - ssize_t depth = bench_stack_watermark_depth - bench_stack_watermark_enter; - if (depth < 0) { - depth = -depth; - } - return depth; -} -#endif - -// get the current stack usage, note this is included in bench_stack +// get the current stack usage // -// note note the noinline here is important for forcing a new stack frame -#ifdef BENCH_YES_STACK +// note the noinline here is important for forcing a new stack frame +#ifdef BENCH_STACK __attribute__((noinline)) size_t bench_stack_current(void) { - uint8_t *watermark = __builtin_frame_address(0); + uint8_t *current = __builtin_frame_address(0); - ssize_t depth = watermark - bench_stack_watermark_enter; + ssize_t depth = current - bench_stack_entrance; if (depth < 0) { depth = -depth; } + return depth; } #endif // heap hooks -#ifdef BENCH_YES_HEAP +#ifdef BENCH_HEAP uint32_t bench_heap_entered = 0; +size_t bench_heap_current = 0; size_t bench_heap_watermark = 0; -size_t bench_heap_watermark_depth = 0; #endif // call me when entering/exiting a bench! -#ifdef BENCH_YES_HEAP +#ifdef BENCH_HEAP void bench_heap_enter(void) { bench_heap_entered = 1; + bench_heap_current = 0; bench_heap_watermark = 0; - bench_heap_watermark_depth = 0; } #endif -#ifdef BENCH_YES_HEAP +#ifdef BENCH_HEAP void bench_heap_exit(void) { bench_heap_entered = 0; if (bench_heap_watermark != 0) { @@ -719,56 +706,42 @@ void bench_heap_exit(void) { #endif // call me when entering/exiting a bd op! -#ifdef BENCH_YES_HEAP +#ifdef BENCH_HEAP void bench_heap_pause(void) { // haha, a little 32-bit stack bench_heap_entered <<= 1; } #endif -#ifdef BENCH_YES_HEAP +#ifdef BENCH_HEAP void bench_heap_resume(void) { bench_heap_entered >>= 1; } #endif -#ifdef BENCH_YES_HEAP +#ifdef BENCH_HEAP void bench_heap_inc(size_t size) { if (bench_heap_entered & 1) { - bench_heap_watermark += size; + bench_heap_current += size; // keep track of the deepest heap - if (bench_heap_watermark > bench_heap_watermark_depth) { - bench_heap_watermark_depth = bench_heap_watermark; + if (bench_heap_current > bench_heap_watermark) { + bench_heap_watermark = bench_heap_current; } } } #endif -#ifdef BENCH_YES_HEAP +#ifdef BENCH_HEAP void bench_heap_dec(size_t size) { if (bench_heap_entered & 1) { - assert(bench_heap_watermark >= size); - bench_heap_watermark -= size; + assert(bench_heap_current >= size); + bench_heap_current -= size; } } #endif -// get the worst-case heap usage -#ifdef BENCH_YES_HEAP -size_t bench_heap(void) { - return bench_heap_watermark_depth; -} -#endif - -// get the current heap usage -#ifdef BENCH_YES_HEAP -size_t bench_heap_current(void) { - return bench_heap_watermark; -} -#endif - // __real_malloc stubs, gcc's --wrap wraps these over the original symbols -#ifdef BENCH_YES_HEAP +#ifdef BENCH_HEAP extern void *__real_malloc(size_t size); extern void __real_free(void *p); extern void *__real_realloc(void *p, size_t size); @@ -777,7 +750,7 @@ extern void *__real_realloc(void *p, size_t size); // the actual malloc hooks // // these only work if wrapped via gcc's --wrap -#ifdef BENCH_YES_HEAP +#ifdef BENCH_HEAP void *__wrap_malloc(size_t size) { // prefix with allocation size, note we use uintptr_t to hopefully // keep things aligned @@ -786,13 +759,13 @@ void *__wrap_malloc(size_t size) { return NULL; } - bench_heap_inc(size); + BENCH_HEAP_INC(size); *p_ = size; return p_ + 1; } #endif -#ifdef BENCH_YES_HEAP +#ifdef BENCH_HEAP void __wrap_free(void *p) { if (!p) { return; @@ -800,13 +773,13 @@ void __wrap_free(void *p) { uintptr_t *p_ = ((uintptr_t*)p) - 1; size_t size = *p_; - bench_heap_dec(size); + BENCH_HEAP_DEC(size); __real_free(p_); } #endif -#ifdef BENCH_YES_HEAP +#ifdef BENCH_HEAP void *__wrap_realloc(void *p, size_t size) { uintptr_t *p_; size_t old; @@ -824,8 +797,8 @@ void *__wrap_realloc(void *p, size_t size) { return NULL; } - bench_heap_dec(old); - bench_heap_inc(size); + BENCH_HEAP_DEC(old); + BENCH_HEAP_INC(size); *p_ = size; return p_ + 1; } @@ -862,12 +835,8 @@ void bench_reset(const struct lfs3_cfg *cfg) { } void bench_start(const char *probe) { - #ifdef BENCH_YES_STACK BENCH_STACK_PAUSE(); - #endif - #ifdef BENCH_YES_HEAP BENCH_HEAP_PAUSE(); - #endif // measure current read/prog/erase assert(bench_cfg); @@ -936,21 +905,13 @@ void bench_start(const char *probe) { record->last_erased = erased; record->last_simtime = simtime; - #ifdef BENCH_YES_HEAP BENCH_HEAP_RESUME(); - #endif - #ifdef BENCH_YES_STACK BENCH_STACK_RESUME(); - #endif } void bench_stop(const char *probe, uintmax_t n) { - #ifdef BENCH_YES_STACK BENCH_STACK_PAUSE(); - #endif - #ifdef BENCH_YES_HEAP BENCH_HEAP_PAUSE(); - #endif // measure current read/prog/erase assert(bench_cfg); @@ -1042,21 +1003,13 @@ void bench_stop(const char *probe, uintmax_t n) { } done:; - #ifdef BENCH_YES_HEAP BENCH_HEAP_RESUME(); - #endif - #ifdef BENCH_YES_STACK BENCH_STACK_RESUME(); - #endif } void bench_result(const char *probe, uintmax_t n, uintmax_t result) { - #ifdef BENCH_YES_STACK BENCH_STACK_PAUSE(); - #endif - #ifdef BENCH_YES_HEAP BENCH_HEAP_PAUSE(); - #endif // we just print these directly printf("benched %s %jd %"PRIu64"\n", @@ -1064,21 +1017,13 @@ void bench_result(const char *probe, uintmax_t n, uintmax_t result) { n, result); - #ifdef BENCH_YES_HEAP BENCH_HEAP_RESUME(); - #endif - #ifdef BENCH_YES_STACK BENCH_STACK_RESUME(); - #endif } void bench_fresult(const char *probe, uintmax_t n, double result) { - #ifdef BENCH_YES_STACK BENCH_STACK_PAUSE(); - #endif - #ifdef BENCH_YES_HEAP BENCH_HEAP_PAUSE(); - #endif // we just print these directly printf("benched %s %jd %.6f\n", @@ -1086,12 +1031,8 @@ void bench_fresult(const char *probe, uintmax_t n, double result) { n, result); - #ifdef BENCH_YES_HEAP BENCH_HEAP_RESUME(); - #endif - #ifdef BENCH_YES_STACK BENCH_STACK_RESUME(); - #endif } @@ -1730,12 +1671,8 @@ static void list_implicit_defines(void) { // bench bd wrappers for heap/stack tracking int bench_bd_read(const struct lfs3_cfg *cfg, lfs3_block_t block, lfs3_off_t off, void *buffer, lfs3_size_t size) { - #ifdef BENCH_YES_STACK BENCH_STACK_PAUSE(); - #endif - #ifdef BENCH_YES_HEAP BENCH_HEAP_PAUSE(); - #endif #ifdef BENCH_KIWIBD int err = lfs3_kiwibd_read(cfg, block, off, buffer, size); @@ -1743,23 +1680,15 @@ int bench_bd_read(const struct lfs3_cfg *cfg, lfs3_block_t block, int err = lfs3_emubd_read(cfg, block, off, buffer, size); #endif - #ifdef BENCH_YES_HEAP BENCH_HEAP_RESUME(); - #endif - #ifdef BENCH_YES_STACK BENCH_STACK_RESUME(); - #endif return err; } int bench_bd_prog(const struct lfs3_cfg *cfg, lfs3_block_t block, lfs3_off_t off, const void *buffer, lfs3_size_t size) { - #ifdef BENCH_YES_STACK BENCH_STACK_PAUSE(); - #endif - #ifdef BENCH_YES_HEAP BENCH_HEAP_PAUSE(); - #endif #ifdef BENCH_KIWIBD int err = lfs3_kiwibd_prog(cfg, block, off, buffer, size); @@ -1767,22 +1696,14 @@ int bench_bd_prog(const struct lfs3_cfg *cfg, lfs3_block_t block, int err = lfs3_emubd_prog(cfg, block, off, buffer, size); #endif - #ifdef BENCH_YES_HEAP BENCH_HEAP_RESUME(); - #endif - #ifdef BENCH_YES_STACK BENCH_STACK_RESUME(); - #endif return err; } int bench_bd_erase(const struct lfs3_cfg *cfg, lfs3_block_t block) { - #ifdef BENCH_YES_STACK BENCH_STACK_PAUSE(); - #endif - #ifdef BENCH_YES_HEAP BENCH_HEAP_PAUSE(); - #endif #ifdef BENCH_KIWIBD int err = lfs3_kiwibd_erase(cfg, block); @@ -1790,22 +1711,14 @@ int bench_bd_erase(const struct lfs3_cfg *cfg, lfs3_block_t block) { int err = lfs3_emubd_erase(cfg, block); #endif - #ifdef BENCH_YES_HEAP BENCH_HEAP_RESUME(); - #endif - #ifdef BENCH_YES_STACK BENCH_STACK_RESUME(); - #endif return err; } int bench_bd_sync(const struct lfs3_cfg *cfg) { - #ifdef BENCH_YES_STACK BENCH_STACK_PAUSE(); - #endif - #ifdef BENCH_YES_HEAP BENCH_HEAP_PAUSE(); - #endif #ifdef BENCH_KIWIBD int err = lfs3_kiwibd_sync(cfg); @@ -1813,12 +1726,8 @@ int bench_bd_sync(const struct lfs3_cfg *cfg) { int err = lfs3_emubd_sync(cfg); #endif - #ifdef BENCH_YES_HEAP BENCH_HEAP_RESUME(); - #endif - #ifdef BENCH_YES_STACK BENCH_STACK_RESUME(); - #endif return err; } @@ -1901,19 +1810,19 @@ void perm_run( perm_printid(suite, case_); printf("\n"); bench_reset(CFG); - #ifdef BENCH_YES_STACK + #ifdef BENCH_STACK bench_stack_enter(); #endif - #ifdef BENCH_YES_HEAP + #ifdef BENCH_HEAP bench_heap_enter(); #endif case_->run(CFG); - #ifdef BENCH_YES_HEAP + #ifdef BENCH_HEAP bench_heap_exit(); #endif - #ifdef BENCH_YES_STACK + #ifdef BENCH_STACK bench_stack_exit(); #endif printf("finished "); diff --git a/runners/bench_runner.h b/runners/bench_runner.h index 072bbb75..5abe9c0a 100644 --- a/runners/bench_runner.h +++ b/runners/bench_runner.h @@ -148,36 +148,44 @@ void bench_permutation(size_t i, uint32_t *buffer, size_t size); #define BENCH_FACTORIAL(x) bench_factorial(x) #define BENCH_PERMUTATION(i, buffer, size) bench_permutation(i, buffer, size) -#ifdef BENCH_YES_STACK +#ifdef BENCH_STACK // get the maximum/current stack usage for this run -size_t bench_stack(void); -__attribute__((noinline)) -size_t bench_stack_current(void); -__attribute__((noinline)) -void bench_stack_pause(void); +extern size_t bench_stack_watermark; +__attribute__((noinline)) size_t bench_stack_current(void); +__attribute__((noinline)) void bench_stack_pause(void); void bench_stack_resume(void); -#define BENCH_STACK() bench_stack() +#define BENCH_STACK_WATERMARK() bench_stack_watermark #define BENCH_STACK_CURRENT() bench_stack_current() #define BENCH_STACK_PAUSE() bench_stack_pause() #define BENCH_STACK_RESUME() bench_stack_resume() +#else +// stubs if not measuring stack +#define BENCH_STACK_PAUSE() +#define BENCH_STACK_RESUME() #endif -#ifdef BENCH_YES_HEAP +#ifdef BENCH_HEAP // get the maximum/current heap usage for this run -size_t bench_heap(void); -size_t bench_heap_current(void); +extern size_t bench_heap_watermark; +extern size_t bench_heap_current; 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_WATERMARK() bench_heap_watermark +#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) +#else +// stubs if not measuring heap +#define BENCH_HEAP_PAUSE() +#define BENCH_HEAP_RESUME() +#define BENCH_HEAP_INC(size) +#define BENCH_HEAP_DEC(size) #endif diff --git a/runners/test_runner.c b/runners/test_runner.c index 922c58a3..fa7c6a9f 100644 --- a/runners/test_runner.c +++ b/runners/test_runner.c @@ -633,98 +633,85 @@ void test_permutation(size_t i, uint32_t *buffer, size_t size) { // stack hooks -#ifdef TEST_YES_STACK -uint8_t *test_stack_watermark_enter; -uint8_t *test_stack_watermark_depth; +#ifdef TEST_STACK +uint8_t *test_stack_entrance = NULL; +size_t test_stack_watermark = 0; #endif // call me when entering/exiting a test! -#ifdef TEST_YES_STACK +#ifdef TEST_STACK __attribute__((noinline)) void test_stack_enter(void) { - test_stack_watermark_enter = __builtin_frame_address(0); - test_stack_watermark_depth = test_stack_watermark_enter; + test_stack_entrance = __builtin_frame_address(0); + test_stack_watermark = 0; } #endif -#ifdef TEST_YES_STACK +#ifdef TEST_STACK void test_stack_exit(void) { // do nothing } #endif // call me when entering/exiting a bd op! -#ifdef TEST_YES_STACK +#ifdef TEST_STACK __attribute__((noinline)) void test_stack_pause(void) { - uint8_t *watermark = __builtin_frame_address(0); + uint8_t *current = __builtin_frame_address(0); // keep track of the deepest stack - ssize_t depth = test_stack_watermark_depth - test_stack_watermark_enter; + ssize_t depth = current - test_stack_entrance; if (depth < 0) { depth = -depth; } - ssize_t depth_ = watermark - test_stack_watermark_enter; - if (depth_ < 0) { - depth_ = -depth_; - } - if (depth_ > depth) { - test_stack_watermark_depth = watermark; + + if ((size_t)depth > test_stack_watermark) { + test_stack_watermark = depth; } } #endif -#ifdef TEST_YES_STACK +#ifdef TEST_STACK void test_stack_resume(void) { // do nothing } #endif -// get the worst-case stack usage -#ifdef TEST_YES_STACK -size_t test_stack(void) { - ssize_t depth = test_stack_watermark_depth - test_stack_watermark_enter; - if (depth < 0) { - depth = -depth; - } - return depth; -} -#endif - -// get the current stack usage, note this is included in test_stack +// get the current stack usage // -// note note the noinline here is important for forcing a new stack frame -#ifdef TEST_YES_STACK +// note the noinline here is important for forcing a new stack frame +#ifdef TEST_STACK __attribute__((noinline)) size_t test_stack_current(void) { - uint8_t *watermark = __builtin_frame_address(0); + uint8_t *current = __builtin_frame_address(0); - ssize_t depth = watermark - test_stack_watermark_enter; + ssize_t depth = current - test_stack_entrance; if (depth < 0) { depth = -depth; } + return depth; } #endif // heap hooks -#ifdef TEST_YES_HEAP +#ifdef TEST_HEAP uint32_t test_heap_entered = 0; +size_t test_heap_current = 0; size_t test_heap_watermark = 0; -size_t test_heap_watermark_depth = 0; #endif // call me when entering/exiting a test! -#ifdef TEST_YES_HEAP +#ifdef TEST_HEAP void test_heap_enter(void) { test_heap_entered = 1; + test_heap_current = 0; test_heap_watermark = 0; - test_heap_watermark_depth = 0; } #endif -#ifdef TEST_YES_HEAP +#ifdef TEST_HEAP void test_heap_exit(void) { test_heap_entered = 0; if (test_heap_watermark != 0) { @@ -735,56 +722,42 @@ void test_heap_exit(void) { #endif // call me when entering/exiting a bd op! -#ifdef TEST_YES_HEAP +#ifdef TEST_HEAP void test_heap_pause(void) { // haha, a little 32-bit stack test_heap_entered <<= 1; } #endif -#ifdef TEST_YES_HEAP +#ifdef TEST_HEAP void test_heap_resume(void) { test_heap_entered >>= 1; } #endif -#ifdef TEST_YES_HEAP +#ifdef TEST_HEAP void test_heap_inc(size_t size) { if (test_heap_entered & 1) { - test_heap_watermark += size; + test_heap_current += size; // keep track of the deepest heap - if (test_heap_watermark > test_heap_watermark_depth) { - test_heap_watermark_depth = test_heap_watermark; + if (test_heap_current > test_heap_watermark) { + test_heap_watermark = test_heap_current; } } } #endif -#ifdef TEST_YES_HEAP +#ifdef TEST_HEAP void test_heap_dec(size_t size) { if (test_heap_entered & 1) { - assert(test_heap_watermark >= size); - test_heap_watermark -= size; + assert(test_heap_current >= size); + test_heap_current -= size; } } #endif -// get the worst-case heap usage -#ifdef TEST_YES_HEAP -size_t test_heap(void) { - return test_heap_watermark_depth; -} -#endif - -// get the current heap usage -#ifdef TEST_YES_HEAP -size_t test_heap_current(void) { - return test_heap_watermark; -} -#endif - // __real_malloc stubs, gcc's --wrap wraps these over the original symbols -#ifdef TEST_YES_HEAP +#ifdef TEST_HEAP extern void *__real_malloc(size_t size); extern void __real_free(void *p); extern void *__real_realloc(void *p, size_t size); @@ -793,7 +766,7 @@ extern void *__real_realloc(void *p, size_t size); // the actual malloc hooks // // these only work if wrapped via gcc's --wrap -#ifdef TEST_YES_HEAP +#ifdef TEST_HEAP void *__wrap_malloc(size_t size) { // prefix with allocation size, note we use uintptr_t to hopefully // keep things aligned @@ -802,13 +775,13 @@ void *__wrap_malloc(size_t size) { return NULL; } - test_heap_inc(size); + TEST_HEAP_INC(size); *p_ = size; return p_ + 1; } #endif -#ifdef TEST_YES_HEAP +#ifdef TEST_HEAP void __wrap_free(void *p) { if (!p) { return; @@ -816,13 +789,13 @@ void __wrap_free(void *p) { uintptr_t *p_ = ((uintptr_t*)p) - 1; size_t size = *p_; - test_heap_dec(size); + TEST_HEAP_DEC(size); __real_free(p_); } #endif -#ifdef TEST_YES_HEAP +#ifdef TEST_HEAP void *__wrap_realloc(void *p, size_t size) { uintptr_t *p_; size_t old; @@ -840,8 +813,8 @@ void *__wrap_realloc(void *p, size_t size) { return NULL; } - test_heap_dec(old); - test_heap_inc(size); + TEST_HEAP_DEC(old); + TEST_HEAP_INC(size); *p_ = size; return p_ + 1; } @@ -1551,12 +1524,8 @@ static void list_implicit_defines(void) { // test bd wrappers for heap/stack tracking int test_bd_read(const struct lfs3_cfg *cfg, lfs3_block_t block, lfs3_off_t off, void *buffer, lfs3_size_t size) { - #ifdef TEST_YES_STACK TEST_STACK_PAUSE(); - #endif - #ifdef TEST_YES_HEAP TEST_HEAP_PAUSE(); - #endif #ifdef TEST_KIWIBD int err = lfs3_kiwibd_read(cfg, block, off, buffer, size); @@ -1564,23 +1533,15 @@ int test_bd_read(const struct lfs3_cfg *cfg, lfs3_block_t block, int err = lfs3_emubd_read(cfg, block, off, buffer, size); #endif - #ifdef TEST_YES_HEAP TEST_HEAP_RESUME(); - #endif - #ifdef TEST_YES_STACK TEST_STACK_RESUME(); - #endif return err; } int test_bd_prog(const struct lfs3_cfg *cfg, lfs3_block_t block, lfs3_off_t off, const void *buffer, lfs3_size_t size) { - #ifdef TEST_YES_STACK TEST_STACK_PAUSE(); - #endif - #ifdef TEST_YES_HEAP TEST_HEAP_PAUSE(); - #endif #ifdef TEST_KIWIBD int err = lfs3_kiwibd_prog(cfg, block, off, buffer, size); @@ -1588,22 +1549,14 @@ int test_bd_prog(const struct lfs3_cfg *cfg, lfs3_block_t block, int err = lfs3_emubd_prog(cfg, block, off, buffer, size); #endif - #ifdef TEST_YES_HEAP TEST_HEAP_RESUME(); - #endif - #ifdef TEST_YES_STACK TEST_STACK_RESUME(); - #endif return err; } int test_bd_erase(const struct lfs3_cfg *cfg, lfs3_block_t block) { - #ifdef TEST_YES_STACK TEST_STACK_PAUSE(); - #endif - #ifdef TEST_YES_HEAP TEST_HEAP_PAUSE(); - #endif #ifdef TEST_KIWIBD int err = lfs3_kiwibd_erase(cfg, block); @@ -1611,22 +1564,14 @@ int test_bd_erase(const struct lfs3_cfg *cfg, lfs3_block_t block) { int err = lfs3_emubd_erase(cfg, block); #endif - #ifdef TEST_YES_HEAP TEST_HEAP_RESUME(); - #endif - #ifdef TEST_YES_STACK TEST_STACK_RESUME(); - #endif return err; } int test_bd_sync(const struct lfs3_cfg *cfg) { - #ifdef TEST_YES_STACK TEST_STACK_PAUSE(); - #endif - #ifdef TEST_YES_HEAP TEST_HEAP_PAUSE(); - #endif #ifdef TEST_KIWIBD int err = lfs3_kiwibd_sync(cfg); @@ -1634,12 +1579,8 @@ int test_bd_sync(const struct lfs3_cfg *cfg) { int err = lfs3_emubd_sync(cfg); #endif - #ifdef TEST_YES_HEAP TEST_HEAP_RESUME(); - #endif - #ifdef TEST_YES_STACK TEST_STACK_RESUME(); - #endif return err; } @@ -1703,19 +1644,19 @@ static void run_powerloss_none( printf("running "); perm_printid(suite, case_, NULL, 0); printf("\n"); - #ifdef TEST_YES_STACK + #ifdef TEST_STACK test_stack_enter(); #endif - #ifdef TEST_YES_HEAP + #ifdef TEST_HEAP test_heap_enter(); #endif case_->run(CFG); - #ifdef TEST_YES_HEAP + #ifdef TEST_HEAP test_heap_exit(); #endif - #ifdef TEST_YES_STACK + #ifdef TEST_STACK test_stack_exit(); #endif printf("finished "); @@ -1795,20 +1736,20 @@ static void run_powerloss_linear( while (true) { if (!setjmp(powerloss_jmp)) { - #ifdef TEST_YES_STACK + #ifdef TEST_STACK test_stack_enter(); #endif - #ifdef TEST_YES_HEAP + #ifdef TEST_HEAP test_heap_enter(); #endif // run the test case_->run(CFG); - #ifdef TEST_YES_HEAP + #ifdef TEST_HEAP test_heap_exit(); #endif - #ifdef TEST_YES_STACK + #ifdef TEST_STACK test_stack_exit(); #endif break; @@ -1891,20 +1832,20 @@ static void run_powerloss_log( while (true) { if (!setjmp(powerloss_jmp)) { - #ifdef TEST_YES_STACK + #ifdef TEST_STACK test_stack_enter(); #endif - #ifdef TEST_YES_HEAP + #ifdef TEST_HEAP test_heap_enter(); #endif // run the test case_->run(CFG); - #ifdef TEST_YES_HEAP + #ifdef TEST_HEAP test_heap_exit(); #endif - #ifdef TEST_YES_STACK + #ifdef TEST_STACK test_stack_exit(); #endif break; @@ -1987,20 +1928,20 @@ static void run_powerloss_cycles( while (true) { if (!setjmp(powerloss_jmp)) { - #ifdef TEST_YES_STACK + #ifdef TEST_STACK test_stack_enter(); #endif - #ifdef TEST_YES_HEAP + #ifdef TEST_HEAP test_heap_enter(); #endif // run the test case_->run(CFG); - #ifdef TEST_YES_HEAP + #ifdef TEST_HEAP test_heap_exit(); #endif - #ifdef TEST_YES_STACK + #ifdef TEST_STACK test_stack_exit(); #endif break; @@ -2100,20 +2041,20 @@ static void run_powerloss_exhaustive_layer( lfs3_emubd_setpowercycles(state.cfg, (depth > 0) ? 1 : 0); bdcfg->powerloss_data = &state; - #ifdef TEST_YES_STACK + #ifdef TEST_STACK test_stack_enter(); #endif - #ifdef TEST_YES_HEAP + #ifdef TEST_HEAP test_heap_enter(); #endif // run the tests case_->run(cfg); - #ifdef TEST_YES_HEAP + #ifdef TEST_HEAP test_heap_exit(); #endif - #ifdef TEST_YES_STACK + #ifdef TEST_STACK test_stack_exit(); #endif diff --git a/runners/test_runner.h b/runners/test_runner.h index 666241b9..90dbd7f0 100644 --- a/runners/test_runner.h +++ b/runners/test_runner.h @@ -138,36 +138,44 @@ void test_permutation(size_t i, uint32_t *buffer, size_t size); #define TEST_FACTORIAL(x) test_factorial(x) #define TEST_PERMUTATION(i, buffer, size) test_permutation(i, buffer, size) -#ifdef TEST_YES_STACK +#ifdef TEST_STACK // get the maximum/current stack usage for this run -size_t test_stack(void); -__attribute__((noinline)) -size_t test_stack_current(void); -__attribute__((noinline)) -void test_stack_pause(void); +extern size_t test_stack_watermark; +__attribute__((noinline)) size_t test_stack_current(void); +__attribute__((noinline)) void test_stack_pause(void); void test_stack_resume(void); -#define TEST_STACK() test_stack() +#define TEST_STACK_WATERMARK() test_stack_watermark #define TEST_STACK_CURRENT() test_stack_current() #define TEST_STACK_PAUSE() test_stack_pause() #define TEST_STACK_RESUME() test_stack_resume() +#else +// stubs if not measuring stack +#define TEST_STACK_PAUSE() +#define TEST_STACK_RESUME() #endif -#ifdef TEST_YES_HEAP +#ifdef TEST_HEAP // get the maximum/current heap usage for this run -size_t test_heap(void); -size_t test_heap_current(void); +extern size_t test_heap_watermark; +extern size_t test_heap_current; 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_WATERMARK() test_heap_watermark +#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) +#else +// stubs if not measuring heap +#define TEST_HEAP_PAUSE() +#define TEST_HEAP_RESUME() +#define TEST_HEAP_INC(size) +#define TEST_HEAP_DEC(size) #endif