Changed lfsr_rbyd_append back to using tag bits for diverged/found state
With the lower 4 tag bits getting all sorts of in-device-only uses, reusing these bits to maintain diverged state during lfsr_rbyd_append is less of a special case. And anything that replaces the awkward 5-state, idiosyncratic diverged state machine is a win in my opinion.
This commit is contained in:
@@ -545,20 +545,39 @@ static inline bool lfsr_tag_isalt(lfsr_tag_t tag) {
|
|||||||
return tag & 0x8;
|
return tag & 0x8;
|
||||||
}
|
}
|
||||||
|
|
||||||
//static inline bool lfsr_tag_isfound(lfsr_tag_t tag) {
|
|
||||||
// // note that this is only for driver bookkeeping and never
|
|
||||||
// // exists on disk
|
|
||||||
// return tag & 0x1;
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//static inline lfsr_tag_t lfsr_tag_setfound(lfsr_tag_t tag) {
|
|
||||||
// return tag | 0x1;
|
|
||||||
//}
|
|
||||||
|
|
||||||
static inline lfsr_tag_t lfsr_tag_next(lfsr_tag_t tag) {
|
static inline lfsr_tag_t lfsr_tag_next(lfsr_tag_t tag) {
|
||||||
return tag + 0x10;
|
return tag + 0x10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// lfsr_rbyd_append specific flags
|
||||||
|
static inline bool lfsr_tag_isfound(lfsr_tag_t tag) {
|
||||||
|
return tag & 0x1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline lfsr_tag_t lfsr_tag_setfound(lfsr_tag_t tag) {
|
||||||
|
return tag | 0x1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool lfsr_tag_isupper(lfsr_tag_t tag) {
|
||||||
|
return tag & 0x4;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool lfsr_tag_islower(lfsr_tag_t tag) {
|
||||||
|
return !lfsr_tag_isupper(tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline lfsr_tag_t lfsr_tag_setupper(lfsr_tag_t tag) {
|
||||||
|
return tag | 0x4;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool lfsr_tag_hasdiverged(lfsr_tag_t tag) {
|
||||||
|
return tag & 0x8;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline lfsr_tag_t lfsr_tag_setdiverged(lfsr_tag_t tag) {
|
||||||
|
return tag | 0x8;
|
||||||
|
}
|
||||||
|
|
||||||
// alt operations
|
// alt operations
|
||||||
static inline bool lfsr_tag_isblack(lfsr_tag_t tag) {
|
static inline bool lfsr_tag_isblack(lfsr_tag_t tag) {
|
||||||
return !(tag & 0x2);
|
return !(tag & 0x2);
|
||||||
@@ -1990,6 +2009,9 @@ static int lfsr_rbyd_append(lfs_t *lfs, lfsr_rbyd_t *rbyd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// figure out the range of tags we're operating on
|
// figure out the range of tags we're operating on
|
||||||
|
//
|
||||||
|
// several lower bits are reserved, so we repurpose these
|
||||||
|
// to keep track of some append state
|
||||||
lfs_ssize_t id_;
|
lfs_ssize_t id_;
|
||||||
lfs_ssize_t other_id_;
|
lfs_ssize_t other_id_;
|
||||||
lfsr_tag_t tag_;
|
lfsr_tag_t tag_;
|
||||||
@@ -2004,7 +2026,7 @@ static int lfsr_rbyd_append(lfs_t *lfs, lfsr_rbyd_t *rbyd,
|
|||||||
other_id_ = id + 1;
|
other_id_ = id + 1;
|
||||||
// also note these tags MUST NOT be zero, due to unreachable tag holes
|
// also note these tags MUST NOT be zero, due to unreachable tag holes
|
||||||
tag_ = 0x10;
|
tag_ = 0x10;
|
||||||
other_tag_ = 0x10;
|
other_tag_ = lfsr_tag_setupper(0x10);
|
||||||
} else if (lfsr_tag_ismk(tag) && delta < 0) {
|
} else if (lfsr_tag_ismk(tag) && delta < 0) {
|
||||||
LFS_ASSERT(id < rbyd->weight);
|
LFS_ASSERT(id < rbyd->weight);
|
||||||
|
|
||||||
@@ -2015,21 +2037,21 @@ static int lfsr_rbyd_append(lfs_t *lfs, lfsr_rbyd_t *rbyd,
|
|||||||
other_id_ = id;
|
other_id_ = id;
|
||||||
// also note these tags MUST NOT be zero, due to unreachable tag holes
|
// also note these tags MUST NOT be zero, due to unreachable tag holes
|
||||||
tag_ = 0x10;
|
tag_ = 0x10;
|
||||||
other_tag_ = 0x10;
|
other_tag_ = lfsr_tag_setupper(0x10);
|
||||||
} else if (lfsr_tag_isrm(tag)) {
|
} else if (lfsr_tag_isrm(tag)) {
|
||||||
LFS_ASSERT(id < rbyd->weight);
|
LFS_ASSERT(id < rbyd->weight);
|
||||||
|
|
||||||
id_ = id - lfs_smax32(-delta, 0);
|
id_ = id - lfs_smax32(-delta, 0);
|
||||||
other_id_ = id;
|
other_id_ = id;
|
||||||
tag_ = lfsr_tag_key(tag);
|
tag_ = lfsr_tag_key(tag);
|
||||||
other_tag_ = lfsr_tag_key(tag) + 0x10;
|
other_tag_ = lfsr_tag_setupper(lfsr_tag_key(tag) + 0x10);
|
||||||
} else {
|
} else {
|
||||||
LFS_ASSERT(id < rbyd->weight);
|
LFS_ASSERT(id < rbyd->weight);
|
||||||
|
|
||||||
id_ = id - lfs_smax32(-delta, 0);
|
id_ = id - lfs_smax32(-delta, 0);
|
||||||
other_id_ = id;
|
other_id_ = id;
|
||||||
tag_ = lfsr_tag_key(tag);
|
tag_ = lfsr_tag_key(tag);
|
||||||
other_tag_ = lfsr_tag_key(tag);
|
other_tag_ = lfsr_tag_setupper(lfsr_tag_key(tag));
|
||||||
}
|
}
|
||||||
|
|
||||||
// keep track of bounds as we descend down the tree
|
// keep track of bounds as we descend down the tree
|
||||||
@@ -2050,14 +2072,6 @@ static int lfsr_rbyd_append(lfs_t *lfs, lfsr_rbyd_t *rbyd,
|
|||||||
//
|
//
|
||||||
// note we can't just perform two searches sequentially, or else our tree
|
// note we can't just perform two searches sequentially, or else our tree
|
||||||
// will end up very unbalanced.
|
// will end up very unbalanced.
|
||||||
//
|
|
||||||
// we end up going through several states when diverging:
|
|
||||||
// diverged=0 => not diverged
|
|
||||||
// diverged=4 => diverged, on lower path
|
|
||||||
// diverged=5 => diverged, on upper path
|
|
||||||
// diverged=2 => diverged, found one tag, on lower path
|
|
||||||
// diverged=3 => diverged, found one tag, on upper path
|
|
||||||
uint8_t diverged = 0;
|
|
||||||
lfs_off_t other_branch = 0;
|
lfs_off_t other_branch = 0;
|
||||||
lfs_ssize_t other_lower_id = 0;
|
lfs_ssize_t other_lower_id = 0;
|
||||||
lfs_ssize_t other_upper_id = 0;
|
lfs_ssize_t other_upper_id = 0;
|
||||||
@@ -2104,7 +2118,7 @@ static int lfsr_rbyd_append(lfs_t *lfs, lfsr_rbyd_t *rbyd,
|
|||||||
lfs_off_t branch_ = branch + d;
|
lfs_off_t branch_ = branch + d;
|
||||||
|
|
||||||
// do bounds want to take different paths? begin cutting
|
// do bounds want to take different paths? begin cutting
|
||||||
if (!diverged
|
if (!lfsr_tag_hasdiverged(tag_)
|
||||||
&& lfsr_tag_follow2(alt, weight,
|
&& lfsr_tag_follow2(alt, weight,
|
||||||
p_alts[0], p_weights[0],
|
p_alts[0], p_weights[0],
|
||||||
lower_id, upper_id,
|
lower_id, upper_id,
|
||||||
@@ -2121,7 +2135,8 @@ static int lfsr_rbyd_append(lfs_t *lfs, lfsr_rbyd_t *rbyd,
|
|||||||
branch_ = branch;
|
branch_ = branch;
|
||||||
lfsr_rbyd_p_pop(p_alts, p_weights, p_jumps);
|
lfsr_rbyd_p_pop(p_alts, p_weights, p_jumps);
|
||||||
} else {
|
} else {
|
||||||
diverged = 4;
|
tag_ = lfsr_tag_setdiverged(tag_);
|
||||||
|
other_tag_ = lfsr_tag_setdiverged(other_tag_);
|
||||||
other_branch = branch;
|
other_branch = branch;
|
||||||
other_lower_id = lower_id;
|
other_lower_id = lower_id;
|
||||||
other_upper_id = upper_id;
|
other_upper_id = upper_id;
|
||||||
@@ -2133,7 +2148,7 @@ static int lfsr_rbyd_append(lfs_t *lfs, lfsr_rbyd_t *rbyd,
|
|||||||
// if we're diverging, go ahead and make alt black, this isn't
|
// if we're diverging, go ahead and make alt black, this isn't
|
||||||
// perfect but it's simpler and compact will take care of any
|
// perfect but it's simpler and compact will take care of any
|
||||||
// balance issues that may occur
|
// balance issues that may occur
|
||||||
if (diverged) {
|
if (lfsr_tag_hasdiverged(tag_)) {
|
||||||
alt = lfsr_tag_setblack(alt);
|
alt = lfsr_tag_setblack(alt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2277,7 +2292,8 @@ static int lfsr_rbyd_append(lfs_t *lfs, lfsr_rbyd_t *rbyd,
|
|||||||
branch = branch_;
|
branch = branch_;
|
||||||
|
|
||||||
// prune inner alts if our tags diverged
|
// prune inner alts if our tags diverged
|
||||||
if (diverged && (diverged & 0x1) != lfsr_tag_isgt(alt)) {
|
if (lfsr_tag_hasdiverged(tag_)
|
||||||
|
&& lfsr_tag_isupper(tag_) != lfsr_tag_isgt(alt)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2294,20 +2310,23 @@ static int lfsr_rbyd_append(lfs_t *lfs, lfsr_rbyd_t *rbyd,
|
|||||||
// found end of tree?
|
// found end of tree?
|
||||||
} else {
|
} else {
|
||||||
// update the found tag/id
|
// update the found tag/id
|
||||||
tag_ = alt;
|
//
|
||||||
|
// note we:
|
||||||
|
// - preserve diverged bit (0x8)
|
||||||
|
// - preserve is upper tag (0x4)
|
||||||
|
// - set found tag (0x1)
|
||||||
|
tag_ = lfsr_tag_setfound(alt | (tag_ & 0xc));
|
||||||
id_ = upper_id-1;
|
id_ = upper_id-1;
|
||||||
|
|
||||||
// done?
|
// done?
|
||||||
if (diverged >= 4) {
|
if (!lfsr_tag_hasdiverged(tag_)
|
||||||
diverged -= 2;
|
|| lfsr_tag_isfound(other_tag_)) {
|
||||||
} else {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// switch to the other path if we have diverged
|
// switch to the other path if we have diverged
|
||||||
if (diverged >= 4 || !lfsr_tag_isalt(alt)) {
|
if (lfsr_tag_hasdiverged(tag_) || !lfsr_tag_isalt(alt)) {
|
||||||
diverged ^= 0x1;
|
|
||||||
lfs_swap16(&tag_, &other_tag_);
|
lfs_swap16(&tag_, &other_tag_);
|
||||||
lfs_sswap32(&id_, &other_id_);
|
lfs_sswap32(&id_, &other_id_);
|
||||||
lfs_swap32(&branch, &other_branch);
|
lfs_swap32(&branch, &other_branch);
|
||||||
@@ -2322,14 +2341,16 @@ static int lfsr_rbyd_append(lfs_t *lfs, lfsr_rbyd_t *rbyd,
|
|||||||
LFS_ASSERT(lfsr_tag_isblack(p_alts[0]));
|
LFS_ASSERT(lfsr_tag_isblack(p_alts[0]));
|
||||||
|
|
||||||
// if we diverged, merge the bounds
|
// if we diverged, merge the bounds
|
||||||
LFS_ASSERT(diverged < 4);
|
LFS_ASSERT(lfsr_tag_isfound(tag_));
|
||||||
if (diverged == 2) {
|
LFS_ASSERT(!lfsr_tag_hasdiverged(tag_)
|
||||||
|
|| lfsr_tag_isfound(other_tag_));
|
||||||
|
if (lfsr_tag_hasdiverged(tag_) && lfsr_tag_islower(tag_)) {
|
||||||
// finished on lower path
|
// finished on lower path
|
||||||
tag_ = other_tag_;
|
tag_ = other_tag_;
|
||||||
id_ = other_id_;
|
id_ = other_id_;
|
||||||
branch = other_branch;
|
branch = other_branch;
|
||||||
upper_id = other_upper_id;
|
upper_id = other_upper_id;
|
||||||
} else if (diverged == 3) {
|
} else if (lfsr_tag_hasdiverged(tag_) && lfsr_tag_isupper(tag_)) {
|
||||||
// finished on upper path
|
// finished on upper path
|
||||||
lower_id = other_lower_id;
|
lower_id = other_lower_id;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user