提交 5108276c 创建 作者: Silas Boyd-Wickizer's avatar Silas Boyd-Wickizer

Merge remote-tracking branch '6.828/scale-amd64' into scale-amd64

...@@ -28,7 +28,6 @@ LDFLAGS += -m elf_x86_64 ...@@ -28,7 +28,6 @@ LDFLAGS += -m elf_x86_64
OBJS = \ OBJS = \
bio.o \ bio.o \
bonsai.o \
cga.o \ cga.o \
condvar.o \ condvar.o \
console.o \ console.o \
......
...@@ -26,46 +26,52 @@ ...@@ -26,46 +26,52 @@
#define assert(c) if (!(c)) { panic("assertion failure"); } #define assert(c) if (!(c)) { panic("assertion failure"); }
struct lock { #define CRANGE_CHECKING 1
int locked;
int me;
} __mpalign__;
struct clist_range {
u64 key;
u64 size;
long value;
int curlevel;
int nlevel;
struct crange *cr;
struct clist_range** next; // one next pointer per level
struct lock lock; // on separate cache line?
} __mpalign__;
#define CRANGE_CHECKING 0
#define MINNLEVEL 10 #define MINNLEVEL 10
#define MARKED(x) (((uintptr) (x)) & 0x1) #define MARKED(x) (((uintptr) (x)) & 0x1)
#define RANGE_MARK(x) ((struct clist_range *) (((uintptr) (x)) | 0x1)) #define RANGE_MARK(x) ((struct clist_range *) (((uintptr) (x)) | 0x1))
#define RANGE_WOMARK(x) ((struct clist_range *) (((uintptr) (x)) & ~0x1)) #define RANGE_WOMARK(x) ((struct clist_range *) (((uintptr) (x)) & ~0x1))
enum { crange_debug = 0 };
struct crange { struct crange {
int nlevel; int nlevel;
struct clist_range crange_head; struct clist_range crange_head;
} cr; } cr;
struct crange* struct crange*
crange_init(int nlevel) crange_alloc(int nlevel)
{ {
struct crange *cr = kmalloc(sizeof(struct crange)); struct crange *cr = kmalloc(sizeof(struct crange));
cr->nlevel = (nlevel < MINNLEVEL) ? MINNLEVEL : nlevel; // XXX cr->nlevel = (nlevel < MINNLEVEL) ? MINNLEVEL : nlevel; // XXX
cr->crange_head.cr = cr; cr->crange_head.cr = cr;
cr->crange_head.lock.me = -1; cr->crange_head.lock = kmalloc(sizeof(struct spinlock));
initlock(cr->crange_head.lock, "head lock");
cr->crange_head.next = kmalloc(sizeof(cr->crange_head.next[0]) * nlevel); cr->crange_head.next = kmalloc(sizeof(cr->crange_head.next[0]) * nlevel);
for (int l = 0; l < nlevel; l++) cr->crange_head.next[l] = 0; for (int l = 0; l < nlevel; l++) cr->crange_head.next[l] = 0;
if (crange_debug) cprintf("crange_alloc: return 0x%x\n", cr);
return cr; return cr;
} }
static void clist_range_free(void *p);
void
crange_free(struct crange *cr)
{
assert(cr);
if (crange_debug) cprintf("crange_free: 0x%x\n", cr);
struct clist_range *e, *n;
for (e = RANGE_WOMARK(cr->crange_head.next[0]); e; e = n) {
n = RANGE_WOMARK(e->next[0]);
clist_range_free(e);
}
kmfree(cr->crange_head.next);
kmfree(cr->crange_head.lock);
kmfree(cr);
}
// draw nlevel in [1, nlevel] // draw nlevel in [1, nlevel]
static int static int
crange_draw_nlevel(int nlevel) crange_draw_nlevel(int nlevel)
...@@ -82,7 +88,7 @@ crange_draw_nlevel(int nlevel) ...@@ -82,7 +88,7 @@ crange_draw_nlevel(int nlevel)
void void
crange_print_elem(struct clist_range *e, int l) crange_print_elem(struct clist_range *e, int l)
{ {
cprintf ("%lu(%lu, 0x%lx, c %d, t %d, l %d, me %d n 0x%lx m 0x%ld\n", e->key, e->size, (long) e->value, e->curlevel, e->nlevel, e->lock.locked, e->lock.me, (long) e->next, MARKED(e->next[l])); cprintf ("0x%lx(0x%lx, 0x%lx, c %d, t %d, l %d, n 0x%lx m 0x%lx\n", e->key, e->size, (long) e->value, e->curlevel, e->nlevel, e->lock->locked, (long) e->next, MARKED(e->next[l]));
} }
void void
...@@ -91,7 +97,7 @@ crange_print(struct crange *cr, int full) ...@@ -91,7 +97,7 @@ crange_print(struct crange *cr, int full)
struct clist_range *e; struct clist_range *e;
for (int l = 0; l < cr->nlevel; l++) { for (int l = 0; l < cr->nlevel; l++) {
int c = 0; int c = 0;
cprintf("crange %d (l %d me %d): ", l, cr->crange_head.lock.locked, cr->crange_head.lock.me); cprintf("crange %d (l %d): ", l, cr->crange_head.lock->locked);
for (e = cr->crange_head.next[l]; e; e = RANGE_WOMARK(e->next[l])) { for (e = cr->crange_head.next[l]; e; e = RANGE_WOMARK(e->next[l])) {
c++; c++;
if (full) crange_print_elem(e, l); if (full) crange_print_elem(e, l);
...@@ -110,8 +116,8 @@ crange_check(struct crange *cr, int lockcheck, struct clist_range *absent) ...@@ -110,8 +116,8 @@ crange_check(struct crange *cr, int lockcheck, struct clist_range *absent)
for (int l = 0; l < cr->nlevel; l++) { for (int l = 0; l < cr->nlevel; l++) {
p = &cr->crange_head; p = &cr->crange_head;
for (e = cr->crange_head.next[l]; e; e = s) { for (e = cr->crange_head.next[l]; e; e = s) {
assert((e != absent) || (l == 0 && e->lock.locked)); assert((e != absent) || (l == 0 && e->lock->locked));
assert(!lockcheck || e->lock.me != mycpu()->id); // assert(!lockcheck || e->lock.me != mycpu()->id);
assert(e->curlevel < cr->nlevel); assert(e->curlevel < cr->nlevel);
if (l > 0 && e->next[l] != 0 && !MARKED(e->next[l])) { if (l > 0 && e->next[l] != 0 && !MARKED(e->next[l])) {
struct clist_range *n; struct clist_range *n;
...@@ -149,7 +155,7 @@ crange_check(struct crange *cr, int lockcheck, struct clist_range *absent) ...@@ -149,7 +155,7 @@ crange_check(struct crange *cr, int lockcheck, struct clist_range *absent)
} }
static void static void
crange_free(void *p) clist_range_free(void *p)
{ {
struct clist_range *e = (struct clist_range *) p; struct clist_range *e = (struct clist_range *) p;
// cprintf("crange_free: %u(%u)\n", e->key, e->size); // cprintf("crange_free: %u(%u)\n", e->key, e->size);
...@@ -157,8 +163,9 @@ crange_free(void *p) ...@@ -157,8 +163,9 @@ crange_free(void *p)
for (int l = 0; l < e->nlevel; l++) { for (int l = 0; l < e->nlevel; l++) {
e->next[l] = (struct clist_range *) 0xDEADBEEF; e->next[l] = (struct clist_range *) 0xDEADBEEF;
} }
kfree(e->next); kmfree(e->lock);
kfree(e); kmfree(e->next);
kmfree(e);
} }
static void static void
...@@ -166,18 +173,18 @@ crange_free_delayed(struct clist_range *e) ...@@ -166,18 +173,18 @@ crange_free_delayed(struct clist_range *e)
{ {
// cprintf("crange_free_delayed: 0x%lx %u(%u) %u\n", (long) e, (e)->key, (e)->size, myepoch); // cprintf("crange_free_delayed: 0x%lx %u(%u) %u\n", (long) e, (e)->key, (e)->size, myepoch);
crange_check(e->cr, 0, e); crange_check(e->cr, 0, e);
gc_delayed(e, crange_free); gc_delayed(e, clist_range_free);
} }
static struct clist_range * static struct clist_range *
crange_new(struct crange *cr, u64 k, u64 sz, struct clist_range *n) crange_new(struct crange *cr, u64 k, u64 sz, void *v, struct clist_range *n)
{ {
struct clist_range *r; struct clist_range *r;
r = kmalloc(sizeof(struct clist_range)); r = kmalloc(sizeof(struct clist_range));
assert(r); assert(r);
r->key = k; r->key = k;
r->size = sz; r->size = sz;
r->value = 0; r->value = v;
assert(r->size > 0); assert(r->size > 0);
assert(cr->nlevel > 0); assert(cr->nlevel > 0);
r->curlevel = 0; r->curlevel = 0;
...@@ -186,8 +193,8 @@ crange_new(struct crange *cr, u64 k, u64 sz, struct clist_range *n) ...@@ -186,8 +193,8 @@ crange_new(struct crange *cr, u64 k, u64 sz, struct clist_range *n)
assert(r->next); assert(r->next);
r->next[0] = n; r->next[0] = n;
for (int l = 1; l < r->nlevel; l++) r->next[l] = 0; for (int l = 1; l < r->nlevel; l++) r->next[l] = 0;
r->lock.locked = 0; r->lock = kmalloc(sizeof(struct spinlock));
r->lock.me = -1; initlock(r->lock, "crange");
r->cr = cr; r->cr = cr;
return r; return r;
} }
...@@ -222,44 +229,16 @@ crange_intersect(u64 k1, u64 sz1, u64 k2, u64 sz2) ...@@ -222,44 +229,16 @@ crange_intersect(u64 k1, u64 sz1, u64 k2, u64 sz2)
else return 1; else return 1;
} }
// XXX should use scalable locks
static void
crange_unlock(struct lock *lock)
{
assert(lock->locked);
assert(lock->me == mycpu()->id);
lock->me = -1;
lock->locked = 0;
}
static void
crange_lock(struct lock *lock)
{
assert(lock->me != mycpu()->id);
while (1) {
int locked = __sync_val_compare_and_swap(&lock->locked, 0, 1);
if (!locked)
break;
}
lock->me = mycpu()->id;
}
static int
crange_check_locked(struct lock *l)
{
return (l->locked && l->me == mycpu()->id);
}
// lock p if p->next == e and p isn't marked for deletion. if not, return failure. // lock p if p->next == e and p isn't marked for deletion. if not, return failure.
static int static int
crange_lockpred(struct clist_range *p, struct clist_range *e) crange_lockpred(struct clist_range *p, struct clist_range *e)
{ {
assert(!MARKED(e)); assert(!MARKED(e));
crange_lock(&p->lock); acquire(p->lock);
if (p->next[0] == e) { if (p->next[0] == e) {
return 1; return 1;
} }
crange_unlock(&p->lock); release(p->lock);
// cprintf("%d: crange_lockpred: retry %u\n", mycpu()->id, p->key); // cprintf("%d: crange_lockpred: retry %u\n", mycpu()->id, p->key);
return 0; return 0;
} }
...@@ -285,9 +264,9 @@ crange_unlockn(struct clist_range *f, struct clist_range *l) ...@@ -285,9 +264,9 @@ crange_unlockn(struct clist_range *f, struct clist_range *l)
struct clist_range *e; struct clist_range *e;
for (e = f; e != l; e = RANGE_WOMARK(e->next[0])) { for (e = f; e != l; e = RANGE_WOMARK(e->next[0])) {
assert(e); assert(e);
crange_unlock(&e->lock); release(e->lock);
} }
if (l) crange_unlock(&e->lock); if (l) release(e->lock);
} }
// Delay free nodes f through l // Delay free nodes f through l
...@@ -329,7 +308,7 @@ crange_del_index(struct crange *cr, struct clist_range *p0, struct clist_range * ...@@ -329,7 +308,7 @@ crange_del_index(struct crange *cr, struct clist_range *p0, struct clist_range *
int cas = __sync_bool_compare_and_swap(&(p0->next[l]), *e, RANGE_WOMARK((*e)->next[l])); int cas = __sync_bool_compare_and_swap(&(p0->next[l]), *e, RANGE_WOMARK((*e)->next[l]));
if (cas) { if (cas) {
__sync_fetch_and_sub(&((*e)->curlevel), 1); __sync_fetch_and_sub(&((*e)->curlevel), 1);
if (l == 1 && !(*e)->lock.locked) { if (l == 1 && !(*e)->lock->locked) {
// assert((*e)->curlevel == 0); // XXX could it be 1 temporarily because of add_index? // assert((*e)->curlevel == 0); // XXX could it be 1 temporarily because of add_index?
crange_free_delayed(*e); crange_free_delayed(*e);
} }
...@@ -397,11 +376,11 @@ crange_lock_range(u64 k, u64 sz, int l, struct clist_range **er, struct clist_ra ...@@ -397,11 +376,11 @@ crange_lock_range(u64 k, u64 sz, int l, struct clist_range **er, struct clist_ra
// locked p and e; we are in business // locked p and e; we are in business
} }
// find successor of [k, sz) // find successor of [k, sz)
while (e && k+sz > e->key) { while (e && (k+sz) > e->key) {
assert(*fr); assert(*fr);
*lr = e; *lr = e;
if (l == 0) { if (l == 0) {
crange_lock(&e->lock); // lock all nodes in the range acquire(e->lock); // lock all nodes in the range
} }
e = RANGE_WOMARK(e->next[l]); e = RANGE_WOMARK(e->next[l]);
} }
...@@ -454,8 +433,8 @@ crange_find_and_lock(struct crange *cr, u64 k, u64 sz, struct clist_range **p0, ...@@ -454,8 +433,8 @@ crange_find_and_lock(struct crange *cr, u64 k, u64 sz, struct clist_range **p0,
if (*f0 == NULL) { // range isn't present, lock predecessor of key if (*f0 == NULL) { // range isn't present, lock predecessor of key
if (!crange_lockpred(*p0, *s0)) goto retry; if (!crange_lockpred(*p0, *s0)) goto retry;
} }
assert(!*f0 || crange_check_locked(&((*f0)->lock))); assert(!*f0 || ((*f0)->lock->locked));
assert(!*l0 || crange_check_locked(&((*l0)->lock))); assert(!*l0 || ((*l0)->lock->locked));
assert(!*l0 || !MARKED((*l0)->next[0])); assert(!*l0 || !MARKED((*l0)->next[0]));
assert(!MARKED((*p0)->next)); assert(!MARKED((*p0)->next));
assert(!(*p0)->next[0] || !MARKED((*p0)->next[0]->next[0])); assert(!(*p0)->next[0] || !MARKED((*p0)->next[0]->next[0]));
...@@ -466,28 +445,28 @@ crange_find_and_lock(struct crange *cr, u64 k, u64 sz, struct clist_range **p0, ...@@ -466,28 +445,28 @@ crange_find_and_lock(struct crange *cr, u64 k, u64 sz, struct clist_range **p0,
// Compute the sublist that will replace the to-be deleted range. Make copies to create // Compute the sublist that will replace the to-be deleted range. Make copies to create
// the new nodes, because readers may running through the list and looking at the old nodes. // the new nodes, because readers may running through the list and looking at the old nodes.
static struct clist_range * static struct clist_range *
crange_replace(u64 k, u64 sz, struct clist_range *f, struct clist_range *l, crange_replace(u64 k, u64 sz, void *v, struct clist_range *f, struct clist_range *l,
struct clist_range *s) struct clist_range *s)
{ {
struct clist_range *r; struct clist_range *r;
assert(!f || crange_check_locked(&f->lock)); assert(!f || f->lock->locked);
assert(!l || crange_check_locked(&l->lock)); assert(!l || l->lock->locked);
if (f == l) { // the first node covers range to be deleted if (f == l) { // the first node covers range to be deleted
if (k <= f->key && f->key + f->size <= k + sz) { // range covers the first node if (k <= f->key && f->key + f->size <= k + sz) { // range covers the first node
r = s; r = s;
} else { } else {
if (f->key < k && k+sz < f->key + f->size) { // split node? if (f->key < k && k+sz < f->key + f->size) { // split node?
struct clist_range *right = crange_new(f->cr, k+sz, f->key+f->size-k-sz, s); struct clist_range *right = crange_new(f->cr, k+sz, f->key+f->size-k-sz, v, s);
struct clist_range *left = crange_new(f->cr, f->key, k-f->key, right); struct clist_range *left = crange_new(f->cr, f->key, k-f->key, v, right);
r = left; r = left;
} else if (k <= f->key) { // cut front? } else if (k <= f->key) { // cut front?
assert(k+sz <= f->key + f->size); assert(k+sz <= f->key + f->size);
r = crange_new(f->cr, k+sz, f->key + f->size - k - sz, f->next[0]); r = crange_new(f->cr, k+sz, f->key + f->size - k - sz, v, f->next[0]);
} else { // cut end } else { // cut end
assert(k > f->key); assert(k > f->key);
r = crange_new(f->cr, f->key, k - f->key, f->next[0]); r = crange_new(f->cr, f->key, k - f->key, v, f->next[0]);
} }
} }
} else if (k <= f->key && k + sz >= l->key + l->size) { // delete complete range? } else if (k <= f->key && k + sz >= l->key + l->size) { // delete complete range?
...@@ -500,14 +479,14 @@ crange_replace(u64 k, u64 sz, struct clist_range *f, struct clist_range *l, ...@@ -500,14 +479,14 @@ crange_replace(u64 k, u64 sz, struct clist_range *f, struct clist_range *l,
left = NULL; left = NULL;
} else { } else {
assert(k > f->key); assert(k > f->key);
left = crange_new(f->cr, f->key, k - f->key, 0); left = crange_new(f->cr, f->key, k - f->key, v, 0);
} }
if (k + sz >= l->key + l->size) { // delete last node? if (k + sz >= l->key + l->size) { // delete last node?
right = NULL; right = NULL;
} else { } else {
assert(k+sz > l->key); assert(k+sz > l->key);
assert(l->key + l->size >= k + sz); assert(l->key + l->size >= k + sz);
right = crange_new(f->cr, k+sz, l->key+l->size - k - sz, s); right = crange_new(f->cr, k+sz, l->key+l->size - k - sz, v, s);
} }
r = left ? left : right; r = left ? left : right;
if (left) left->next[0] = right ? right : s; if (left) left->next[0] = right ? right : s;
...@@ -521,6 +500,7 @@ crange_search(struct crange *cr, u64 k) ...@@ -521,6 +500,7 @@ crange_search(struct crange *cr, u64 k)
{ {
struct clist_range *p, *e, *r; struct clist_range *p, *e, *r;
gc_begin_epoch(); gc_begin_epoch();
if (crange_debug) cprintf("crange_search: 0x%x 0x%lx\n", cr, k);
r = NULL; r = NULL;
p = &cr->crange_head; p = &cr->crange_head;
for (int l = cr->nlevel-1; l >= 0; l--) { for (int l = cr->nlevel-1; l >= 0; l--) {
...@@ -541,6 +521,7 @@ crange_search(struct crange *cr, u64 k) ...@@ -541,6 +521,7 @@ crange_search(struct crange *cr, u64 k)
} }
end: end:
gc_end_epoch(); gc_end_epoch();
// cprintf("crange_search: 0x%x return (0x%lx,0x%lx)\n", cr, r? r->key : 0, r? r->size : 0);
return r; return r;
} }
...@@ -554,19 +535,21 @@ crange_del(struct crange *cr, u64 k, u64 sz) ...@@ -554,19 +535,21 @@ crange_del(struct crange *cr, u64 k, u64 sz)
struct clist_range *last; struct clist_range *last;
struct clist_range *repl = NULL; struct clist_range *repl = NULL;
if (crange_debug) cprintf("crange_del: 0x%x (0x%lx,0x%lx)\n", cr, k, sz);
assert(cr);
gc_begin_epoch(); gc_begin_epoch();
if (!crange_find_and_lock(cr, k, sz, &prev, &first, &last, &succ)) { // done? if (!crange_find_and_lock(cr, k, sz, &prev, &first, &last, &succ)) { // done?
// cprintf("crange_del: [%d,%d) not present\n", k, sz); cprintf("crange_del: [0x%lx,0x%lx) not present\n", k, sz);
crange_unlock(&prev->lock); release(prev->lock);
goto done; goto done;
} }
repl = crange_replace(k, sz, first, last, succ); repl = crange_replace(k, sz, NULL, first, last, succ); // XXX cannot be NULL
crange_mark(first, succ, 0); // mark first till s on level >= 0 crange_mark(first, succ, 0); // mark first till s on level >= 0
while (1) { while (1) {
// hook new list into bottom list; if del resulted in a new list, use that (repl), otherwise // hook new list into bottom list; if del resulted in a new list, use that (repl), otherwise
// set predecessor to successor. // set predecessor to successor.
if (__sync_bool_compare_and_swap(&(prev->next[0]), first, repl ? repl : succ)) { if (__sync_bool_compare_and_swap(&(prev->next[0]), first, repl ? repl : succ)) {
crange_unlock(&prev->lock); release(prev->lock);
crange_freen(first, last); // put on delayed list before unlocking crange_freen(first, last); // put on delayed list before unlocking
crange_unlockn(first, last); crange_unlockn(first, last);
break; break;
...@@ -576,7 +559,7 @@ crange_del(struct crange *cr, u64 k, u64 sz) ...@@ -576,7 +559,7 @@ crange_del(struct crange *cr, u64 k, u64 sz)
} }
done: done:
crange_check(cr, 1, NULL); crange_check(cr, 1, NULL);
// cprintf("%d: crange_del(%u, %u):\n", mycpu()->id, k, sz); crange_print(cr, 1); // cprintf("%d: crange_del(0x%lx, 0x%lx):\n", mycpu()->id, k, sz); crange_print(cr, 1);
gc_end_epoch(); gc_end_epoch();
} }
...@@ -584,7 +567,7 @@ crange_del(struct crange *cr, u64 k, u64 sz) ...@@ -584,7 +567,7 @@ crange_del(struct crange *cr, u64 k, u64 sz)
// add the range [k, sz), which causes nodes to be deleted, if the range overlaps an // add the range [k, sz), which causes nodes to be deleted, if the range overlaps an
// existing range. we compute the replacement list and then hook it atomically. // existing range. we compute the replacement list and then hook it atomically.
void void
crange_add(struct crange *cr, u64 k, u64 sz) crange_add(struct crange *cr, u64 k, u64 sz, void *v)
{ {
struct clist_range *new; struct clist_range *new;
struct clist_range *first; struct clist_range *first;
...@@ -593,27 +576,40 @@ crange_add(struct crange *cr, u64 k, u64 sz) ...@@ -593,27 +576,40 @@ crange_add(struct crange *cr, u64 k, u64 sz)
struct clist_range *succ; struct clist_range *succ;
struct clist_range *repl = NULL; struct clist_range *repl = NULL;
if (crange_debug) cprintf("crange_add: 0x%x (0x%lx,0x%lx)\n", cr, k, sz);
assert(cr);
gc_begin_epoch(); gc_begin_epoch();
if (crange_find_and_lock(cr, k, sz, &prev, &first, &last, &succ)) { if (crange_find_and_lock(cr, k, sz, &prev, &first, &last, &succ)) {
// cprintf("crange_add(%d,%d) overlaps with [%d,%d)\n", k, sz, first->key, first->size); cprintf("crange_add(0x%lx,0x%lx) overlaps with [0x%lx,0x%lx)\n", k, sz, first->key, first->size);
repl = crange_replace(k, sz, first, last, succ); repl = crange_replace(k, sz, v, first, last, succ);
} else { } else {
repl = succ; repl = succ;
} }
new = crange_new(cr, k, sz, succ); new = crange_new(cr, k, sz, v, succ);
repl = crange_insert(repl, new); repl = crange_insert(repl, new);
crange_mark(first, succ, 0); // mark first till s on all levels crange_mark(first, succ, 0); // mark first till s on all levels
if (prev) if (prev)
assert(!MARKED(prev->next[0])); assert(!MARKED(prev->next[0]));
if (__sync_bool_compare_and_swap(&(prev->next[0]), first ? first : succ, repl)) { if (__sync_bool_compare_and_swap(&(prev->next[0]), first ? first : succ, repl)) {
crange_unlock(&prev->lock); release(prev->lock);
crange_freen(first, last); // put on delayed list before unlocking crange_freen(first, last); // put on delayed list before unlocking
crange_unlockn(first, last); crange_unlockn(first, last);
} else { } else {
assert(0); assert(0);
} }
//cprintf("crange_add(%u,%u):\n", k, sz); crange_print(cr, 1); // cprintf("crange_add(0x%lx,0x%lx):\n", k, sz); crange_print(cr, 1);
crange_check(cr, 1, NULL); crange_check(cr, 1, NULL);
gc_end_epoch(); gc_end_epoch();
} }
int
crange_foreach(struct crange *cr, int (*cb)(struct clist_range *r, void *), void *st)
{
struct clist_range *e;
assert(cr);
for (e = RANGE_WOMARK(cr->crange_head.next[0]); e; e = RANGE_WOMARK(e->next[0])) {
if (!cb(e, st))
return 0;
}
return 1;
}
...@@ -38,19 +38,6 @@ struct buf* bread(u32, u64, int writer); ...@@ -38,19 +38,6 @@ struct buf* bread(u32, u64, int writer);
void brelse(struct buf*, int writer); void brelse(struct buf*, int writer);
void bwrite(struct buf*); void bwrite(struct buf*);
// bonsai.c
struct kv {
u64 key;
void *val;
};
struct kv* tree_find(struct node *n, u64 key);
struct kv* tree_find_gt(struct node *n, u64 key);
struct node* tree_insert(struct node *n, struct kv *kv);
struct node* tree_remove(struct node *n, u64 key);
int tree_foreach(struct node *n, int (*cb)(struct kv* kv, void *), void *);
void tree_test(void);
// cga.c // cga.c
void cgaputc(int c); void cgaputc(int c);
...@@ -70,6 +57,30 @@ void panic(const char*) __attribute__((noreturn)); ...@@ -70,6 +57,30 @@ void panic(const char*) __attribute__((noreturn));
void snprintf(char *buf, u32 n, char *fmt, ...); void snprintf(char *buf, u32 n, char *fmt, ...);
void consoleintr(int(*)(void)); void consoleintr(int(*)(void));
// crange.c
struct clist_range {
u64 key;
u64 size;
void *value;
int curlevel;
int nlevel;
struct crange *cr;
struct clist_range** next; // one next pointer per level
struct spinlock *lock; // on separate cache line?
} __mpalign__;
struct crange;
struct crange* crange_alloc(int nlevel);
void crange_free(struct crange *cr);
void crange_del(struct crange *cr, u64 k, u64 sz);
void crange_add(struct crange *cr, u64 k, u64 sz, void *v);
struct clist_range* crange_search(struct crange *cr, u64 k);
int crange_foreach(struct crange *crk, int (*f)(struct clist_range *r, void *st), void *st);
void crange_print(struct crange *cr, int);
// e1000.c // e1000.c
extern int e1000irq; extern int e1000irq;
void e1000intr(void); void e1000intr(void);
......
...@@ -569,7 +569,7 @@ fork(int flags) ...@@ -569,7 +569,7 @@ fork(int flags)
struct proc *np; struct proc *np;
int cow = 1; int cow = 1;
// cprintf("%d: fork\n", proc->pid); // cprintf("%d: fork\n", myproc()->pid);
// Allocate process. // Allocate process.
if((np = allocproc()) == 0) if((np = allocproc()) == 0)
......
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
static void vmap_free(void *p); static void vmap_free(void *p);
enum { vm_debug = 0 };
static struct vma * static struct vma *
vma_alloc(void) vma_alloc(void)
{ {
...@@ -103,7 +105,6 @@ vmap_alloc(void) ...@@ -103,7 +105,6 @@ vmap_alloc(void)
struct vmap *m = kmalloc(sizeof(struct vmap)); struct vmap *m = kmalloc(sizeof(struct vmap));
if (m == 0) if (m == 0)
return 0; return 0;
memset(m, 0, sizeof(struct vmap)); memset(m, 0, sizeof(struct vmap));
snprintf(m->lockname, sizeof(m->lockname), "vmap:%p", m); snprintf(m->lockname, sizeof(m->lockname), "vmap:%p", m);
initlock(&m->lock, m->lockname); initlock(&m->lock, m->lockname);
...@@ -114,6 +115,11 @@ vmap_alloc(void) ...@@ -114,6 +115,11 @@ vmap_alloc(void)
kmfree(m); kmfree(m);
return 0; return 0;
} }
#ifdef TREE
m->cr = crange_alloc(10);
if (m->cr == 0)
return 0;
#endif
return m; return m;
} }
...@@ -210,6 +216,9 @@ pagefault(struct vmap *vmap, uptr va, u32 err) ...@@ -210,6 +216,9 @@ pagefault(struct vmap *vmap, uptr va, u32 err)
if (m->n && m->n->type == ONDEMAND && m->n->page[npg] == 0) if (m->n && m->n->type == ONDEMAND && m->n->page[npg] == 0)
m = pagefault_ondemand(vmap, va, err, m); m = pagefault_ondemand(vmap, va, err, m);
if (vm_debug)
cprintf("pagefault: err 0x%x va 0x%x type %d ref %d pid %d\n", err, va, m->va_type, m->n->ref, myproc()->pid);
if (m->va_type == COW && (err & FEC_WR)) { if (m->va_type == COW && (err & FEC_WR)) {
if (pagefault_wcow(vmap, va, pte, m, npg) < 0) { if (pagefault_wcow(vmap, va, pte, m, npg) < 0) {
release(&m->lock); release(&m->lock);
...@@ -301,15 +310,14 @@ vmn_alloc(u64 npg, enum vmntype type) ...@@ -301,15 +310,14 @@ vmn_alloc(u64 npg, enum vmntype type)
struct state { struct state {
int share; int share;
void *pml4; void *pml4;
struct node *root; struct crange *cr;
}; };
static int static int
vmap_free_vma(struct kv *kv, void *p) vmap_free_vma(struct clist_range *r, void *st)
{ {
struct state *st = (struct state *) p; vma_free(r->value);
vma_free(kv->val); crange_del(r->cr, r->key, r->size);
st->root = tree_remove(st->root, kv->key);
return 1; return 1;
} }
...@@ -317,12 +325,9 @@ static void ...@@ -317,12 +325,9 @@ static void
vmap_free(void *p) vmap_free(void *p)
{ {
struct vmap *m = (struct vmap *) p; struct vmap *m = (struct vmap *) p;
struct state *st = kmalloc(sizeof(struct state)); crange_foreach(m->cr, vmap_free_vma, NULL);
st->root = m->root; crange_free(m->cr);
tree_foreach(m->root, vmap_free_vma, st);
m->root = st->root;
freevm(m->pml4); freevm(m->pml4);
kmfree(st);
m->pml4 = 0; m->pml4 = 0;
m->alloc = 0; m->alloc = 0;
} }
...@@ -339,9 +344,9 @@ vmap_lookup(struct vmap *m, uptr start, uptr len) ...@@ -339,9 +344,9 @@ vmap_lookup(struct vmap *m, uptr start, uptr len)
if(start + len < start) if(start + len < start)
panic("vmap_lookup bad len"); panic("vmap_lookup bad len");
struct kv *kv = tree_find_gt(m->root, start); // find vma with va_end > start struct clist_range *r = crange_search(m->cr, start);
if (kv != 0) { if (r != 0) {
struct vma *e = (struct vma *) (kv->val); struct vma *e = (struct vma *) (r->value);
if (e->va_end <= e->va_start) if (e->va_end <= e->va_start)
panic("malformed va"); panic("malformed va");
if (e->va_start < start+len && e->va_end > start) { if (e->va_start < start+len && e->va_end > start) {
...@@ -365,7 +370,6 @@ vmap_insert(struct vmap *m, struct vmnode *n, uptr va_start) ...@@ -365,7 +370,6 @@ vmap_insert(struct vmap *m, struct vmnode *n, uptr va_start)
} }
struct vma *e = vma_alloc(); struct vma *e = vma_alloc();
struct kv kv;
if (e == 0) { if (e == 0) {
release(&m->lock); release(&m->lock);
return -1; return -1;
...@@ -374,18 +378,16 @@ vmap_insert(struct vmap *m, struct vmnode *n, uptr va_start) ...@@ -374,18 +378,16 @@ vmap_insert(struct vmap *m, struct vmnode *n, uptr va_start)
e->va_end = va_start + len; e->va_end = va_start + len;
e->n = n; e->n = n;
__sync_fetch_and_add(&n->ref, 1); __sync_fetch_and_add(&n->ref, 1);
kv.key = e->va_end; crange_add(m->cr, e->va_start, len, (void *) e);
kv.val = e;
m->root = tree_insert(m->root, &kv);
release(&m->lock); release(&m->lock);
return 0; return 0;
} }
static int static int
vmap_copy_vma(struct kv *kv, void *_st) vmap_copy_vma(struct clist_range *r, void *_st)
{ {
struct state *st = (struct state *) _st; struct state *st = (struct state *) _st;
struct vma *e = (struct vma *) kv->val; struct vma *e = (struct vma *) r->value;
struct vma *c = vma_alloc(); struct vma *c = vma_alloc();
if (c == 0) { if (c == 0) {
return 0; return 0;
...@@ -407,10 +409,7 @@ vmap_copy_vma(struct kv *kv, void *_st) ...@@ -407,10 +409,7 @@ vmap_copy_vma(struct kv *kv, void *_st)
return 0; return 0;
} }
__sync_fetch_and_add(&c->n->ref, 1); __sync_fetch_and_add(&c->n->ref, 1);
struct kv kv1; crange_add(st->cr, c->va_start, c->va_end - c->va_start, (void *) c);
kv1.key = c->va_end;
kv1.val = (void *) c;
st->root = tree_insert(st->root, &kv1);
return 1; return 1;
} }
...@@ -425,14 +424,13 @@ vmap_copy(struct vmap *m, int share) ...@@ -425,14 +424,13 @@ vmap_copy(struct vmap *m, int share)
struct state *st = kmalloc(sizeof(struct state)); struct state *st = kmalloc(sizeof(struct state));
st->share = share; st->share = share;
st->pml4 = m->pml4; st->pml4 = m->pml4;
st->root = c->root; st->cr = c->cr;
if (!tree_foreach(m->root, vmap_copy_vma, st)) { if (!crange_foreach(m->cr, vmap_copy_vma, st)) {
vmap_free(c); vmap_free(c);
release(&m->lock); release(&m->lock);
kmfree(st); kmfree(st);
return 0; return 0;
} }
c->root = st->root;
kmfree(st); kmfree(st);
if (share) if (share)
...@@ -447,16 +445,16 @@ vmap_remove(struct vmap *m, uptr va_start, u64 len) ...@@ -447,16 +445,16 @@ vmap_remove(struct vmap *m, uptr va_start, u64 len)
{ {
acquire(&m->lock); acquire(&m->lock);
uptr va_end = va_start + len; uptr va_end = va_start + len;
struct kv *kv = tree_find_gt(m->root, va_start); struct clist_range *r = crange_search(m->cr, va_start);
if (kv == 0) if (r == 0)
panic("no vma?"); panic("no vma?");
struct vma *e = (struct vma *) kv->val; struct vma *e = (struct vma *) r->value;
if(e->va_start != va_start || e->va_end != va_end) { if(e->va_start != va_start || e->va_end != va_end) {
cprintf("vmap_remove: partial unmap unsupported\n"); cprintf("vmap_remove: partial unmap unsupported\n");
release(&m->lock); release(&m->lock);
return -1; return -1;
} }
m->root = tree_remove(m->root, va_start+len); crange_del(m->cr, va_start, len);
gc_delayed(e, vma_free); gc_delayed(e, vma_free);
release(&m->lock); release(&m->lock);
return 0; return 0;
......
...@@ -28,7 +28,8 @@ struct vmnode { ...@@ -28,7 +28,8 @@ struct vmnode {
// The elements of e[] are not ordered by address. // The elements of e[] are not ordered by address.
struct vmap { struct vmap {
#ifdef TREE #ifdef TREE
struct node* root; // struct node* root;
struct crange* cr;
#else #else
struct vma* e[16]; struct vma* e[16];
#endif #endif
......
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论