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

fixes for VERIFYFREE, make proc inherit from rcu_freed

上级 79ba4240
...@@ -6,8 +6,8 @@ using std::atomic; ...@@ -6,8 +6,8 @@ using std::atomic;
struct buf : public rcu_freed { struct buf : public rcu_freed {
atomic<int> flags; atomic<int> flags;
u32 dev; const u32 dev;
u64 sector; const u64 sector;
struct buf *prev; // LRU cache list struct buf *prev; // LRU cache list
struct buf *next; struct buf *next;
struct buf *qnext; // disk queue struct buf *qnext; // disk queue
...@@ -16,7 +16,17 @@ struct buf : public rcu_freed { ...@@ -16,7 +16,17 @@ struct buf : public rcu_freed {
struct spinlock lock; struct spinlock lock;
u8 data[512]; u8 data[512];
buf() : rcu_freed("buf") {} buf(u32 d, u64 s) : rcu_freed("buf"), dev(d), sector(s) {
snprintf(lockname, sizeof(lockname), "cv:buf:%d", sector);
initlock(&lock, lockname+3, LOCKSTAT_BIO);
initcondvar(&cv, lockname);
}
~buf() {
destroycondvar(&cv);
destroylock(&lock);
}
virtual void do_gc() { delete this; } virtual void do_gc() { delete this; }
NEW_DELETE_OPS(buf) NEW_DELETE_OPS(buf)
}; };
......
...@@ -46,6 +46,7 @@ extern u64 ticks; ...@@ -46,6 +46,7 @@ extern u64 ticks;
extern struct spinlock tickslock; extern struct spinlock tickslock;
extern struct condvar cv_ticks; extern struct condvar cv_ticks;
void initcondvar(struct condvar *, const char *); void initcondvar(struct condvar *, const char *);
void destroycondvar(struct condvar *);
void cv_sleep(struct condvar *cv, struct spinlock*); void cv_sleep(struct condvar *cv, struct spinlock*);
void cv_sleepto(struct condvar *cv, struct spinlock*, u64); void cv_sleepto(struct condvar *cv, struct spinlock*, u64);
void cv_wakeup(struct condvar *cv); void cv_wakeup(struct condvar *cv);
......
...@@ -18,7 +18,12 @@ ...@@ -18,7 +18,12 @@
#define NELEM(x) (sizeof(x)/sizeof((x)[0])) #define NELEM(x) (sizeof(x)/sizeof((x)[0]))
#if 0
#define __offsetof offsetof #define __offsetof offsetof
#else
#define __offsetof(type, field) (((uptr) &((type*)0x1000000)->field)-0x1000000)
#endif
#define __mpalign__ __attribute__((aligned(CACHELINE))) #define __mpalign__ __attribute__((aligned(CACHELINE)))
#define __padout__ char __padout[0] __attribute__((aligned(CACHELINE))) #define __padout__ char __padout[0] __attribute__((aligned(CACHELINE)))
#define __noret__ __attribute__((noreturn)) #define __noret__ __attribute__((noreturn))
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#include "spinlock.h" #include "spinlock.h"
#include "atomic.hh" #include "atomic.hh"
#include "cpputil.hh"
// Saved registers for kernel context switches. // Saved registers for kernel context switches.
// (also implicitly defined in swtch.S) // (also implicitly defined in swtch.S)
...@@ -36,7 +37,7 @@ struct mtrace_stacks { ...@@ -36,7 +37,7 @@ struct mtrace_stacks {
enum procstate { UNUSED, EMBRYO, SLEEPING, RUNNABLE, RUNNING, ZOMBIE }; enum procstate { UNUSED, EMBRYO, SLEEPING, RUNNABLE, RUNNING, ZOMBIE };
// Per-process state // Per-process state
struct proc { struct proc : public rcu_freed {
struct vmap *vmap; // va -> vma struct vmap *vmap; // va -> vma
uptr brk; // Top of heap uptr brk; // Top of heap
char *kstack; // Bottom of kernel stack for this process char *kstack; // Bottom of kernel stack for this process
...@@ -73,4 +74,31 @@ struct proc { ...@@ -73,4 +74,31 @@ struct proc {
u64 cv_wakeup; // Wakeup time for this process u64 cv_wakeup; // Wakeup time for this process
LIST_ENTRY(proc) cv_waiters; // Linked list of processes waiting for oncv LIST_ENTRY(proc) cv_waiters; // Linked list of processes waiting for oncv
LIST_ENTRY(proc) cv_sleep; // Linked list of processes sleeping on a cv LIST_ENTRY(proc) cv_sleep; // Linked list of processes sleeping on a cv
proc(int npid) : rcu_freed("proc"), vmap(0), brk(0), kstack(0),
state(EMBRYO), pid(npid), parent(0), tf(0), context(0), killed(0),
cwd(0), tsc(0), curcycles(0), cpuid(0), epoch(0), epoch_depth(0),
on_runq(-1), cpu_pin(0), runq(0), oncv(0), cv_wakeup(0)
{
snprintf(lockname, sizeof(lockname), "cv:proc:%d", pid);
initlock(&lock, lockname+3, LOCKSTAT_PROC);
initlock(&gc_epoch_lock, lockname+3, LOCKSTAT_PROC);
initcondvar(&cv, lockname);
memset(&childq, 0, sizeof(childq));
memset(&child_next, 0, sizeof(child_next));
memset(ofile, 0, sizeof(ofile));
memset(&runqlink, 0, sizeof(runqlink));
memset(&cv_waiters, 0, sizeof(cv_waiters));
memset(&cv_sleep, 0, sizeof(cv_sleep));
}
~proc() {
destroylock(&lock);
destroylock(&gc_epoch_lock);
destroycondvar(&cv);
}
virtual void do_gc() { delete this; }
NEW_DELETE_OPS(proc)
}; };
...@@ -100,20 +100,13 @@ bget(u32 dev, u64 sector, int *writer) ...@@ -100,20 +100,13 @@ bget(u32 dev, u64 sector, int *writer)
victim->flags |= B_BUSY; victim->flags |= B_BUSY;
bufns->remove(mkpair(victim->dev, victim->sector), &victim); bufns->remove(mkpair(victim->dev, victim->sector), &victim);
release(&victim->lock); release(&victim->lock);
destroylock(&victim->lock);
gc_delayed(victim); gc_delayed(victim);
b = new buf(); b = new buf(dev, sector);
b->dev = dev;
b->sector = sector;
b->flags = B_BUSY; b->flags = B_BUSY;
*writer = 1; *writer = 1;
snprintf(b->lockname, sizeof(b->lockname), "cv:buf:%d", b->sector);
initlock(&b->lock, b->lockname+3, LOCKSTAT_BIO);
initcondvar(&b->cv, b->lockname);
gc_begin_epoch(); gc_begin_epoch();
if (bufns->insert(mkpair(b->dev, b->sector), b) < 0) { if (bufns->insert(mkpair(b->dev, b->sector), b) < 0) {
destroylock(&b->lock);
gc_delayed(b); gc_delayed(b);
goto loop; goto loop;
} }
...@@ -169,12 +162,9 @@ initbio(void) ...@@ -169,12 +162,9 @@ initbio(void)
bufns = new xns<pair<u32, u64>, buf*, bio_hash>(false); bufns = new xns<pair<u32, u64>, buf*, bio_hash>(false);
for (u64 i = 0; i < NBUF; i++) { for (u64 i = 0; i < NBUF; i++) {
struct buf *b = new buf(); struct buf *b = new buf(0xdeadbeef, -i);
b->dev = 0xdeadbeef; /* dummy to pre-allocate NBUF spaces for evict */
b->sector = -i; /* dummy to pre-allocate NBUF spaces for evict */
b->flags = 0; b->flags = 0;
initlock(&b->lock, "bcache-lock", LOCKSTAT_BIO);
initcondvar(&b->cv, "bcache-cv");
if (bufns->insert(mkpair(b->dev, b->sector), b) < 0) if (bufns->insert(mkpair(b->dev, b->sector), b) < 0)
panic("binit ns_insert"); panic("binit ns_insert");
} }
......
...@@ -139,3 +139,9 @@ initcondvar(struct condvar *cv, const char *n) ...@@ -139,3 +139,9 @@ initcondvar(struct condvar *cv, const char *n)
initlock(&cv->lock, n, LOCKSTAT_CONDVAR); initlock(&cv->lock, n, LOCKSTAT_CONDVAR);
LIST_INIT(&cv->waiters); LIST_INIT(&cv->waiters);
} }
void
destroycondvar(struct condvar *cv)
{
destroylock(&cv->lock);
}
...@@ -231,6 +231,7 @@ inode::~inode() ...@@ -231,6 +231,7 @@ inode::~inode()
} }
destroylock(&lock); destroylock(&lock);
destroycondvar(&cv);
} }
struct inode* struct inode*
......
...@@ -30,7 +30,7 @@ pipealloc(struct file **f0, struct file **f1) ...@@ -30,7 +30,7 @@ pipealloc(struct file **f0, struct file **f1)
*f0 = *f1 = 0; *f0 = *f1 = 0;
if((*f0 = filealloc()) == 0 || (*f1 = filealloc()) == 0) if((*f0 = filealloc()) == 0 || (*f1 = filealloc()) == 0)
goto bad; goto bad;
if((p = (struct pipe*)kalloc()) == 0) if((p = (pipe*)kmalloc(sizeof(*p))) == 0)
goto bad; goto bad;
p->readopen = 1; p->readopen = 1;
p->writeopen = 1; p->writeopen = 1;
...@@ -52,7 +52,7 @@ pipealloc(struct file **f0, struct file **f1) ...@@ -52,7 +52,7 @@ pipealloc(struct file **f0, struct file **f1)
bad: bad:
if(p) { if(p) {
destroylock(&p->lock); destroylock(&p->lock);
kfree((char*)p); kmfree((char*)p, sizeof(*p));
} }
if(*f0) if(*f0)
fileclose(*f0); fileclose(*f0);
...@@ -74,7 +74,7 @@ pipeclose(struct pipe *p, int writable) ...@@ -74,7 +74,7 @@ pipeclose(struct pipe *p, int writable)
if(p->readopen == 0 && p->writeopen == 0){ if(p->readopen == 0 && p->writeopen == 0){
release(&p->lock); release(&p->lock);
destroylock(&p->lock); destroylock(&p->lock);
kfree((char*)p); kmfree((char*)p, sizeof(*p));
} else } else
release(&p->lock); release(&p->lock);
} }
......
...@@ -177,25 +177,10 @@ exit(void) ...@@ -177,25 +177,10 @@ exit(void)
panic("zombie exit"); panic("zombie exit");
} }
class delayed_proc_free : public rcu_freed {
private:
proc *_p;
public:
delayed_proc_free(proc *p) : rcu_freed("delayed proc free"), _p(p) {}
virtual void do_gc() {
kmfree(_p, sizeof(struct proc));
delete this;
}
NEW_DELETE_OPS(delayed_proc_free)
};
static void static void
freeproc(struct proc *p) freeproc(struct proc *p)
{ {
destroylock(&p->lock); gc_delayed(p);
gc_delayed(new delayed_proc_free(p));
} }
// Look in the process table for an UNUSED proc. // Look in the process table for an UNUSED proc.
...@@ -208,23 +193,15 @@ allocproc(void) ...@@ -208,23 +193,15 @@ allocproc(void)
struct proc *p; struct proc *p;
char *sp; char *sp;
p = (proc*) kmalloc(sizeof(struct proc)); p = new proc(xnspid->allockey());
if (p == 0) return 0; if (p == 0) return 0;
memset(p, 0, sizeof(*p));
p->state = EMBRYO;
p->pid = xnspid->allockey();
p->cpuid = mycpu()->id; p->cpuid = mycpu()->id;
p->on_runq = -1;
p->cpu_pin = 0;
initprocgc(p); initprocgc(p);
#if MTRACE #if MTRACE
p->mtrace_stacks.curr = -1; p->mtrace_stacks.curr = -1;
#endif #endif
snprintf(p->lockname, sizeof(p->lockname), "cv:proc:%d", p->pid);
initlock(&p->lock, p->lockname+3, LOCKSTAT_PROC);
initcondvar(&p->cv, p->lockname);
initcilkframe(&p->cilkframe); initcilkframe(&p->cilkframe);
if (xnspid->insert(p->pid, p) < 0) if (xnspid->insert(p->pid, p) < 0)
......
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论