提交 d959c79e 创建 作者: 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

...@@ -57,6 +57,10 @@ struct radix { ...@@ -57,6 +57,10 @@ struct radix {
} }
radix_elem* search(u64 key); radix_elem* search(u64 key);
radix_range search_lock(u64 start, u64 size); radix_range search_lock(u64 start, u64 size);
// k is shifted value.
u64 skip_empty(u64 k) const;
NEW_DELETE_OPS(radix) NEW_DELETE_OPS(radix)
}; };
...@@ -64,8 +68,8 @@ struct radix_iterator { ...@@ -64,8 +68,8 @@ struct radix_iterator {
const radix* r_; const radix* r_;
u64 k_; u64 k_;
radix_iterator(const radix* r, u64 k) : r_(r), k_(k) {} radix_iterator(const radix* r, u64 k) : r_(r), k_(r->skip_empty(k)) {}
radix_iterator &operator++() { k_++; return *this; } radix_iterator &operator++() { k_++; k_ = r_->skip_empty(k_); return *this; }
radix_elem* operator*(); radix_elem* operator*();
bool operator==(const radix_iterator &other) { bool operator==(const radix_iterator &other) {
return r_ == other.r_ && k_ == other.k_; } return r_ == other.r_ && k_ == other.k_; }
......
...@@ -5,32 +5,39 @@ ...@@ -5,32 +5,39 @@
#include "cpputil.hh" #include "cpputil.hh"
#include "radix.hh" #include "radix.hh"
// Returns the level we stopped at.
template<class CB> template<class CB>
void u32
descend(u64 key, markptr<void> *n, u32 level, CB cb) descend(u64 key, markptr<void> *n, u32 level, CB cb, bool create)
{ {
// for now, we only support exact multiples of bits_per_level static_assert(key_bits == bits_per_level * radix_levels,
assert(key_bits == bits_per_level * radix_levels); "for now, we only support exact multiples of bits_per_level");
assert(n); assert(n);
void *v = n->ptr(); void *v = n->ptr();
if (v == 0) { if (v == 0 && create) {
radix_node *new_rn = new radix_node(); radix_node *new_rn = new radix_node();
if (n->ptr().cmpxch_update(&v, (void*) new_rn)) if (n->ptr().cmpxch_update(&v, (void*) new_rn))
v = new_rn; v = new_rn;
else else
delete new_rn; delete new_rn;
} }
// Node isn't there. Just return.
if (v == 0) {
return level+1;
}
radix_node *rn = (radix_node*) v; radix_node *rn = (radix_node*) v;
u64 idx = key >> (bits_per_level * level); u64 idx = key >> (bits_per_level * level);
idx &= (1<<bits_per_level)-1; idx &= (1<<bits_per_level)-1;
markptr<void> *vptr = &rn->ptr[idx]; markptr<void> *vptr = &rn->ptr[idx];
if (level == 0) if (level == 0) {
cb(vptr); cb(vptr);
else return level;
descend(key, vptr, level-1, cb); } else {
return descend(key, vptr, level-1, cb, create);
}
} }
radix_elem* radix_elem*
...@@ -39,7 +46,7 @@ radix::search(u64 key) ...@@ -39,7 +46,7 @@ radix::search(u64 key)
radix_elem *result = 0; radix_elem *result = 0;
descend(key >> shift_, &root_, radix_levels-1, [&result](markptr<void> *v) { descend(key >> shift_, &root_, radix_levels-1, [&result](markptr<void> *v) {
result = (radix_elem*) v->ptr().load(); result = (radix_elem*) v->ptr().load();
}); }, false);
return result; return result;
} }
...@@ -49,14 +56,37 @@ radix::search_lock(u64 start, u64 size) ...@@ -49,14 +56,37 @@ radix::search_lock(u64 start, u64 size)
return radix_range(this, start >> shift_, size >> shift_); return radix_range(this, start >> shift_, size >> shift_);
} }
u64
radix::skip_empty(u64 k) const
{
u64 next_k = k;
while (next_k < (1UL<<key_bits)) {
// Does next_k exist?
// FIXME: evil evil const_cast
u32 level = descend(next_k, const_cast<markptr<void>*>(&root_),
radix_levels-1, [](markptr<void> *v){}, false);
if (level == 0) {
return next_k;
}
u64 mask = 1UL<<(bits_per_level * level);
// Skip past everything we know is missing.
next_k = (next_k & ~(mask-1)) + mask;
}
// Nope, no successor.
return ~0ULL;
}
radix_range::radix_range(radix *r, u64 start, u64 size) radix_range::radix_range(radix *r, u64 start, u64 size)
: r_(r), start_(start), size_(size) : r_(r), start_(start), size_(size)
{ {
for (u64 k = start_; k != start_ + size_; k++) for (u64 k = start_; k != start_ + size_; k++) {
descend(k, &r_->root_, radix_levels-1, [](markptr<void> *v) { if (descend(k, &r_->root_, radix_levels-1, [](markptr<void> *v) {
while (!v->mark().xchg(true)) while (!v->mark().xchg(true))
; // spin ; // spin
}); }, true) != 0) {
panic("radix_range");
}
}
} }
radix_range::~radix_range() radix_range::~radix_range()
...@@ -64,10 +94,13 @@ radix_range::~radix_range() ...@@ -64,10 +94,13 @@ radix_range::~radix_range()
if (!r_) if (!r_)
return; return;
for (u64 k = start_; k != start_ + size_; k++) for (u64 k = start_; k != start_ + size_; k++) {
descend(k, &r_->root_, radix_levels-1, [](markptr<void> *v) { if (descend(k, &r_->root_, radix_levels-1, [](markptr<void> *v) {
v->mark() = false; v->mark() = false;
}); }, true) != 0) {
panic("~radix_range");
}
}
} }
void void
...@@ -79,15 +112,19 @@ radix_range::replace(u64 start, u64 size, radix_elem *val) ...@@ -79,15 +112,19 @@ radix_range::replace(u64 start, u64 size, radix_elem *val)
assert(start >= start_); assert(start >= start_);
assert(start + size <= start_ + size_); assert(start + size <= start_ + size_);
for (u64 k = start; k != start + size; k++) for (u64 k = start; k != start + size; k++) {
descend(k, &r_->root_, radix_levels-1, [val](markptr<void> *v) { if (descend(k, &r_->root_, radix_levels-1, [val](markptr<void> *v) {
void* cur = v->ptr().load(); void* cur = v->ptr().load();
while (!v->ptr().cmpxch_update(&cur, val)) while (!v->ptr().cmpxch_update(&cur, val))
; // spin ; // spin
val->incref(); if (val)
if (cur) val->incref();
((radix_elem*) cur)->decref(); if (cur)
}); ((radix_elem*) cur)->decref();
}, true)) {
panic("radix_range::replace");
}
}
} }
radix_elem* radix_elem*
...@@ -96,6 +133,6 @@ radix_iterator::operator*() ...@@ -96,6 +133,6 @@ radix_iterator::operator*()
radix_elem *result = 0; radix_elem *result = 0;
descend(k_, (markptr<void>*) &r_->root_, radix_levels-1, [&result](markptr<void> *v) { descend(k_, (markptr<void>*) &r_->root_, radix_levels-1, [&result](markptr<void> *v) {
result = (radix_elem*) v->ptr().load(); result = (radix_elem*) v->ptr().load();
}); }, false);
return result; return result;
} }
...@@ -640,7 +640,16 @@ vmap::sbrk(ssize_t n, uptr *addr) ...@@ -640,7 +640,16 @@ vmap::sbrk(ssize_t n, uptr *addr)
#if VM_RADIX #if VM_RADIX
auto span = rx.search_lock(newstart, newn + PGSIZE); auto span = rx.search_lock(newstart, newn + PGSIZE);
#endif #endif
#if VM_CRANGE
for (auto r: span) {
#endif
#if VM_RADIX
void *last = 0;
for (auto r: span) { for (auto r: span) {
if (!r || r == last)
continue;
last = r;
#endif
vma *e = (vma*) r; vma *e = (vma*) r;
if (e->vma_start <= newstart) { if (e->vma_start <= newstart) {
......
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论