提交 71c12c3a 创建 作者: Nickolai Zeldovich's avatar Nickolai Zeldovich

some ns/rcu cleanup

上级 e6958239
#include "types.h" #include "types.h"
#include "defs.h" #include "defs.h"
#include "spinlock.h" #include "spinlock.h"
#include "queue.h"
// name spaces // name spaces
// XXX maybe use open hash table, no chain, better cache locality // XXX maybe use open hash table, no chain, better cache locality
#define NHASH 100 #define NHASH 100
static int rcu = 1;
#define ACQUIRE(l) (rcu) ? rcu_begin_write(l) : acquire(l)
#define RELEASE(l) (rcu) ? rcu_end_write(l) : release(l)
// XXX cache align // XXX cache align
struct elem { struct elem {
int key; int key;
void *val; void *val;
TAILQ_ENTRY(elem) chain; struct elem * volatile next;
}; };
struct bucket { struct bucket {
TAILQ_HEAD(elist, elem) chain; struct spinlock l;
struct elem * volatile chain;
}; };
struct ns { struct ns {
int used; int used;
int nextkey; int nextkey;
struct bucket table[NHASH]; struct bucket table[NHASH];
struct spinlock lock;
char name[16];
}; };
void void
...@@ -46,12 +40,9 @@ nsalloc(void) ...@@ -46,12 +40,9 @@ nsalloc(void)
if (ns == 0) if (ns == 0)
panic("nsalloc"); panic("nsalloc");
memset(ns, 0, sizeof(struct ns)); memset(ns, 0, sizeof(struct ns));
snprintf(ns->name, sizeof(ns->name), "ns:%x", ns);
initlock(&ns->lock, ns->name);
ns->nextkey = 1;
for (int i = 0; i < NHASH; i++) for (int i = 0; i < NHASH; i++)
TAILQ_INIT(&ns->table[i].chain); initlock(&ns->table[i].l, "bucket");
ns->nextkey = 1;
return ns; return ns;
} }
...@@ -83,69 +74,77 @@ ns_insert(struct ns *ns, int key, void *val) ...@@ -83,69 +74,77 @@ ns_insert(struct ns *ns, int key, void *val)
e->key = key; e->key = key;
e->val = val; e->val = val;
uint i = key % NHASH; uint i = key % NHASH;
ACQUIRE(&ns->lock); rcu_begin_write(0);
TAILQ_INSERT_TAIL(&(ns->table[i].chain), e, chain); for (;;) {
RELEASE(&ns->lock); struct elem *x = ns->table[i].chain;
e->next = x;
if (__sync_bool_compare_and_swap(&ns->table[i].chain, x, e))
break;
}
rcu_end_write(0);
r = 0; r = 0;
} }
return r; return r;
} }
static struct elem* void*
ns_dolookup(struct ns *ns, int key) ns_lookup(struct ns *ns, int key)
{ {
struct elem *e = TAILQ_FIRST(&(ns->table[key % NHASH].chain)); uint i = key % NHASH;
rcu_begin_read();
struct elem *e = ns->table[i].chain;
while (e != NULL) { while (e != NULL) {
if (e->key == key) { if (e->key == key) {
return e; return e;
} }
e = TAILQ_NEXT(e, chain); e = e->next;
} }
rcu_end_read();
return 0; return 0;
} }
void* int
ns_lookup(struct ns *ns, int key) ns_remove(struct ns *ns, int key)
{ {
if (rcu) rcu_begin_read(); uint i = key % NHASH;
else acquire(&ns->lock); rcu_begin_write(&ns->table[i].l);
struct elem *e = ns_dolookup(ns, key); struct elem * volatile * pe = &ns->table[i].chain;
for (;;) {
struct elem *e = *pe;
if (!e)
break;
if (rcu) rcu_begin_read(); if (e->key == key) {
else release(&ns->lock); for (;;)
if (__sync_bool_compare_and_swap(pe, e, e->next))
return (e == 0)? 0 : e->val; break;
} rcu_end_write(&ns->table[i].l);
rcu_delayed(e, kmfree);
return 0;
}
int pe = &e->next;
ns_remove(struct ns *ns, int key)
{
int r = -1;
ACQUIRE(&ns->lock);
struct elem *e = ns_dolookup(ns, key);
if (e) {
TAILQ_REMOVE(&(ns->table[key % NHASH].chain), e, chain);
RELEASE(&ns->lock);
if (rcu) rcu_delayed(e, kmfree);
else kmfree(e);
r = 0;
} else {
RELEASE(&ns->lock);
} }
return r;
rcu_end_write(&ns->table[i].l);
return -1;
} }
void void
ns_enumerate(struct ns *ns, void (*f)(int, void *)) ns_enumerate(struct ns *ns, void (*f)(int, void *))
{ {
acquire(&ns->lock); rcu_begin_read();
for (int i = 0; i < NHASH; i++) { for (int i = 0; i < NHASH; i++) {
struct elem *e = TAILQ_FIRST(&(ns->table[i].chain)); struct elem *e = ns->table[i].chain;
while (e != NULL) { while (e != NULL) {
(*f)(e->key, e->val); (*f)(e->key, e->val);
e = TAILQ_NEXT(e, chain); e = e->next;
} }
} }
release(&ns->lock); rcu_end_read();
} }
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论