提交 1db560a8 创建 作者: Nickolai Zeldovich's avatar Nickolai Zeldovich

per-core periodic rcu_gc and gc lists

上级 446cb46d
...@@ -142,6 +142,7 @@ void rcu_end_write(struct spinlock *); ...@@ -142,6 +142,7 @@ void rcu_end_write(struct spinlock *);
void rcu_begin_read(void); void rcu_begin_read(void);
void rcu_end_read(void); void rcu_end_read(void);
void rcu_delayed(void*, void (*dofree)(void*)); void rcu_delayed(void*, void (*dofree)(void*));
void rcu_gc(void);
// swtch.S // swtch.S
void swtch(struct context**, struct context*); void swtch(struct context**, struct context*);
......
...@@ -545,6 +545,12 @@ scheduler(void) ...@@ -545,6 +545,12 @@ scheduler(void)
} }
if (idle[cpu->id]) { if (idle[cpu->id]) {
int now = ticks;
if (now - cpu->last_rcu_gc_ticks > 100) {
rcu_gc();
cpu->last_rcu_gc_ticks = now;
}
sti(); sti();
hlt(); hlt();
} }
......
...@@ -109,6 +109,7 @@ struct cpu { ...@@ -109,6 +109,7 @@ struct cpu {
volatile uint booted; // Has the CPU started? volatile uint booted; // Has the CPU started?
int ncli; // Depth of pushcli nesting. int ncli; // Depth of pushcli nesting.
int intena; // Were interrupts enabled before pushcli? int intena; // Were interrupts enabled before pushcli?
int last_rcu_gc_ticks;
// Cpu-local storage variables; see below // Cpu-local storage variables; see below
struct cpu *cpu; struct cpu *cpu;
......
...@@ -8,17 +8,14 @@ ...@@ -8,17 +8,14 @@
#include "queue.h" #include "queue.h"
#include "proc.h" #include "proc.h"
#define NRCU 1000
struct rcu { struct rcu {
void *item; void *item;
unsigned long epoch; unsigned long epoch;
struct rcu *rcu; struct rcu *rcu;
void (*dofree)(void *); void (*dofree)(void *);
}; };
static struct rcu *rcu_delayed_head __attribute__ ((aligned (CACHELINE))); static struct rcu *rcu_delayed_head[NCPU] __attribute__ ((aligned (CACHELINE)));
static struct rcu *rcu_delayed_tail __attribute__ ((aligned (CACHELINE))); static struct rcu *rcu_delayed_tail[NCPU] __attribute__ ((aligned (CACHELINE)));
static struct rcu *rcu_freelist __attribute__ ((aligned (CACHELINE)));
static uint global_epoch __attribute__ ((aligned (CACHELINE))); static uint global_epoch __attribute__ ((aligned (CACHELINE)));
static uint min_epoch __attribute__ ((aligned (CACHELINE))); static uint min_epoch __attribute__ ((aligned (CACHELINE)));
static struct spinlock rcu_lock __attribute__ ((aligned (CACHELINE))); static struct spinlock rcu_lock __attribute__ ((aligned (CACHELINE)));
...@@ -27,28 +24,13 @@ static int delayed_nfree __attribute__ ((aligned (CACHELINE))); ...@@ -27,28 +24,13 @@ static int delayed_nfree __attribute__ ((aligned (CACHELINE)));
void void
rcuinit(void) rcuinit(void)
{ {
struct rcu *r;
int i;
initlock(&rcu_lock, "rcu"); initlock(&rcu_lock, "rcu");
for (i = 0; i < NRCU; i++) {
r = (struct rcu *) kmalloc(sizeof(struct rcu));
memset(r, 0, sizeof(struct rcu));
r->rcu = rcu_freelist;
rcu_freelist = r;
}
// cprintf("rcu_init: allocated %d bytes\n", sizeof(struct rcu) * NRCU);
} }
struct rcu * struct rcu *
rcu_alloc() rcu_alloc()
{ {
struct rcu *r = rcu_freelist; return kmalloc(sizeof(struct rcu));
if (r == 0) {
panic("rcu_alloc");
}
rcu_freelist = r->rcu;
return r;
} }
void void
...@@ -71,7 +53,7 @@ rcu_gc(void) ...@@ -71,7 +53,7 @@ rcu_gc(void)
ns_enumerate(nspid, rcu_min); ns_enumerate(nspid, rcu_min);
acquire(&rcu_lock); acquire(&rcu_lock);
for (r = rcu_delayed_head; r != NULL; r = nr) { for (r = rcu_delayed_head[cpu->id]; r != NULL; r = nr) {
if (r->epoch >= min_epoch) if (r->epoch >= min_epoch)
break; break;
// cprintf("free: %d\n", r->epoch); // cprintf("free: %d\n", r->epoch);
...@@ -80,12 +62,11 @@ rcu_gc(void) ...@@ -80,12 +62,11 @@ rcu_gc(void)
r->dofree(r->item); r->dofree(r->item);
delayed_nfree--; delayed_nfree--;
n++; n++;
rcu_delayed_head = r->rcu; rcu_delayed_head[cpu->id] = r->rcu;
if (rcu_delayed_head == 0) if (rcu_delayed_head[cpu->id] == 0)
rcu_delayed_tail = 0; rcu_delayed_tail[cpu->id] = 0;
nr = r->rcu; nr = r->rcu;
r->rcu = rcu_freelist; kmfree(r);
rcu_freelist = r;
} }
release(&rcu_lock); release(&rcu_lock);
// cprintf("rcu_gc: n %d ndelayed_free=%d\n", n, delayed_nfree); // cprintf("rcu_gc: n %d ndelayed_free=%d\n", n, delayed_nfree);
...@@ -104,10 +85,11 @@ rcu_delayed(void *e, void (*dofree)(void *)) ...@@ -104,10 +85,11 @@ rcu_delayed(void *e, void (*dofree)(void *))
r->epoch = global_epoch; r->epoch = global_epoch;
acquire(&rcu_lock); acquire(&rcu_lock);
// cprintf("rcu_delayed: %d\n", global_epoch); // cprintf("rcu_delayed: %d\n", global_epoch);
if (rcu_delayed_tail != 0) if (rcu_delayed_tail[cpu->id] != 0)
rcu_delayed_tail->rcu = r; rcu_delayed_tail[cpu->id]->rcu = r;
rcu_delayed_tail = r; rcu_delayed_tail[cpu->id] = r;
if (rcu_delayed_head == 0) rcu_delayed_head = r; if (rcu_delayed_head[cpu->id] == 0)
rcu_delayed_head[cpu->id] = r;
release(&rcu_lock); release(&rcu_lock);
delayed_nfree++; delayed_nfree++;
} }
...@@ -139,6 +121,6 @@ rcu_end_write(struct spinlock *l) ...@@ -139,6 +121,6 @@ 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); release(l);
rcu_gc(); // rcu_gc();
} }
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论