提交 374fe0a0 创建 作者: Frans Kaashoek's avatar Frans Kaashoek

checkpoint some RCU changes

上级 6600eed0
...@@ -134,6 +134,8 @@ void migrate(void); ...@@ -134,6 +134,8 @@ void migrate(void);
// rcu.c // rcu.c
void rcuinit(void); void rcuinit(void);
void rcu_begin_write(struct spinlock *);
void rcu_end_write(struct spinlock *);
// swtch.S // swtch.S
void swtch(struct context**, struct context*); void swtch(struct context**, struct context*);
......
...@@ -50,8 +50,8 @@ mainc(void) ...@@ -50,8 +50,8 @@ mainc(void)
consoleinit(); // I/O devices & their interrupts consoleinit(); // I/O devices & their interrupts
uartinit(); // serial port uartinit(); // serial port
kvmalloc(); // initialize the kernel page table kvmalloc(); // initialize the kernel page table
nsinit(); // initialize name space module
rcuinit(); // initialize rcu module rcuinit(); // initialize rcu module
nsinit(); // initialize name space module
pinit(); // process table pinit(); // process table
tvinit(); // trap vectors tvinit(); // trap vectors
binit(); // buffer cache binit(); // buffer cache
......
...@@ -4,8 +4,13 @@ ...@@ -4,8 +4,13 @@
#include "queue.h" #include "queue.h"
// name spaces // name spaces
// XXX maybe use open hash table, no chain, better cache locality
#define NHASH 100 #define NHASH 100
static int rcu = 0;
#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 {
...@@ -39,11 +44,12 @@ nsalloc(void) ...@@ -39,11 +44,12 @@ nsalloc(void)
{ {
struct ns *ns = 0; struct ns *ns = 0;
acquire(&ns_lock);
ns = kmalloc(sizeof(struct ns)); ns = kmalloc(sizeof(struct ns));
if (ns == 0) if (ns == 0)
panic("nsalloc"); panic("nsalloc");
memset(ns, 0, sizeof(struct ns)); memset(ns, 0, sizeof(struct ns));
acquire(&ns_lock);
for (int i = 0; i < NHASH; i++) { for (int i = 0; i < NHASH; i++) {
TAILQ_INIT(&ns->table[i].chain); TAILQ_INIT(&ns->table[i].chain);
} }
...@@ -74,7 +80,7 @@ int ...@@ -74,7 +80,7 @@ int
ns_insert(struct ns *ns, int key, void *val) ns_insert(struct ns *ns, int key, void *val)
{ {
int r = -1; int r = -1;
acquire(&ns->lock); ACQUIRE(&ns->lock);
struct elem *e = elemalloc(); struct elem *e = elemalloc();
if (e) { if (e) {
e->key = key; e->key = key;
...@@ -83,7 +89,7 @@ ns_insert(struct ns *ns, int key, void *val) ...@@ -83,7 +89,7 @@ ns_insert(struct ns *ns, int key, void *val)
TAILQ_INSERT_TAIL(&(ns->table[i].chain), e, chain); TAILQ_INSERT_TAIL(&(ns->table[i].chain), e, chain);
r = 0; r = 0;
} }
release(&ns->lock); RELEASE(&ns->lock);
return r; return r;
} }
...@@ -103,9 +109,9 @@ ns_dolookup(struct ns *ns, int key) ...@@ -103,9 +109,9 @@ ns_dolookup(struct ns *ns, int key)
void* void*
ns_lookup(struct ns *ns, int key) ns_lookup(struct ns *ns, int key)
{ {
acquire(&ns->lock); ACQUIRE(&ns->lock);
struct elem *e = ns_dolookup(ns, key); struct elem *e = ns_dolookup(ns, key);
release(&ns->lock); RELEASE(&ns->lock);
return (e == 0)? 0 : e->val; return (e == 0)? 0 : e->val;
} }
...@@ -113,14 +119,14 @@ int ...@@ -113,14 +119,14 @@ int
ns_remove(struct ns *ns, int key) ns_remove(struct ns *ns, int key)
{ {
int r = -1; int r = -1;
acquire(&ns->lock); ACQUIRE(&ns->lock);
struct elem *e = ns_dolookup(ns, key); struct elem *e = ns_dolookup(ns, key);
if (e) { if (e) {
TAILQ_REMOVE(&(ns->table[key % NHASH].chain), e, chain); TAILQ_REMOVE(&(ns->table[key % NHASH].chain), e, chain);
kmfree(e); kmfree(e);
r = 0; r = 0;
} }
release(&ns->lock); RELEASE(&ns->lock);
return r; return r;
} }
......
...@@ -10,8 +10,6 @@ ...@@ -10,8 +10,6 @@
#define NRCU 1000 #define NRCU 1000
#define NDELAY 500
struct rcu { struct rcu {
void *item; void *item;
unsigned long epoch; unsigned long epoch;
...@@ -37,10 +35,11 @@ rcuinit(void) ...@@ -37,10 +35,11 @@ rcuinit(void)
initlock(&rcu_lock, "rcu"); initlock(&rcu_lock, "rcu");
for (i = 0; i < NRCU; i++) { for (i = 0; i < NRCU; i++) {
r = (struct rcu *) kmalloc(sizeof(struct rcu)); r = (struct rcu *) kmalloc(sizeof(struct rcu));
memset(r, 0, sizeof(struct rcu));
r->rcu = rcu_freelist; r->rcu = rcu_freelist;
rcu_freelist = r; rcu_freelist = r;
} }
cprintf("rcu_init: allocated %ld bytes\n", sizeof(struct rcu) * NRCU); cprintf("rcu_init: allocated %d bytes\n", sizeof(struct rcu) * NRCU);
} }
struct rcu * struct rcu *
...@@ -71,7 +70,11 @@ rcu_gc(void) ...@@ -71,7 +70,11 @@ rcu_gc(void)
int n = 0; int n = 0;
min_epoch = global_epoch; min_epoch = global_epoch;
acquire(&rcu_lock);
ns_enumerate(nspid, rcu_min); ns_enumerate(nspid, rcu_min);
for (r = rcu_delayed_head; r != NULL; r = nr) { for (r = rcu_delayed_head; r != NULL; r = nr) {
if (r->epoch >= min_epoch) if (r->epoch >= min_epoch)
break; break;
...@@ -93,6 +96,7 @@ rcu_gc(void) ...@@ -93,6 +96,7 @@ rcu_gc(void)
r->rcu = rcu_freelist; r->rcu = rcu_freelist;
rcu_freelist = r; rcu_freelist = r;
} }
release(&rcu_lock);
// printf("rcu_gc: n=%d ndelayed_free=%d nfree=%d ninuse=%d\n", n, delayed_nfree, // printf("rcu_gc: n=%d ndelayed_free=%d nfree=%d ninuse=%d\n", n, delayed_nfree,
// tree_nfree, tree_ninuse); // tree_nfree, tree_ninuse);
} }
...@@ -108,40 +112,42 @@ rcu_delayed(void *e, void (*dofree)(void *)) ...@@ -108,40 +112,42 @@ rcu_delayed(void *e, void (*dofree)(void *))
r->item = e; r->item = e;
r->rcu = 0; r->rcu = 0;
r->epoch = global_epoch; r->epoch = global_epoch;
acquire(&rcu_lock);
// printf("rcu_delayed: %ld\n", global_epoch); // printf("rcu_delayed: %ld\n", global_epoch);
if (rcu_delayed_tail != 0) if (rcu_delayed_tail != 0)
rcu_delayed_tail->rcu = r; rcu_delayed_tail->rcu = r;
rcu_delayed_tail = r; rcu_delayed_tail = r;
if (rcu_delayed_head == 0) rcu_delayed_head = r; if (rcu_delayed_head == 0) rcu_delayed_head = r;
release(&rcu_lock);
delayed_nfree++; delayed_nfree++;
ninuse--; ninuse--;
} }
void void
rcu_begin_read(int tid) rcu_begin_read()
{ {
proc->epoch = global_epoch; proc->epoch = global_epoch;
__sync_synchronize(); __sync_synchronize();
} }
void void
rcu_end_read(int tid) rcu_end_read()
{ {
proc->epoch = INF; proc->epoch = INF;
} }
void void
rcu_begin_write(int tid) rcu_begin_write(struct spinlock *l)
{ {
acquire(&rcu_lock); acquire(l);
} }
void void
rcu_end_write(int tid) rcu_end_write(struct spinlock *l)
{ {
// for other data structures using rcu, use atomic add: // for other data structures using rcu, use atomic add:
__sync_fetch_and_add(&global_epoch, 1); __sync_fetch_and_add(&global_epoch, 1);
release(l);
rcu_gc(); rcu_gc();
release(&rcu_lock);
} }
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论