From b336e92c66bb8ce72ad332897d96d0abecc0f328 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Fri, 5 Jan 2024 02:05:22 -0600 Subject: [PATCH] Exposed lfsr_file_flush, LFS_O_FLUSH, for manually flushing buffers A recent change, motivated by user feedback, was to delay write buffer flushes as much as possible. Before, littlefs would always flush the buffer during lfs_file_seek, but now, buffer flushes can be delayed all the way to lfsr_file_read, or even skipped entirely thanks to bypassing reads. This is all fine and dandy, except it's easy to imagine a use case where a user might really not want a _write_ error to pop out of a _read_ call. With this new behavior, avoiding this situation is impossible. So enters a function common to other filesystems: lfsr_file_flush. However it's value is quite a bit different here. Unlike flush in other filesystems, this flush does not necessarily make data accessible on disk. It only writes to the pending file snapshot, which is not accessible until lfsr_file_sync. This makes flush a function with a rather narrow scope in littlefs (pretty much just preventing write errors in read), but since we had already implemented this function for internal plumbing, it adds _very_ little cost. I'm more concerned about potential user confusion around sync vs flush. Curiously, exposing lfsr_file_flush actually _saved_ code size for some reason. Not sure what would make that happen: code stack before: 33544 3072 flush: 33536 (-0.0%) 3072 (+0.0%) flush+O_FLUSH: 33548 (+0.0%) 3072 (+0.0%) --- lfs.c | 19 ++-- lfs.h | 10 ++ tests/test_fmulti.toml | 206 +++++++++++++++++++++++++++++------------ 3 files changed, 169 insertions(+), 66 deletions(-) diff --git a/lfs.c b/lfs.c index fdbedd8a..47817247 100644 --- a/lfs.c +++ b/lfs.c @@ -9249,6 +9249,10 @@ static inline bool lfsr_o_isdesync(uint32_t flags) { return flags & LFS_O_DESYNC; } +static inline bool lfsr_o_isflush(uint32_t flags) { + return flags & LFS_O_FLUSH; +} + static inline bool lfsr_f_isunflushed(uint32_t flags) { return flags & LFS_F_UNFLUSHED; } @@ -10528,9 +10532,6 @@ static int lfsr_ftree_sync(lfs_t *lfs, lfsr_ftree_t *ftree, bool unflushed, // our high-level file operations -// needed in lfsr_file_read -static int lfsr_file_flush(lfs_t *lfs, lfsr_file_t *file); - lfs_ssize_t lfsr_file_read(lfs_t *lfs, lfsr_file_t *file, void *buffer, lfs_size_t size) { LFS_ASSERT(lfsr_o_isreadable(file->flags)); @@ -10749,11 +10750,11 @@ lfs_ssize_t lfsr_file_write(lfs_t *lfs, lfsr_file_t *file, unflushed_ = false; } - // sync if requested lfs_off_t size__ = lfs_max32(file->size, pos__); bool unsynced_ = true; - if (lfsr_o_issync(file->flags)) { - // syncing requires a flush for non-small files + // flush if requested + if (lfsr_o_isflush(file->flags) || lfsr_o_issync(file->flags)) { + // keep small files unflushed if (unflushed_ && !( size__ <= lfs->cfg->cache_size && size__ <= lfs->cfg->inline_size @@ -10766,7 +10767,9 @@ lfs_ssize_t lfsr_file_write(lfs_t *lfs, lfsr_file_t *file, } unflushed_ = false; } - + } + // sync if requested + if (lfsr_o_issync(file->flags)) { // sync err = lfsr_ftree_sync(lfs, &ftree_, unflushed_, buffer_pos_, buffer_, buffer_size_); @@ -10817,7 +10820,7 @@ failed:; return err; } -static int lfsr_file_flush(lfs_t *lfs, lfsr_file_t *file) { +int lfsr_file_flush(lfs_t *lfs, lfsr_file_t *file) { // do nothing if our file is readonly if (!lfsr_o_iswriteable(file->flags)) { LFS_ASSERT(!lfsr_f_isunflushed(file->flags) diff --git a/lfs.h b/lfs.h index eeec862b..cb7b0b92 100644 --- a/lfs.h +++ b/lfs.h @@ -164,6 +164,7 @@ enum lfs_open_flags { LFS_O_APPEND = 0x0800, // Move to end of file on every write LFS_O_SYNC = 0x1000, // Sync metadata on every write LFS_O_DESYNC = 0x2000, // Do not sync or recieve file updates + LFS_O_FLUSH = 0x4000, // Flush data on every write #endif // internally used flags @@ -817,6 +818,15 @@ int lfsr_file_sync(lfs_t *lfs, lfsr_file_t *file); // Returns a negative error code on failure. int lfsr_file_desync(lfs_t *lfs, lfsr_file_t *file); +// Flush any buffered data +// +// This does not update metadata and is called implicitly by lfsr_file_sync. +// Calling this explicitly may be useful for preventing write errors in +// read operations. +// +// Returns a negative error code on failure. +int lfsr_file_flush(lfs_t *lfs, lfsr_file_t *file); + // Read data from file // // Takes a buffer and size indicating where to store the read data. diff --git a/tests/test_fmulti.toml b/tests/test_fmulti.toml index 31aec911..cd180588 100644 --- a/tests/test_fmulti.toml +++ b/tests/test_fmulti.toml @@ -6,7 +6,6 @@ after = 'test_fwrite' [cases.test_fmulti_rrrr] defines.R = 4 defines.SIZE = [ - '0', 'CACHE_SIZE/2', '2*CACHE_SIZE', 'BLOCK_SIZE/2', @@ -14,8 +13,7 @@ defines.SIZE = [ '2*BLOCK_SIZE', '4*BLOCK_SIZE', ] -defines.CHUNK = [32, 8, 1] -if = 'CHUNK <= SIZE' +defines.CHUNK = '(SIZE+16-1) / 16' code = ''' lfs_t lfs; lfsr_format(&lfs, CFG) => 0; @@ -58,7 +56,6 @@ defines.R = 4 defines.SEED = 'range(10)' defines.N = 20 defines.SIZE = [ - '0', 'CACHE_SIZE/2', '2*CACHE_SIZE', 'BLOCK_SIZE/2', @@ -66,8 +63,7 @@ defines.SIZE = [ '2*BLOCK_SIZE', '4*BLOCK_SIZE', ] -defines.CHUNK = [32, 8, 1] -if = 'CHUNK <= SIZE' +defines.CHUNK = '(SIZE+16-1) / 16' code = ''' lfs_t lfs; lfsr_format(&lfs, CFG) => 0; @@ -118,8 +114,11 @@ defines.R = 4 # 1 => sync via lfsr_file_sync # 2 => sync via LFS_O_SYNC defines.SYNC = [0, 1, 2] +# 0 => no flush +# 1 => flush via lfsr_file_flush +# 2 => flush via LFS_O_FLUSH +defines.FLUSH = [0, 1, 2] defines.SIZE = [ - '0', 'CACHE_SIZE/2', '2*CACHE_SIZE', 'BLOCK_SIZE/2', @@ -127,8 +126,7 @@ defines.SIZE = [ '2*BLOCK_SIZE', '4*BLOCK_SIZE', ] -defines.CHUNK = [32, 8, 1] -if = 'CHUNK <= SIZE' +defines.CHUNK = '(SIZE+16-1) / 16' code = ''' lfs_t lfs; lfsr_format(&lfs, CFG) => 0; @@ -153,7 +151,9 @@ code = ''' lfsr_file_t writer; lfsr_file_t readers[R]; lfsr_file_open(&lfs, &writer, "jello", - LFS_O_WRONLY | ((SYNC == 2) ? LFS_O_SYNC : 0)) => 0; + LFS_O_WRONLY + | ((FLUSH == 2) ? LFS_O_FLUSH : 0) + | ((SYNC == 2) ? LFS_O_SYNC : 0)) => 0; for (lfs_size_t r = 0; r < R; r++) { lfsr_file_open(&lfs, &readers[r], "jello", LFS_O_RDONLY) => 0; } @@ -164,6 +164,9 @@ code = ''' } lfsr_file_write(&lfs, &writer, wbuf, CHUNK) => CHUNK; memcpy(&after[i], wbuf, CHUNK); + if (FLUSH == 1) { + lfsr_file_flush(&lfs, &writer) => 0; + } if (SYNC == 1) { lfsr_file_sync(&lfs, &writer) => 0; } @@ -199,10 +202,13 @@ defines.R = 4 # 1 => sync via lfsr_file_sync # 2 => sync via LFS_O_SYNC defines.SYNC = [0, 1, 2] +# 0 => no flush +# 1 => flush via lfsr_file_flush +# 2 => flush via LFS_O_FLUSH +defines.FLUSH = [0, 1, 2] defines.SEED = 'range(10)' defines.N = 20 defines.SIZE = [ - '0', 'CACHE_SIZE/2', '2*CACHE_SIZE', 'BLOCK_SIZE/2', @@ -210,8 +216,7 @@ defines.SIZE = [ '2*BLOCK_SIZE', '4*BLOCK_SIZE', ] -defines.CHUNK = [32, 8, 1] -if = 'CHUNK <= SIZE' +defines.CHUNK = '(SIZE+16-1) / 16' code = ''' lfs_t lfs; lfsr_format(&lfs, CFG) => 0; @@ -236,7 +241,9 @@ code = ''' lfsr_file_t writer; lfsr_file_t readers[R]; lfsr_file_open(&lfs, &writer, "jello", - LFS_O_WRONLY | ((SYNC == 2) ? LFS_O_SYNC : 0)) => 0; + LFS_O_WRONLY + | ((FLUSH == 2) ? LFS_O_FLUSH : 0) + | ((SYNC == 2) ? LFS_O_SYNC : 0)) => 0; for (lfs_size_t r = 0; r < R; r++) { lfsr_file_open(&lfs, &readers[r], "jello", LFS_O_RDONLY) => 0; } @@ -253,6 +260,9 @@ code = ''' } lfsr_file_write(&lfs, &writer, wbuf, size) => size; memcpy(&after[off], wbuf, size); + if (FLUSH == 1) { + lfsr_file_flush(&lfs, &writer) => 0; + } if (SYNC == 1) { lfsr_file_sync(&lfs, &writer) => 0; } @@ -295,8 +305,11 @@ defines.W = 4 # 1 => sync via lfsr_file_sync # 2 => sync via LFS_O_SYNC defines.SYNC = [0, 1, 2] +# 0 => no flush +# 1 => flush via lfsr_file_flush +# 2 => flush via LFS_O_FLUSH +defines.FLUSH = [0, 1, 2] defines.SIZE = [ - '0', 'CACHE_SIZE/2', '2*CACHE_SIZE', 'BLOCK_SIZE/2', @@ -304,8 +317,7 @@ defines.SIZE = [ '2*BLOCK_SIZE', '4*BLOCK_SIZE', ] -defines.CHUNK = [32, 8, 1] -if = 'CHUNK <= SIZE' +defines.CHUNK = '(SIZE+16-1) / 16' code = ''' lfs_t lfs; lfsr_format(&lfs, CFG) => 0; @@ -330,7 +342,9 @@ code = ''' lfsr_file_t writers[W]; for (lfs_size_t w = 0; w < W; w++) { lfsr_file_open(&lfs, &writers[w], "jello", - LFS_O_WRONLY | ((SYNC == 2) ? LFS_O_SYNC : 0)) => 0; + LFS_O_WRONLY + | ((FLUSH == 2) ? LFS_O_FLUSH : 0) + | ((SYNC == 2) ? LFS_O_SYNC : 0)) => 0; } for (lfs_size_t i = 0; i < SIZE; i += CHUNK) { for (lfs_size_t w = 0; w < W; w++) { @@ -344,6 +358,9 @@ code = ''' memcpy(&after[i], wbuf, CHUNK); } } else { + if (FLUSH == 1) { + lfsr_file_flush(&lfs, &writers[w]) => 0; + } if (SYNC == 1) { lfsr_file_sync(&lfs, &writers[w]) => 0; } @@ -371,10 +388,13 @@ defines.W = 4 # 1 => sync via lfsr_file_sync # 2 => sync via LFS_O_SYNC defines.SYNC = [0, 1, 2] +# 0 => no flush +# 1 => flush via lfsr_file_flush +# 2 => flush via LFS_O_FLUSH +defines.FLUSH = [0, 1, 2] defines.SEED = 'range(10)' defines.N = 20 defines.SIZE = [ - '0', 'CACHE_SIZE/2', '2*CACHE_SIZE', 'BLOCK_SIZE/2', @@ -382,8 +402,7 @@ defines.SIZE = [ '2*BLOCK_SIZE', '4*BLOCK_SIZE', ] -defines.CHUNK = 32 -if = 'CHUNK <= SIZE' +defines.CHUNK = '(SIZE+16-1) / 16' code = ''' lfs_t lfs; lfsr_format(&lfs, CFG) => 0; @@ -408,7 +427,9 @@ code = ''' lfsr_file_t writers[W]; for (lfs_size_t w = 0; w < W; w++) { lfsr_file_open(&lfs, &writers[w], "jello", - LFS_O_WRONLY | ((SYNC == 2) ? LFS_O_SYNC : 0)) => 0; + LFS_O_WRONLY + | ((FLUSH == 2) ? LFS_O_FLUSH : 0) + | ((SYNC == 2) ? LFS_O_SYNC : 0)) => 0; } for (lfs_size_t i = 0; i < SIZE; i += CHUNK) { for (lfs_size_t w = 0; w < W; w++) { @@ -428,6 +449,9 @@ code = ''' memcpy(&after[off], wbuf, size); } } else { + if (FLUSH == 1) { + lfsr_file_flush(&lfs, &writers[w]) => 0; + } if (SYNC == 1) { lfsr_file_sync(&lfs, &writers[w]) => 0; } @@ -457,8 +481,11 @@ defines.R = 4 # 1 => sync via lfsr_file_sync # 2 => sync via LFS_O_SYNC defines.SYNC = [0, 1, 2] +# 0 => no flush +# 1 => flush via lfsr_file_flush +# 2 => flush via LFS_O_FLUSH +defines.FLUSH = [0, 1, 2] defines.SIZE = [ - '0', 'CACHE_SIZE/2', '2*CACHE_SIZE', 'BLOCK_SIZE/2', @@ -466,8 +493,7 @@ defines.SIZE = [ '2*BLOCK_SIZE', '4*BLOCK_SIZE', ] -defines.CHUNK = [32, 8, 1] -if = 'CHUNK <= SIZE' +defines.CHUNK = '(SIZE+16-1) / 16' code = ''' lfs_t lfs; lfsr_format(&lfs, CFG) => 0; @@ -493,7 +519,9 @@ code = ''' lfsr_file_t readers[R]; for (lfs_size_t w = 0; w < W; w++) { lfsr_file_open(&lfs, &writers[w], "jello", - LFS_O_WRONLY | ((SYNC == 2) ? LFS_O_SYNC : 0)) => 0; + LFS_O_WRONLY + | ((FLUSH == 2) ? LFS_O_FLUSH : 0) + | ((SYNC == 2) ? LFS_O_SYNC : 0)) => 0; } for (lfs_size_t r = 0; r < R; r++) { lfsr_file_open(&lfs, &readers[r], "jello", LFS_O_RDONLY) => 0; @@ -510,6 +538,9 @@ code = ''' memcpy(&after[i], wbuf, CHUNK); } } else { + if (FLUSH == 1) { + lfsr_file_flush(&lfs, &writers[w]) => 0; + } if (SYNC == 1) { lfsr_file_sync(&lfs, &writers[w]) => 0; } @@ -550,10 +581,13 @@ defines.R = 4 # 1 => sync via lfsr_file_sync # 2 => sync via LFS_O_SYNC defines.SYNC = [0, 1, 2] +# 0 => no flush +# 1 => flush via lfsr_file_flush +# 2 => flush via LFS_O_FLUSH +defines.FLUSH = [0, 1, 2] defines.SEED = 'range(10)' defines.N = 20 defines.SIZE = [ - '0', 'CACHE_SIZE/2', '2*CACHE_SIZE', 'BLOCK_SIZE/2', @@ -561,8 +595,7 @@ defines.SIZE = [ '2*BLOCK_SIZE', '4*BLOCK_SIZE', ] -defines.CHUNK = 32 -if = 'CHUNK <= SIZE' +defines.CHUNK = '(SIZE+16-1) / 16' code = ''' lfs_t lfs; lfsr_format(&lfs, CFG) => 0; @@ -588,7 +621,9 @@ code = ''' lfsr_file_t readers[R]; for (lfs_size_t w = 0; w < W; w++) { lfsr_file_open(&lfs, &writers[w], "jello", - LFS_O_WRONLY | ((SYNC == 2) ? LFS_O_SYNC : 0)) => 0; + LFS_O_WRONLY + | ((FLUSH == 2) ? LFS_O_FLUSH : 0) + | ((SYNC == 2) ? LFS_O_SYNC : 0)) => 0; } for (lfs_size_t r = 0; r < R; r++) { lfsr_file_open(&lfs, &readers[r], "jello", LFS_O_RDONLY) => 0; @@ -611,6 +646,9 @@ code = ''' memcpy(&after[off], wbuf, size); } } else { + if (FLUSH == 1) { + lfsr_file_flush(&lfs, &writers[w]) => 0; + } if (SYNC == 1) { lfsr_file_sync(&lfs, &writers[w]) => 0; } @@ -657,8 +695,11 @@ defines.RW = 4 # 1 => sync via lfsr_file_sync # 2 => sync via LFS_O_SYNC defines.SYNC = [0, 1, 2] +# 0 => no flush +# 1 => flush via lfsr_file_flush +# 2 => flush via LFS_O_FLUSH +defines.FLUSH = [0, 1, 2] defines.SIZE = [ - '0', 'CACHE_SIZE/2', '2*CACHE_SIZE', 'BLOCK_SIZE/2', @@ -666,8 +707,7 @@ defines.SIZE = [ '2*BLOCK_SIZE', '4*BLOCK_SIZE', ] -defines.CHUNK = [32, 8, 1] -if = 'CHUNK <= SIZE' +defines.CHUNK = '(SIZE+16-1) / 16' code = ''' lfs_t lfs; lfsr_format(&lfs, CFG) => 0; @@ -696,7 +736,9 @@ code = ''' lfsr_file_t rdwrs[RW]; for (lfs_size_t rw = 0; rw < RW; rw++) { lfsr_file_open(&lfs, &rdwrs[rw], "jello", - LFS_O_RDWR | ((SYNC == 2) ? LFS_O_SYNC : 0)) => 0; + LFS_O_RDWR + | ((FLUSH == 2) ? LFS_O_FLUSH : 0) + | ((SYNC == 2) ? LFS_O_SYNC : 0)) => 0; } for (lfs_size_t i = 0; i < SIZE; i += CHUNK) { for (lfs_size_t rw = 0; rw < RW; rw++) { @@ -712,6 +754,9 @@ code = ''' memcpy(&after[i], wbuf, CHUNK); } } else { + if (FLUSH == 1) { + lfsr_file_flush(&lfs, &rdwrs[rw]) => 0; + } if (SYNC == 1) { lfsr_file_sync(&lfs, &rdwrs[rw]) => 0; } @@ -749,10 +794,13 @@ defines.RW = 4 # 1 => sync via lfsr_file_sync # 2 => sync via LFS_O_SYNC defines.SYNC = [0, 1, 2] +# 0 => no flush +# 1 => flush via lfsr_file_flush +# 2 => flush via LFS_O_FLUSH +defines.FLUSH = [0, 1, 2] defines.SEED = 'range(10)' defines.N = 20 defines.SIZE = [ - '0', 'CACHE_SIZE/2', '2*CACHE_SIZE', 'BLOCK_SIZE/2', @@ -760,8 +808,7 @@ defines.SIZE = [ '2*BLOCK_SIZE', '4*BLOCK_SIZE', ] -defines.CHUNK = 32 -if = 'CHUNK <= SIZE' +defines.CHUNK = '(SIZE+16-1) / 16' code = ''' lfs_t lfs; lfsr_format(&lfs, CFG) => 0; @@ -790,7 +837,9 @@ code = ''' lfsr_file_t rdwrs[RW]; for (lfs_size_t rw = 0; rw < RW; rw++) { lfsr_file_open(&lfs, &rdwrs[rw], "jello", - LFS_O_RDWR | ((SYNC == 2) ? LFS_O_SYNC : 0)) => 0; + LFS_O_RDWR + | ((FLUSH == 2) ? LFS_O_FLUSH : 0) + | ((SYNC == 2) ? LFS_O_SYNC : 0)) => 0; } for (lfs_size_t i = 0; i < SIZE; i += CHUNK) { for (lfs_size_t rw = 0; rw < RW; rw++) { @@ -811,6 +860,9 @@ code = ''' memcpy(&after[off], wbuf, size); } } else { + if (FLUSH == 1) { + lfsr_file_flush(&lfs, &rdwrs[rw]) => 0; + } if (SYNC == 1) { lfsr_file_sync(&lfs, &rdwrs[rw]) => 0; } @@ -857,8 +909,11 @@ defines.R = 4 # 1 => sync via lfsr_file_sync # 2 => sync via LFS_O_SYNC defines.SYNC = [0, 1, 2] +# 0 => no flush +# 1 => flush via lfsr_file_flush +# 2 => flush via LFS_O_FLUSH +defines.FLUSH = [0, 1, 2] defines.SIZE = [ - '0', 'CACHE_SIZE/2', '2*CACHE_SIZE', 'BLOCK_SIZE/2', @@ -866,8 +921,7 @@ defines.SIZE = [ '2*BLOCK_SIZE', '4*BLOCK_SIZE', ] -defines.CHUNK = [32, 8, 1] -if = 'CHUNK <= SIZE' +defines.CHUNK = '(SIZE+16-1) / 16' code = ''' lfs_t lfs; lfsr_format(&lfs, CFG) => 0; @@ -894,6 +948,7 @@ code = ''' lfsr_file_open(&lfs, &writer, "jello", LFS_O_WRONLY | LFS_O_DESYNC + | ((FLUSH == 2) ? LFS_O_FLUSH : 0) | ((SYNC == 2) ? LFS_O_SYNC : 0)) => 0; for (lfs_size_t r = 0; r < R; r++) { lfsr_file_open(&lfs, &readers[r], "jello", LFS_O_RDONLY) => 0; @@ -905,6 +960,9 @@ code = ''' } lfsr_file_write(&lfs, &writer, wbuf, CHUNK) => CHUNK; memcpy(&after[i], wbuf, CHUNK); + if (FLUSH == 1) { + lfsr_file_flush(&lfs, &writer) => 0; + } if (SYNC == 1) { lfsr_file_sync(&lfs, &writer) => 0; } @@ -944,10 +1002,13 @@ defines.R = 4 # 1 => sync via lfsr_file_sync # 2 => sync via LFS_O_SYNC defines.SYNC = [0, 1, 2] +# 0 => no flush +# 1 => flush via lfsr_file_flush +# 2 => flush via LFS_O_FLUSH +defines.FLUSH = [0, 1, 2] defines.SEED = 'range(10)' defines.N = 20 defines.SIZE = [ - '0', 'CACHE_SIZE/2', '2*CACHE_SIZE', 'BLOCK_SIZE/2', @@ -955,8 +1016,7 @@ defines.SIZE = [ '2*BLOCK_SIZE', '4*BLOCK_SIZE', ] -defines.CHUNK = [32, 8, 1] -if = 'CHUNK <= SIZE' +defines.CHUNK = '(SIZE+16-1) / 16' code = ''' lfs_t lfs; lfsr_format(&lfs, CFG) => 0; @@ -983,6 +1043,7 @@ code = ''' lfsr_file_open(&lfs, &writer, "jello", LFS_O_WRONLY | LFS_O_DESYNC + | ((FLUSH == 2) ? LFS_O_FLUSH : 0) | ((SYNC == 2) ? LFS_O_SYNC : 0)) => 0; for (lfs_size_t r = 0; r < R; r++) { lfsr_file_open(&lfs, &readers[r], "jello", LFS_O_RDONLY) => 0; @@ -1000,6 +1061,9 @@ code = ''' } lfsr_file_write(&lfs, &writer, wbuf, size) => size; memcpy(&after[off], wbuf, size); + if (FLUSH == 1) { + lfsr_file_flush(&lfs, &writer) => 0; + } if (SYNC == 1) { lfsr_file_sync(&lfs, &writer) => 0; } @@ -1046,8 +1110,11 @@ defines.R = 4 # 1 => sync via lfsr_file_sync # 2 => sync via LFS_O_SYNC defines.SYNC = [0, 1, 2] +# 0 => no flush +# 1 => flush via lfsr_file_flush +# 2 => flush via LFS_O_FLUSH +defines.FLUSH = [0, 1, 2] defines.SIZE = [ - '0', 'CACHE_SIZE/2', '2*CACHE_SIZE', 'BLOCK_SIZE/2', @@ -1055,8 +1122,7 @@ defines.SIZE = [ '2*BLOCK_SIZE', '4*BLOCK_SIZE', ] -defines.CHUNK = [32, 8, 1] -if = 'CHUNK <= SIZE' +defines.CHUNK = '(SIZE+16-1) / 16' code = ''' lfs_t lfs; lfsr_format(&lfs, CFG) => 0; @@ -1081,7 +1147,9 @@ code = ''' lfsr_file_t writer; lfsr_file_t readers[R]; lfsr_file_open(&lfs, &writer, "jello", - LFS_O_WRONLY | ((SYNC == 2) ? LFS_O_SYNC : 0)) => 0; + LFS_O_WRONLY + | ((FLUSH == 2) ? LFS_O_FLUSH : 0) + | ((SYNC == 2) ? LFS_O_SYNC : 0)) => 0; for (lfs_size_t r = 0; r < R; r++) { lfsr_file_open(&lfs, &readers[r], "jello", LFS_O_RDONLY | LFS_O_DESYNC) => 0; @@ -1093,6 +1161,9 @@ code = ''' } lfsr_file_write(&lfs, &writer, wbuf, CHUNK) => CHUNK; memcpy(&after[i], wbuf, CHUNK); + if (FLUSH == 1) { + lfsr_file_flush(&lfs, &writer) => 0; + } if (SYNC == 1) { lfsr_file_sync(&lfs, &writer) => 0; } @@ -1124,10 +1195,13 @@ defines.R = 4 # 1 => sync via lfsr_file_sync # 2 => sync via LFS_O_SYNC defines.SYNC = [0, 1, 2] +# 0 => no flush +# 1 => flush via lfsr_file_flush +# 2 => flush via LFS_O_FLUSH +defines.FLUSH = [0, 1, 2] defines.SEED = 'range(10)' defines.N = 20 defines.SIZE = [ - '0', 'CACHE_SIZE/2', '2*CACHE_SIZE', 'BLOCK_SIZE/2', @@ -1135,8 +1209,7 @@ defines.SIZE = [ '2*BLOCK_SIZE', '4*BLOCK_SIZE', ] -defines.CHUNK = [32, 8, 1] -if = 'CHUNK <= SIZE' +defines.CHUNK = '(SIZE+16-1) / 16' code = ''' lfs_t lfs; lfsr_format(&lfs, CFG) => 0; @@ -1161,7 +1234,9 @@ code = ''' lfsr_file_t writer; lfsr_file_t readers[R]; lfsr_file_open(&lfs, &writer, "jello", - LFS_O_WRONLY | ((SYNC == 2) ? LFS_O_SYNC : 0)) => 0; + LFS_O_WRONLY + | ((FLUSH == 2) ? LFS_O_FLUSH : 0) + | ((SYNC == 2) ? LFS_O_SYNC : 0)) => 0; for (lfs_size_t r = 0; r < R; r++) { lfsr_file_open(&lfs, &readers[r], "jello", LFS_O_RDONLY | LFS_O_DESYNC) => 0; @@ -1179,6 +1254,9 @@ code = ''' } lfsr_file_write(&lfs, &writer, wbuf, size) => size; memcpy(&after[off], wbuf, size); + if (FLUSH == 1) { + lfsr_file_flush(&lfs, &writer) => 0; + } if (SYNC == 1) { lfsr_file_sync(&lfs, &writer) => 0; } @@ -1217,8 +1295,11 @@ defines.RW = 4 # 1 => sync via lfsr_file_sync # 2 => sync via LFS_O_SYNC defines.SYNC = [0, 1, 2] +# 0 => no flush +# 1 => flush via lfsr_file_flush +# 2 => flush via LFS_O_FLUSH +defines.FLUSH = [0, 1, 2] defines.SIZE = [ - '0', 'CACHE_SIZE/2', '2*CACHE_SIZE', 'BLOCK_SIZE/2', @@ -1226,8 +1307,7 @@ defines.SIZE = [ '2*BLOCK_SIZE', '4*BLOCK_SIZE', ] -defines.CHUNK = [32, 8, 1] -if = 'CHUNK <= SIZE' +defines.CHUNK = '(SIZE+16-1) / 16' code = ''' lfs_t lfs; lfsr_format(&lfs, CFG) => 0; @@ -1258,6 +1338,7 @@ code = ''' lfsr_file_open(&lfs, &rdwrs[rw], "jello", LFS_O_RDWR | LFS_O_DESYNC + | ((FLUSH == 2) ? LFS_O_FLUSH : 0) | ((SYNC == 2) ? LFS_O_SYNC : 0)) => 0; } for (lfs_size_t i = 0; i < SIZE; i += CHUNK) { @@ -1274,6 +1355,9 @@ code = ''' memcpy(&after[i], wbuf, CHUNK); } } else { + if (FLUSH == 1) { + lfsr_file_flush(&lfs, &rdwrs[rw]) => 0; + } if (SYNC == 1) { lfsr_file_sync(&lfs, &rdwrs[rw]) => 0; } @@ -1319,10 +1403,13 @@ defines.RW = 4 # 1 => sync via lfsr_file_sync # 2 => sync via LFS_O_SYNC defines.SYNC = [0, 1, 2] +# 0 => no flush +# 1 => flush via lfsr_file_flush +# 2 => flush via LFS_O_FLUSH +defines.FLUSH = [0, 1, 2] defines.SEED = 'range(10)' defines.N = 20 defines.SIZE = [ - '0', 'CACHE_SIZE/2', '2*CACHE_SIZE', 'BLOCK_SIZE/2', @@ -1330,8 +1417,7 @@ defines.SIZE = [ '2*BLOCK_SIZE', '4*BLOCK_SIZE', ] -defines.CHUNK = 32 -if = 'CHUNK <= SIZE' +defines.CHUNK = '(SIZE+16-1) / 16' code = ''' lfs_t lfs; lfsr_format(&lfs, CFG) => 0; @@ -1362,6 +1448,7 @@ code = ''' lfsr_file_open(&lfs, &rdwrs[rw], "jello", LFS_O_RDWR | LFS_O_DESYNC + | ((FLUSH == 2) ? LFS_O_FLUSH : 0) | ((SYNC == 2) ? LFS_O_SYNC : 0)) => 0; } for (lfs_size_t i = 0; i < SIZE; i += CHUNK) { @@ -1383,6 +1470,9 @@ code = ''' memcpy(&after[off], wbuf, size); } } else { + if (FLUSH == 1) { + lfsr_file_flush(&lfs, &rdwrs[rw]) => 0; + } if (SYNC == 1) { lfsr_file_sync(&lfs, &rdwrs[rw]) => 0; }