提交 8cb44655 创建 作者: Robert Morris's avatar Robert Morris

remove p->lock from addrun/delrun; caller must acquire

上级 5f3d853d
...@@ -247,6 +247,9 @@ qemu-nox-gdb: fs.img xv6.img .gdbinit ...@@ -247,6 +247,9 @@ qemu-nox-gdb: fs.img xv6.img .gdbinit
@echo "*** Now run 'gdb'." 1>&2 @echo "*** Now run 'gdb'." 1>&2
$(QEMU) -nographic $(QEMUOPTS) -S $(QEMUGDB) $(QEMU) -nographic $(QEMUOPTS) -S $(QEMUGDB)
mtrace-nox-gdb: fs.img xv6.img mscan.syms mscan.kern .gdbinit
$(MTRACE) -nographic $(QEMUOPTS) $(MTRACEOPTS) -S -gdb tcp::$(GDBPORT)
# CUT HERE # CUT HERE
# prepare dist for students # prepare dist for students
# after running make dist, probably want to # after running make dist, probably want to
......
...@@ -55,12 +55,14 @@ cv_wakeup(struct condvar *cv) ...@@ -55,12 +55,14 @@ cv_wakeup(struct condvar *cv)
acquire(&cv->lock); acquire(&cv->lock);
while(cv->waiters) { while(cv->waiters) {
struct proc *p = cv->waiters; struct proc *p = cv->waiters;
acquire(&p->lock);
if(p->state != SLEEPING || p->oncv != cv) if(p->state != SLEEPING || p->oncv != cv)
panic("cv_wakeup"); panic("cv_wakeup");
struct proc *nxt = p->cv_next; struct proc *nxt = p->cv_next;
p->cv_next = 0; p->cv_next = 0;
p->oncv = 0; p->oncv = 0;
addrun(p); addrun(p);
release(&p->lock);
cv->waiters = nxt; cv->waiters = nxt;
} }
release(&cv->lock); release(&cv->lock);
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "condvar.h" #include "condvar.h"
#include "fs.h" #include "fs.h"
#include "file.h" #include "file.h"
#include "stat.h"
struct devsw devsw[NDEV]; struct devsw devsw[NDEV];
struct { struct {
...@@ -117,6 +118,8 @@ filewrite(struct file *f, char *addr, int n) ...@@ -117,6 +118,8 @@ filewrite(struct file *f, char *addr, int n)
return pipewrite(f->pipe, addr, n); return pipewrite(f->pipe, addr, n);
if(f->type == FD_INODE){ if(f->type == FD_INODE){
ilock(f->ip); ilock(f->ip);
if(f->ip->type == 0 || f->ip->type == T_DIR)
panic("filewrite but 0 or T_DIR");
if((r = writei(f->ip, addr, f->off, n)) > 0) if((r = writei(f->ip, addr, f->off, n)) > 0)
f->off += r; f->off += r;
iunlock(f->ip); iunlock(f->ip);
......
...@@ -585,9 +585,6 @@ namex(char *path, int nameiparent, char *name) ...@@ -585,9 +585,6 @@ namex(char *path, int nameiparent, char *name)
ip = idup(proc->cwd); ip = idup(proc->cwd);
while((path = skipelem(path, name)) != 0){ while((path = skipelem(path, name)) != 0){
// XXX do we need to ilock(ip)?
// hopefully not, would be nice to have
// lock-free namecache hits.
next = 0; next = 0;
if(nameiparent == 0) if(nameiparent == 0)
next = nc_lookup(ip, name); next = nc_lookup(ip, name);
......
...@@ -3,10 +3,12 @@ ...@@ -3,10 +3,12 @@
// //
// to do: // to do:
// use ns.c namespaces // use ns.c namespaces
// invalidation (for rename, unlink) // does directory inum need to be locked around ns_lookup?
// does directory inum need to be locked?
// need a lock to make table lookup and iget atomic? // need a lock to make table lookup and iget atomic?
// unlink/lookup race?
// better: inode generation #
// insert when file created, not just looked up // insert when file created, not just looked up
// eviction
// //
#include "types.h" #include "types.h"
...@@ -32,7 +34,7 @@ struct nce { ...@@ -32,7 +34,7 @@ struct nce {
char name[DIRSIZ]; char name[DIRSIZ];
uint cinum; // child inumber uint cinum; // child inumber
}; };
#define NCE 32 #define NCE 128
struct nce nce[NCE]; struct nce nce[NCE];
void void
...@@ -85,7 +87,8 @@ nc_insert(struct inode *dir, char *name, struct inode *ip) ...@@ -85,7 +87,8 @@ nc_insert(struct inode *dir, char *name, struct inode *ip)
return; return;
} }
for(int i = 0; i < NCE; i++){ int i;
for(i = 0; i < NCE; i++){
e = &nce[i]; e = &nce[i];
if(e->valid == 0){ if(e->valid == 0){
e->valid = 1; e->valid = 1;
...@@ -96,6 +99,8 @@ nc_insert(struct inode *dir, char *name, struct inode *ip) ...@@ -96,6 +99,8 @@ nc_insert(struct inode *dir, char *name, struct inode *ip)
break; break;
} }
} }
if(i >= NCE)
cprintf("namecache full\n");
release(&nc_lock); release(&nc_lock);
} }
......
...@@ -98,15 +98,22 @@ addrun1(struct runq *rq, struct proc *p) ...@@ -98,15 +98,22 @@ addrun1(struct runq *rq, struct proc *p)
STAILQ_FOREACH(q, &rq->runq, run_next) STAILQ_FOREACH(q, &rq->runq, run_next)
if (q == p) if (q == p)
panic("addrun1: already on queue"); panic("addrun1: already on queue");
acquire(&p->lock);
p->state = RUNNABLE; p->state = RUNNABLE;
STAILQ_INSERT_TAIL(&rq->runq, p, run_next); STAILQ_INSERT_TAIL(&rq->runq, p, run_next);
release(&p->lock);
} }
// Mark a process RUNNABLE and add it to the runq
// of its cpu. Caller must hold p->lock so that
// some other core doesn't start running the
// process before the caller has finished setting
// the process up, and to cope with racing callers
// e.g. two wakeups on same process. and to
// allow atomic addrun(); sched();
void void
addrun(struct proc *p) addrun(struct proc *p)
{ {
if(!holding(&p->lock))
panic("addrun no p->lock");
acquire(&runqs[p->cpuid].lock); acquire(&runqs[p->cpuid].lock);
// cprintf("%d: addrun %d\n", cpunum(), p->pid); // cprintf("%d: addrun %d\n", cpunum(), p->pid);
addrun1(&runqs[p->cpuid], p); addrun1(&runqs[p->cpuid], p);
...@@ -119,9 +126,7 @@ delrun1(struct runq *rq, struct proc *p) ...@@ -119,9 +126,7 @@ delrun1(struct runq *rq, struct proc *p)
struct proc *q, *nq; struct proc *q, *nq;
STAILQ_FOREACH_SAFE(q, &rq->runq, run_next, nq) { STAILQ_FOREACH_SAFE(q, &rq->runq, run_next, nq) {
if (q == p) { if (q == p) {
acquire(&p->lock);
STAILQ_REMOVE(&rq->runq, q, proc, run_next); STAILQ_REMOVE(&rq->runq, q, proc, run_next);
release(&p->lock);
return; return;
} }
} }
...@@ -131,6 +136,8 @@ delrun1(struct runq *rq, struct proc *p) ...@@ -131,6 +136,8 @@ delrun1(struct runq *rq, struct proc *p)
void void
delrun(struct proc *p) delrun(struct proc *p)
{ {
if(!holding(&p->lock))
panic("delrun no p->lock");
acquire(&runq->lock); acquire(&runq->lock);
// cprintf("%d: delrun %d\n", cpunum(), p->pid); // cprintf("%d: delrun %d\n", cpunum(), p->pid);
delrun1(runq, p); delrun1(runq, p);
...@@ -167,7 +174,9 @@ userinit(void) ...@@ -167,7 +174,9 @@ userinit(void)
safestrcpy(p->name, "initcode", sizeof(p->name)); safestrcpy(p->name, "initcode", sizeof(p->name));
p->cwd = namei("/"); p->cwd = namei("/");
acquire(&p->lock);
addrun(p); addrun(p);
release(&p->lock);
} }
// Grow/shrink current process's memory by n bytes. // Grow/shrink current process's memory by n bytes.
...@@ -294,14 +303,16 @@ fork(int flags) ...@@ -294,14 +303,16 @@ fork(int flags)
if(proc->ofile[i]) if(proc->ofile[i])
np->ofile[i] = filedup(proc->ofile[i]); np->ofile[i] = filedup(proc->ofile[i]);
np->cwd = idup(proc->cwd); np->cwd = idup(proc->cwd);
pid = np->pid; pid = np->pid;
addrun(np);
safestrcpy(np->name, proc->name, sizeof(proc->name)); safestrcpy(np->name, proc->name, sizeof(proc->name));
acquire(&proc->lock); acquire(&proc->lock);
SLIST_INSERT_HEAD(&proc->childq, np, child_next); SLIST_INSERT_HEAD(&proc->childq, np, child_next);
release(&proc->lock); release(&proc->lock);
acquire(&np->lock);
addrun(np);
release(&np->lock);
// cprintf("%d: fork done (pid %d)\n", proc->pid, pid); // cprintf("%d: fork done (pid %d)\n", proc->pid, pid);
return pid; return pid;
} }
...@@ -420,11 +431,10 @@ migrate(void) ...@@ -420,11 +431,10 @@ migrate(void)
if (idle[c]) { // OK if there is a race if (idle[c]) { // OK if there is a race
// cprintf("migrate to %d\n", c); // cprintf("migrate to %d\n", c);
p = proc; p = proc;
acquire(&p->lock);
p->curcycles = 0; p->curcycles = 0;
p->cpuid = c; p->cpuid = c;
addrun(p); addrun(p);
acquire(&p->lock);
p->state = RUNNABLE;
sched(); sched();
release(&proc->lock); release(&proc->lock);
return; return;
...@@ -443,6 +453,7 @@ steal(void) ...@@ -443,6 +453,7 @@ steal(void)
continue; continue;
acquire(&runqs[c].lock); acquire(&runqs[c].lock);
STAILQ_FOREACH(p, &runqs[c].runq, run_next) { STAILQ_FOREACH(p, &runqs[c].runq, run_next) {
acquire(&p->lock);
if (p->state != RUNNABLE) if (p->state != RUNNABLE)
panic("non-runnable proc on runq"); panic("non-runnable proc on runq");
if (p->curcycles > MINCYCTHRESH) { if (p->curcycles > MINCYCTHRESH) {
...@@ -452,8 +463,10 @@ steal(void) ...@@ -452,8 +463,10 @@ steal(void)
p->curcycles = 0; p->curcycles = 0;
p->cpuid = cpu->id; p->cpuid = cpu->id;
addrun(p); addrun(p);
release(&p->lock);
return 1; return 1;
} }
release(&p->lock);
} }
release(&runqs[c].lock); release(&runqs[c].lock);
} }
...@@ -557,9 +570,8 @@ sched(void) ...@@ -557,9 +570,8 @@ sched(void)
void void
yield(void) yield(void)
{ {
addrun(proc);
acquire(&proc->lock); //DOC: yieldlock acquire(&proc->lock); //DOC: yieldlock
addrun(proc);
sched(); sched();
release(&proc->lock); release(&proc->lock);
} }
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "fcntl.h" #include "fcntl.h"
#include "syscall.h" #include "syscall.h"
#include "traps.h" #include "traps.h"
#include "xv6-mtrace.h"
char buf[2048]; char buf[2048];
char name[3]; char name[3];
...@@ -1464,17 +1465,109 @@ bigargtest(void) ...@@ -1464,17 +1465,109 @@ bigargtest(void)
wait(); wait();
} }
void
uox(char *name, char *data)
{
int fd = open(name, O_CREATE|O_RDWR);
if(fd < 0){
printf(stdout, "creat %s failed\n", name);
exit();
}
if(write(fd, "xx", 2) != 2){
printf(stdout, "write failed\n");
exit();
}
close(fd);
}
// test concurrent unlink / open.
void
unopentest(void)
{
printf(stdout, "concurrent unlink/open\n");
int pid = fork(0);
if(pid == 0){
while(1){
for(int i = 0; i < 1; i++){
char name[32];
name[0] = 'f';
name[1] = 'A' + i;
name[2] = '\0';
int fd = open(name, O_RDWR);
if(fd >= 0)
close(fd);
fd = open(name, O_RDWR);
if(fd >= 0){
if(write(fd, "y", 1) != 1){
printf(stdout, "write %s failed\n", name);
exit();
}
close(fd);
}
}
}
}
for(int iters = 0; iters < 1000; iters++){
for(int i = 0; i < 1; i++){
char name[32];
name[0] = 'f';
name[1] = 'A' + i;
name[2] = '\0';
uox(name, "xxx");
if(unlink(name) < 0){
printf(stdout, "unlink %s failed\n", name);
exit();
}
// reallocate that inode
name[0] = 'g';
if(mkdir(name) != 0){
printf(stdout, "mkdir %s failed\n", name);
exit();
}
}
for(int i = 0; i < 10; i++){
char name[32];
name[0] = 'f';
name[1] = 'A' + i;
name[2] = '\0';
unlink(name);
name[0] = 'g';
unlink(name);
}
}
kill(pid);
wait();
printf(stdout, "concurrent unlink/open ok\n");
}
// for mtrace-magic.h
char*
strncpy(char *s, const char *t, int n)
{
int tlen = strlen((char *)t);
memmove(s, (char *)t, n > tlen ? tlen : n);
if (n > tlen)
s[tlen] = 0;
return s;
}
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
printf(1, "usertests starting\n"); printf(1, "usertests starting\n");
mtrace_enable_set(1, "xv6-forktest");
if(open("usertests.ran", 0) >= 0){ if(open("usertests.ran", 0) >= 0){
printf(1, "already ran user tests -- rebuild fs.img\n"); printf(1, "already ran user tests -- rebuild fs.img\n");
exit(); exit();
} }
close(open("usertests.ran", O_CREATE)); close(open("usertests.ran", O_CREATE));
// unopentest();
bigargtest(); bigargtest();
bsstest(); bsstest();
sbrktest(); sbrktest();
......
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论