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

rcu-free disk blocks, for lock-free exec

上级 d564ca3d
...@@ -143,6 +143,7 @@ void rcu_end_write(struct spinlock *); ...@@ -143,6 +143,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_delayed2(int, uint, void (*dofree)(int, uint));
void rcu_gc(void); void rcu_gc(void);
// swtch.S // swtch.S
......
...@@ -28,7 +28,8 @@ exec(char *path, char **argv) ...@@ -28,7 +28,8 @@ exec(char *path, char **argv)
if((ip = namei(path)) == 0) if((ip = namei(path)) == 0)
return -1; return -1;
ilock(ip, 0); // ilock(ip, 0);
rcu_begin_read();
// Check ELF header // Check ELF header
if(ip->type != T_FILE) if(ip->type != T_FILE)
...@@ -73,10 +74,11 @@ exec(char *path, char **argv) ...@@ -73,10 +74,11 @@ exec(char *path, char **argv)
goto bad; goto bad;
vmn = 0; vmn = 0;
} }
if (odp) if (odp) {
iunlock(ip); // iunlock(ip);
else { } else {
iunlockput(ip); // iunlockput(ip);
iput(ip);
ip = 0; ip = 0;
} }
...@@ -133,15 +135,17 @@ exec(char *path, char **argv) ...@@ -133,15 +135,17 @@ exec(char *path, char **argv)
migrate(proc); migrate(proc);
rcu_end_read();
return 0; return 0;
bad: bad:
cprintf("exec failed\n"); cprintf("exec failed\n");
if(ip) // if(ip)
iunlockput(ip); // iunlockput(ip);
if(vmap) if(vmap)
vmap_decref(vmap); vmap_decref(vmap);
if(vmn) if(vmn)
vmn_free(vmn); vmn_free(vmn);
rcu_end_read();
return -1; return -1;
} }
...@@ -419,7 +419,7 @@ itrunc(struct inode *ip) ...@@ -419,7 +419,7 @@ itrunc(struct inode *ip)
for(i = 0; i < NDIRECT; i++){ for(i = 0; i < NDIRECT; i++){
if(ip->addrs[i]){ if(ip->addrs[i]){
bfree(ip->dev, ip->addrs[i]); rcu_delayed2(ip->dev, ip->addrs[i], bfree);
ip->addrs[i] = 0; ip->addrs[i] = 0;
} }
} }
...@@ -429,10 +429,10 @@ itrunc(struct inode *ip) ...@@ -429,10 +429,10 @@ itrunc(struct inode *ip)
a = (uint*)bp->data; a = (uint*)bp->data;
for(j = 0; j < NINDIRECT; j++){ for(j = 0; j < NINDIRECT; j++){
if(a[j]) if(a[j])
bfree(ip->dev, a[j]); rcu_delayed2(ip->dev, a[j], bfree);
} }
brelse(bp, 0); brelse(bp, 0);
bfree(ip->dev, ip->addrs[NDIRECT]); rcu_delayed2(ip->dev, ip->addrs[NDIRECT], bfree);
ip->addrs[NDIRECT] = 0; ip->addrs[NDIRECT] = 0;
} }
......
...@@ -9,10 +9,21 @@ ...@@ -9,10 +9,21 @@
#include "proc.h" #include "proc.h"
struct rcu { struct rcu {
void *item;
unsigned long epoch; unsigned long epoch;
struct rcu *next; struct rcu *next;
void (*dofree)(void *); union {
struct {
void (*dofree)(void *);
void *item;
} f1;
struct {
void (*dofree)(int, uint);
int arg1;
uint arg2;
} f2;
} u;
int type;
}; };
static struct { struct rcu *x __attribute__((aligned (CACHELINE))); } rcu_delayed_head[NCPU]; static struct { struct rcu *x __attribute__((aligned (CACHELINE))); } rcu_delayed_head[NCPU];
static struct { struct rcu *x __attribute__((aligned (CACHELINE))); } rcu_delayed_tail[NCPU]; static struct { struct rcu *x __attribute__((aligned (CACHELINE))); } rcu_delayed_tail[NCPU];
...@@ -63,9 +74,16 @@ rcu_gc(void) ...@@ -63,9 +74,16 @@ rcu_gc(void)
if (r->epoch >= min_epoch[cpu->id].x) if (r->epoch >= min_epoch[cpu->id].x)
break; break;
// cprintf("free: %d (%x %x)\n", r->epoch, r->dofree, r->item); // cprintf("free: %d (%x %x)\n", r->epoch, r->dofree, r->item);
if (r->dofree == 0) switch (r->type) {
panic("rcu_gc"); case 1:
r->dofree(r->item); r->u.f1.dofree(r->u.f1.item);
break;
case 2:
r->u.f2.dofree(r->u.f2.arg1, r->u.f2.arg2);
break;
default:
panic("rcu type");
}
delayed_nfree[cpu->id].v--; delayed_nfree[cpu->id].v--;
n++; n++;
rcu_delayed_head[cpu->id].x = r->next; rcu_delayed_head[cpu->id].x = r->next;
...@@ -84,34 +102,56 @@ rcu_gc(void) ...@@ -84,34 +102,56 @@ rcu_gc(void)
} }
// XXX Use atomic instruction to update list (instead of holding lock) // XXX Use atomic instruction to update list (instead of holding lock)
static void
rcu_delayed_int(struct rcu *r)
{
pushcli();
acquire(&rcu_lock[cpu->id].l);
// cprintf("rcu_delayed: %d\n", global_epoch);
if (rcu_delayed_tail[cpu->id].x != 0)
rcu_delayed_tail[cpu->id].x->next = r;
rcu_delayed_tail[cpu->id].x = r;
if (rcu_delayed_head[cpu->id].x == 0)
rcu_delayed_head[cpu->id].x = r;
release(&rcu_lock[cpu->id].l);
delayed_nfree[cpu->id].v++;
popcli();
}
void void
rcu_delayed(void *e, void (*dofree)(void *)) rcu_delayed(void *e, void (*dofree)(void *))
{ {
if (rcu_debug) { if (rcu_debug) {
cprintf("rcu_delayed: %x %x\n", dofree, e); cprintf("rcu_delayed: %x %x\n", dofree, e);
for (struct rcu *r = rcu_delayed_head[cpu->id].x; r; r = r->next) for (struct rcu *r = rcu_delayed_head[cpu->id].x; r; r = r->next)
if (r->item == e && r->dofree == dofree) if (r->u.f1.item == e && r->u.f1.dofree == dofree)
panic("rcu_delayed double free"); panic("rcu_delayed double free");
} }
struct rcu *r = rcu_alloc(); struct rcu *r = rcu_alloc();
if (r == 0) if (r == 0)
panic("rcu_delayed"); panic("rcu_delayed");
r->dofree = dofree; r->u.f1.dofree = dofree;
r->item = e; r->u.f1.item = e;
r->next = 0; r->next = 0;
r->epoch = global_epoch; r->epoch = global_epoch;
pushcli(); r->type = 1;
acquire(&rcu_lock[cpu->id].l); rcu_delayed_int(r);
// cprintf("rcu_delayed: %d\n", global_epoch); }
if (rcu_delayed_tail[cpu->id].x != 0)
rcu_delayed_tail[cpu->id].x->next = r; void
rcu_delayed_tail[cpu->id].x = r; rcu_delayed2(int a1, uint a2, void (*dofree)(int,uint))
if (rcu_delayed_head[cpu->id].x == 0) {
rcu_delayed_head[cpu->id].x = r; struct rcu *r = rcu_alloc();
release(&rcu_lock[cpu->id].l); if (r == 0)
delayed_nfree[cpu->id].v++; panic("rcu_delayed");
popcli(); r->u.f2.dofree = dofree;
r->u.f2.arg1 = a1;
r->u.f2.arg2 = a2;
r->next = 0;
r->epoch = global_epoch;
r->type = 2;
rcu_delayed_int(r);
} }
void void
......
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论