提交 6d8e14b0 创建 作者: Nickolai Zeldovich's avatar Nickolai Zeldovich

avoid bucket locks; do locking per element

上级 796f5c48
...@@ -15,11 +15,11 @@ ...@@ -15,11 +15,11 @@
struct elem { struct elem {
int key; int key;
void *val; void *val;
int next_lock;
struct elem * volatile next; struct elem * volatile next;
}; };
struct bucket { struct bucket {
struct spinlock l;
struct elem * volatile chain; struct elem * volatile chain;
} __attribute__((aligned (CACHELINE))); } __attribute__((aligned (CACHELINE)));
...@@ -44,8 +44,6 @@ nsalloc(void) ...@@ -44,8 +44,6 @@ nsalloc(void)
if (ns == 0) if (ns == 0)
panic("nsalloc"); panic("nsalloc");
memset(ns, 0, sizeof(struct ns)); memset(ns, 0, sizeof(struct ns));
for (int i = 0; i < NHASH; i++)
initlock(&ns->table[i].l, "bucket");
ns->nextkey = 1; ns->nextkey = 1;
return ns; return ns;
} }
...@@ -114,8 +112,13 @@ int ...@@ -114,8 +112,13 @@ int
ns_remove(struct ns *ns, int key, void *v) ns_remove(struct ns *ns, int key, void *v)
{ {
uint i = key % NHASH; uint i = key % NHASH;
rcu_begin_write(&ns->table[i].l); rcu_begin_write(0);
retry:
(void) 0;
int fakelock = 0;
int *pelock = &fakelock;
struct elem * volatile * pe = &ns->table[i].chain; struct elem * volatile * pe = &ns->table[i].chain;
for (;;) { for (;;) {
struct elem *e = *pe; struct elem *e = *pe;
...@@ -123,10 +126,20 @@ ns_remove(struct ns *ns, int key, void *v) ...@@ -123,10 +126,20 @@ ns_remove(struct ns *ns, int key, void *v)
break; break;
if (e->key == key && (e->val == v || v == 0)) { if (e->key == key && (e->val == v || v == 0)) {
for (;;) if (!__sync_bool_compare_and_swap(&e->next_lock, 0, 1))
if (__sync_bool_compare_and_swap(pe, e, e->next)) goto retry;
break; if (!__sync_bool_compare_and_swap(pelock, 0, 1)) {
rcu_end_write(&ns->table[i].l); e->next_lock = 0;
goto retry;
}
if (!__sync_bool_compare_and_swap(pe, e, e->next)) {
*pelock = 0;
e->next_lock = 0;
goto retry;
}
*pelock = 0;
rcu_end_write(0);
rcu_delayed(e, kmfree); rcu_delayed(e, kmfree);
return 0; return 0;
} }
...@@ -134,7 +147,7 @@ ns_remove(struct ns *ns, int key, void *v) ...@@ -134,7 +147,7 @@ ns_remove(struct ns *ns, int key, void *v)
pe = &e->next; pe = &e->next;
} }
rcu_end_write(&ns->table[i].l); rcu_end_write(0);
return -1; return -1;
} }
......
...@@ -68,7 +68,8 @@ allocproc(void) ...@@ -68,7 +68,8 @@ allocproc(void)
// Allocate kernel stack if possible. // Allocate kernel stack if possible.
if((p->kstack = kalloc()) == 0){ if((p->kstack = kalloc()) == 0){
ns_remove(nspid, p->pid, p); if (ns_remove(nspid, p->pid, p) < 0)
panic("allocproc: ns_remove");
rcu_delayed(p, kmfree); rcu_delayed(p, kmfree);
return 0; return 0;
} }
...@@ -122,7 +123,8 @@ delrun(struct proc *p) ...@@ -122,7 +123,8 @@ delrun(struct proc *p)
if (p->on_runq < 0) if (p->on_runq < 0)
panic("delrun not on runq"); panic("delrun not on runq");
ns_remove(nsrunq, p->on_runq, p); if (ns_remove(nsrunq, p->on_runq, p) < 0)
panic("delrun: ns_remove");
p->on_runq = -1; p->on_runq = -1;
} }
...@@ -267,7 +269,8 @@ fork(int flags) ...@@ -267,7 +269,8 @@ fork(int flags)
kfree(np->kstack); kfree(np->kstack);
np->kstack = 0; np->kstack = 0;
np->state = UNUSED; np->state = UNUSED;
ns_remove(nspid, np->pid, np); if (ns_remove(nspid, np->pid, np) < 0)
panic("fork: ns_remove");
rcu_delayed(np, kmfree); rcu_delayed(np, kmfree);
return -1; return -1;
} }
......
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论