提交 128f7acc 创建 作者: Silas Boyd-Wickizer's avatar Silas Boyd-Wickizer

Merge branch 'scale-amd64' of git+ssh://amsterdam.csail.mit.edu/home/am0/6.828/xv6 into scale-amd64

......@@ -6,6 +6,8 @@
#include "gc.hh"
#include <iterator>
enum { bits_per_level = 9 };
enum { key_bits = 36 };
enum { radix_levels = (key_bits + bits_per_level - 1) / bits_per_level };
......@@ -184,6 +186,7 @@ static_assert(alignof(radix_elem) > entry_mask,
"radix_elem sufficiently aligned");
struct radix;
struct radix_iterator;
struct radix_range {
radix* r_;
......@@ -196,11 +199,16 @@ struct radix_range {
void replace(u64 start, u64 size, radix_elem* val);
radix_iterator begin() const;
radix_iterator end() const;
radix_range(const radix_range&) = delete;
void operator=(const radix_range&) = delete;
};
struct radix {
typedef radix_iterator iterator;
radix_ptr root_;
u32 shift_;
......@@ -210,29 +218,36 @@ struct radix {
radix_elem* search(u64 key);
radix_range search_lock(u64 start, u64 size);
radix_iterator begin() const;
radix_iterator end() const;
NEW_DELETE_OPS(radix)
};
struct radix_iterator {
const radix* r_;
u64 k_;
// path_[i] is the node at level i. Note that the leaf is at zero
// and is radix_elem. The rest are radix_node. For now we assume all
// leaves are at level 0. Later we'll steal a bit for them. The root
// is path_[radix_levels].
radix_entry path_[radix_levels+1];
u32 leaf_;
radix_iterator(const radix* r, u64 k);
radix_iterator(const radix* r, u64 k, u64 limit)
: r_(r), k_(k), key_limit_(limit)
{
if (k_ != key_limit_)
prime_path();
}
radix_iterator &operator++() {
if (!advance(radix_levels-1)) k_ = ~0ULL;
assert(k_ < key_limit_);
advance();
return *this;
}
radix_elem* operator*() {
return path_[leaf_].elem();
return path_[level_]->load().elem();
}
// Advance the iterator until it points at a non-null entry or end.
// If the current element is non-null, does nothing.
void skip_nulls()
{
if (path_[level_]->load().is_null())
++(*this);
}
radix_node* node(u32 level) { return path_[level].node(); }
// Compare equality on just the key.
bool operator==(const radix_iterator &other) {
......@@ -241,19 +256,38 @@ struct radix_iterator {
return r_ != other.r_ || k_ != other.k_; }
private:
bool find_first_leaf(u32 level);
bool advance(u32 level);
const radix* r_;
u64 k_;
// The key value just past the end of the range being iterator over.
u64 key_limit_;
// path_[i] points into the child array of the node at level i.
const radix_ptr *path_[radix_levels];
// The level of the current element.
u32 level_;
// Prepare the initial path_ and level_ based on k_.
void prime_path();
// Advance to the next non-null leaf. This assumes that
// k_ < key_limit_.
void advance();
};
static inline radix_iterator
begin(const radix &r) { return radix_iterator(&r, 0); }
static inline radix_iterator
end(const radix &r) { return radix_iterator(&r, ~0ULL); }
// What we really need is one-past-the-last...
static inline radix_iterator
begin(const radix_range &rr) { return radix_iterator(rr.r_, rr.start_); }
static inline radix_iterator
end(const radix_range &rr) { return radix_iterator(rr.r_, rr.start_ + rr.size_); }
inline radix_iterator
radix_range::begin() const {
return radix_iterator(r_, start_, start_ + size_);
}
inline radix_iterator
radix_range::end() const {
return radix_iterator(r_, start_ + size_, start_ + size_);
}
inline radix_iterator
radix::begin() const {
return radix_iterator(this, 0, (u64)1 << key_bits);
}
inline radix_iterator
radix::end() const {
return radix_iterator(this, (u64)1 << key_bits, (u64)1 << key_bits);
}
......@@ -7,8 +7,8 @@
#include "hwvm.hh"
#include "uwq.hh"
#define VM_CRANGE 1
#define VM_RADIX 0
#define VM_CRANGE 0
#define VM_RADIX 1
struct padded_length;
......
......@@ -246,65 +246,58 @@ radix_range::replace(u64 start, u64 size, radix_elem *val)
}, 0, 1L << key_bits, start, start + size);
}
radix_iterator::radix_iterator(const radix* r, u64 k)
: r_(r), k_(k) {
void
radix_iterator::prime_path()
{
dprintf("%p: Made iterator with k = %lx\n", r_, k_);
if (k_ != ~0ULL) {
path_[radix_levels] = r_->root_.load();
if (path_[radix_levels].is_elem())
leaf_ = radix_levels; // Maybe best to not do this...
else if (!find_first_leaf(radix_levels - 1))
k_ = ~0ULL;
// Load the initial path
level_ = radix_levels;
const radix_ptr *node = &r_->root_;
radix_entry entry;
while ((entry = node->load()).is_node()) {
level_--;
path_[level_] = &entry.node()->child[index(k_, level_)];
node = path_[level_];
}
// Find a real element
skip_nulls();
dprintf("%p: Adjusted: k = %lx\n", r_, k_);
}
bool
radix_iterator::advance(u32 level)
void
radix_iterator::advance()
{
// First, see if we can advance a lower level.
if (level > leaf_ && advance(level-1)) {
// Nothing more to do.
return true;
}
while (true) {
// As long as we haven't reached our limit or an element, advance
// to the next key.
k_ += (u64)1 << (level_ * bits_per_level);
if (k_ == key_limit_)
return;
// If we've reached the end of this node, move up the tree until
// we find a node that has more entries. (Note that we don't have
// to worry about going off the top because our key_limit_
// prevents that.)
while (index(k_, level_) == 0) {
level_++;
}
assert(level_ <= radix_levels);
// Try to advance this level, if we can.
u32 start_idx = index(k_, level)+1;
if (start_idx < (1<<bits_per_level)) {
// Find the first leaf starting at our sibling node.
k_ &= ~((1ULL<<((level+1) * bits_per_level)) - 1);
k_ |= (u64(start_idx) << (level * bits_per_level));
return find_first_leaf(level);
} else {
return false;
}
}
// Update our path pointer at the level we've moved over on
path_[level_]++;
bool
radix_iterator::find_first_leaf(u32 level)
{
// Find the first non-empty node after k_ on this level.
for (u32 idx = index(k_, level); idx < (1<<bits_per_level); idx++) {
radix_entry next = node(level+1)->child[idx].load();
if (!next.is_null()) {
if (index(k_, level) != idx) {
// We had to advance; clear everything this level and under
// and set this one.
k_ &= ~((1ULL<<((level+1) * bits_per_level)) - 1);
k_ |= (u64(idx) << (level * bits_per_level));
}
path_[level] = next;
if (next.is_elem()) {
// Found a leaf. Stop now.
leaf_ = level;
return true;
} else if (find_first_leaf(level-1))
// Keep looking.
return true;
// Move down the tree as much as we can
radix_entry entry;
while ((entry = path_[level_]->load()).is_node()) {
path_[level_ - 1] = &entry.node()->child[0];
level_--;
}
}
// Failed to find a leaf. Abort.
return false;
// Did we reach a non-null leaf?
if (!entry.is_null())
return;
}
}
// -*- c++ -*-
namespace std {
template <class C> auto begin(C& c) -> decltype(c.begin())
{
return c.begin();
}
template <class C> auto begin(const C& c) -> decltype(c.begin())
{
return c.begin();
}
template <class C> auto end(C& c) -> decltype(c.end())
{
return c.end();
}
template <class C> auto end(const C& c) -> decltype(c.end())
{
return c.end();
}
template <class T, size_t N> T* begin(T (&array)[N])
{
return array[0];
}
template <class T, size_t N> T* end(T (&array)[N])
{
return array[N];
}
}
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论