Fixed another subtle corner cases with noop sync broadcasting
This is an extension of the noop-sync after unrelated write-sync after
desync corner case:
op a state b state
in-sync in-sync
desync(b) in-sync desync
write(a) unsync desync
sync(a) in-sync' desync
sync(b) in-sync in-sync
But instead of explicitly calling lfsr_file_sync, what if you implicitly
triggered sync through something like a write on a file with the
LFS_O_SYNC flag, but not a normal write, a noop write, write(0)?
If the definition of LFS_O_SYNC is taken literally as "lfsr_file_write
and friends implicitly call lfsr_file_sync after every call", then this
should behave just as if lfsr_file_sync had been called, and
unconditionally broadcast the sync. Since this is the simplest
interpretation, I think this is what we should implement.
Added tests, and adopted this behavior. Fortunately this just involves
some small gotos (https://xkcd.com/292):
code stack
before: 33020 2976
after: 33026 (+0.0%) 2976 (+0.0%)
This commit is contained in:
@@ -10520,8 +10520,9 @@ lfs_ssize_t lfsr_file_write(lfs_t *lfs, lfsr_file_t *file,
|
||||
// underlying file, this means no updating file pos or file size
|
||||
//
|
||||
// since we need to test for this, just return early
|
||||
lfs_size_t written = 0;
|
||||
if (size == 0) {
|
||||
return 0;
|
||||
goto noop;
|
||||
}
|
||||
|
||||
// checkpoint the allocator
|
||||
@@ -10548,7 +10549,6 @@ lfs_ssize_t lfsr_file_write(lfs_t *lfs, lfsr_file_t *file,
|
||||
}
|
||||
|
||||
const uint8_t *buffer_ = buffer;
|
||||
lfs_size_t written = 0;
|
||||
while (size > 0) {
|
||||
// bypass buffer?
|
||||
//
|
||||
@@ -10631,6 +10631,7 @@ lfs_ssize_t lfsr_file_write(lfs_t *lfs, lfsr_file_t *file,
|
||||
// update our pos
|
||||
file->pos = pos;
|
||||
|
||||
noop:;
|
||||
// flush if requested
|
||||
//
|
||||
// this seems unreachable, but it's possible if we transition from
|
||||
@@ -10873,7 +10874,7 @@ int lfsr_file_truncate(lfs_t *lfs, lfsr_file_t *file, lfs_off_t size_) {
|
||||
// do nothing if our size does not change
|
||||
lfs_off_t size = lfsr_file_size_(file);
|
||||
if (lfsr_file_size_(file) == size_) {
|
||||
return 0;
|
||||
goto noop;
|
||||
}
|
||||
|
||||
// checkpoint the allocator
|
||||
@@ -10942,6 +10943,7 @@ int lfsr_file_truncate(lfs_t *lfs, lfsr_file_t *file, lfs_off_t size_) {
|
||||
// mark as unsynced
|
||||
file->flags |= LFS_F_UNSYNCED;
|
||||
|
||||
noop:;
|
||||
// flush if requested
|
||||
//
|
||||
// this seems unreachable, but it's possible if we transition from
|
||||
@@ -10978,7 +10980,7 @@ int lfsr_file_fruncate(lfs_t *lfs, lfsr_file_t *file, lfs_off_t size_) {
|
||||
// do nothing if our size does not change
|
||||
lfs_off_t size = lfsr_file_size_(file);
|
||||
if (size == size_) {
|
||||
return 0;
|
||||
goto noop;
|
||||
}
|
||||
|
||||
// checkpoint the allocator
|
||||
@@ -11075,6 +11077,7 @@ int lfsr_file_fruncate(lfs_t *lfs, lfsr_file_t *file, lfs_off_t size_) {
|
||||
// mark as unsynced
|
||||
file->flags |= LFS_F_UNSYNCED;
|
||||
|
||||
noop:;
|
||||
// flush if requested
|
||||
//
|
||||
// this seems unreachable, but it's possible if we transition from
|
||||
|
||||
Reference in New Issue
Block a user