提交 f4cd5305 创建 作者: Silas Boyd-Wickizer's avatar Silas Boyd-Wickizer

Merge branch 'scale-amd64' of git+ssh://amsterdam.csail.mit.edu/home/am0/6.828/xv6 into scale-amd64

#include "types.h" #include "types.h"
#include "stat.h" #include "stat.h"
#include "user.h" #include "user.h"
#include "mtrace.h"
#define NCHILD 2 #define NCHILD 2
#define NDEPTH 7 #define NDEPTH 7
...@@ -11,7 +10,6 @@ forktree(int depth) ...@@ -11,7 +10,6 @@ forktree(int depth)
{ {
if (depth == 0) { if (depth == 0) {
fprintf(1, "%d: forkexectree\n", getpid()); fprintf(1, "%d: forkexectree\n", getpid());
mtenable("xv6-forkexectree");
} }
if (depth >= NDEPTH) if (depth >= NDEPTH)
...@@ -48,9 +46,6 @@ forktree(int depth) ...@@ -48,9 +46,6 @@ forktree(int depth)
if (depth > 0) if (depth > 0)
exit(); exit();
mtops(0);
mtdisable("xv6-forkexectree");
fprintf(1, "%d: forkexectree OK\n", getpid()); fprintf(1, "%d: forkexectree OK\n", getpid());
// halt(); // halt();
} }
......
...@@ -86,6 +86,8 @@ struct proc : public rcu_freed { ...@@ -86,6 +86,8 @@ struct proc : public rcu_freed {
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
u64 user_fs_; u64 user_fs_;
u64 unmap_tlbreq_; u64 unmap_tlbreq_;
int exec_cpuid_;
int in_exec_;
static proc* alloc(); static proc* alloc();
void set_state(procstate_t s); void set_state(procstate_t s);
......
...@@ -4,6 +4,7 @@ class work; ...@@ -4,6 +4,7 @@ class work;
int wq_trywork(void); int wq_trywork(void);
int wq_push(work *w); int wq_push(work *w);
int wq_pushto(work *w, int tcpuid);
void wq_dump(void); void wq_dump(void);
size_t wq_size(void); size_t wq_size(void);
void initwq(void); void initwq(void);
......
...@@ -173,17 +173,33 @@ bad: ...@@ -173,17 +173,33 @@ bad:
cilk_abort(-1); cilk_abort(-1);
} }
static void
exec_cleanup(vmap *oldvmap, uwq *olduwq)
{
if (olduwq != nullptr)
olduwq->dec();
oldvmap->decref();
}
int int
exec(const char *path, char **argv) exec(const char *path, char **argv)
{ {
struct inode *ip = nullptr; struct inode *ip = nullptr;
struct vmap *vmp = nullptr; struct vmap *vmp = nullptr;
uwq* uwq = nullptr; uwq* newuwq = nullptr;
struct elfhdr elf; struct elfhdr elf;
struct proghdr ph; struct proghdr ph;
u64 off; u64 off;
int i; int i;
struct vmap *oldvmap; vmap* oldvmap;
uwq* olduwq;
cwork* w;
myproc()->exec_cpuid_ = mycpuid();
myproc()->in_exec_ = 1;
yield();
myproc()->in_exec_ = 0;
if((ip = namei(myproc()->cwd, path)) == 0) if((ip = namei(myproc()->cwd, path)) == 0)
return -1; return -1;
...@@ -204,7 +220,7 @@ exec(const char *path, char **argv) ...@@ -204,7 +220,7 @@ exec(const char *path, char **argv)
if((vmp = vmap::alloc()) == 0) if((vmp = vmap::alloc()) == 0)
goto bad; goto bad;
if((uwq = uwq::alloc(vmp, myproc()->ftable)) == 0) if((newuwq = uwq::alloc(vmp, myproc()->ftable)) == 0)
goto bad; goto bad;
// Arguments for work queue // Arguments for work queue
...@@ -223,7 +239,7 @@ exec(const char *path, char **argv) ...@@ -223,7 +239,7 @@ exec(const char *path, char **argv)
sizeof(type)) != sizeof(type)) sizeof(type)) != sizeof(type))
goto bad; goto bad;
if (type == ELF_PROG_NOTE) { if (type == ELF_PROG_NOTE) {
if (donotes(ip, uwq, off) < 0) { if (donotes(ip, newuwq, off) < 0) {
cilk_abort(-1); cilk_abort(-1);
break; break;
} }
...@@ -243,14 +259,19 @@ exec(const char *path, char **argv) ...@@ -243,14 +259,19 @@ exec(const char *path, char **argv)
// Commit to the user image. // Commit to the user image.
oldvmap = myproc()->vmap; oldvmap = myproc()->vmap;
olduwq = myproc()->uwq;
myproc()->vmap = vmp; myproc()->vmap = vmp;
if (myproc()->uwq != nullptr) myproc()->uwq = newuwq;
myproc()->uwq->dec();
myproc()->uwq = uwq;
myproc()->tf->rip = elf.entry; myproc()->tf->rip = elf.entry;
switchvm(myproc()); switchvm(myproc());
oldvmap->decref();
w = new cwork();
assert(w);
w->rip = (void*) exec_cleanup;
w->arg0 = oldvmap;
w->arg1 = olduwq;
assert(wq_pushto(w, myproc()->exec_cpuid_) >= 0);
gc_end_epoch(); gc_end_epoch();
return 0; return 0;
...@@ -259,8 +280,8 @@ exec(const char *path, char **argv) ...@@ -259,8 +280,8 @@ exec(const char *path, char **argv)
cprintf("exec failed\n"); cprintf("exec failed\n");
if(vmp) if(vmp)
vmp->decref(); vmp->decref();
if(uwq) if(newuwq)
uwq->dec(); newuwq->dec();
gc_end_epoch(); gc_end_epoch();
return 0; return 0;
} }
...@@ -41,7 +41,7 @@ proc::proc(int npid) : ...@@ -41,7 +41,7 @@ proc::proc(int npid) :
pid(npid), parent(0), tf(0), context(0), killed(0), pid(npid), parent(0), tf(0), context(0), killed(0),
ftable(0), cwd(0), tsc(0), curcycles(0), cpuid(0), epoch(0), ftable(0), cwd(0), tsc(0), curcycles(0), cpuid(0), epoch(0),
cpu_pin(0), runq(0), oncv(0), cv_wakeup(0), cpu_pin(0), runq(0), oncv(0), cv_wakeup(0),
user_fs_(0), unmap_tlbreq_(0), state_(EMBRYO) user_fs_(0), unmap_tlbreq_(0), in_exec_(0), state_(EMBRYO)
{ {
snprintf(lockname, sizeof(lockname), "cv:proc:%d", pid); snprintf(lockname, sizeof(lockname), "cv:proc:%d", pid);
initlock(&lock, lockname+3, LOCKSTAT_PROC); initlock(&lock, lockname+3, LOCKSTAT_PROC);
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "vm.hh" #include "vm.hh"
enum { sched_debug = 0 }; enum { sched_debug = 0 };
enum { steal_nonexec = 1 };
struct runq { struct runq {
STAILQ_HEAD(queue, proc) q; STAILQ_HEAD(queue, proc) q;
...@@ -133,51 +134,54 @@ int ...@@ -133,51 +134,54 @@ int
steal(void) steal(void)
{ {
struct proc *steal; struct proc *steal;
int i;
int r = 0; int r = 0;
pushcli(); pushcli();
for (i = 1; i < ncpu; i++) { for (int nonexec = 0; nonexec < (steal_nonexec ? 2 : 1); nonexec++) {
struct runq *q = &runq[(i+mycpu()->id) % ncpu]; for (int i = 1; i < ncpu; i++) {
struct proc *p; struct runq *q = &runq[(i+mycpu()->id) % ncpu];
struct proc *p;
// XXX(sbw) Look for a process to steal. Acquiring q->lock
// then p->lock can result in deadlock. So we acquire // XXX(sbw) Look for a process to steal. Acquiring q->lock
// q->lock, scan for a process, drop q->lock, acquire p->lock, // then p->lock can result in deadlock. So we acquire
// and then check that it's still ok to steal p. // q->lock, scan for a process, drop q->lock, acquire p->lock,
steal = nullptr; // and then check that it's still ok to steal p.
if (tryacquire(&q->lock) == 0) steal = nullptr;
continue; if (tryacquire(&q->lock) == 0)
STAILQ_FOREACH(p, &q->q, runqlink) { continue;
if (p->get_state() == RUNNABLE && !p->cpu_pin && STAILQ_FOREACH(p, &q->q, runqlink) {
p->curcycles != 0 && p->curcycles > VICTIMAGE) if (p->get_state() == RUNNABLE && !p->cpu_pin &&
{ (p->in_exec_ || nonexec) &&
STAILQ_REMOVE(&q->q, p, proc, runqlink); p->curcycles != 0 && p->curcycles > VICTIMAGE)
steal = p; {
break; STAILQ_REMOVE(&q->q, p, proc, runqlink);
steal = p;
break;
}
} }
} release(&q->lock);
release(&q->lock);
if (steal) {
if (steal) { acquire(&steal->lock);
acquire(&steal->lock); if (steal->get_state() == RUNNABLE && !steal->cpu_pin &&
if (steal->get_state() == RUNNABLE && !steal->cpu_pin && steal->curcycles != 0 && steal->curcycles > VICTIMAGE)
steal->curcycles != 0 && steal->curcycles > VICTIMAGE) {
{ steal->curcycles = 0;
steal->curcycles = 0; steal->cpuid = mycpu()->id;
steal->cpuid = mycpu()->id; addrun(steal);
addrun(steal); release(&steal->lock);
r = 1;
goto found;
}
if (steal->get_state() == RUNNABLE)
addrun(steal);
release(&steal->lock); release(&steal->lock);
r = 1;
break;
} }
if (steal->get_state() == RUNNABLE)
addrun(steal);
release(&steal->lock);
} }
} }
found:
popcli(); popcli();
return r; return r;
} }
......
...@@ -428,6 +428,9 @@ sys_exec(const char *path, u64 uargv) ...@@ -428,6 +428,9 @@ sys_exec(const char *path, u64 uargv)
if(argcheckstr(path) < 0) { if(argcheckstr(path) < 0) {
return -1; return -1;
} }
mt_ascope ascope("%s(%s)", __func__, path);
memset(argv, 0, sizeof(argv)); memset(argv, 0, sizeof(argv));
for(i=0;; i++){ for(i=0;; i++){
if(i >= NELEM(argv)) if(i >= NELEM(argv))
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
class wq { class wq {
public: public:
wq(); wq();
int push(work *w); int push(work *w, int tcpuid);
int trywork(); int trywork();
void dump(); void dump();
...@@ -57,7 +57,13 @@ wq_size(void) ...@@ -57,7 +57,13 @@ wq_size(void)
int int
wq_push(work *w) wq_push(work *w)
{ {
return wq_->push(w); return wq_->push(w, mycpuid());
}
int
wq_pushto(work *w, int tcpuid)
{
return wq_->push(w, tcpuid);
} }
int int
...@@ -128,24 +134,24 @@ wq::declen(int c) ...@@ -128,24 +134,24 @@ wq::declen(int c)
} }
int int
wq::push(work *w) wq::push(work *w, int tcpuid)
{ {
int i; int i;
pushcli(); acquire(&q_[tcpuid].lock);
i = q_->head; i = q_[tcpuid].head;
if ((i - q_->tail) == NSLOTS) { if ((i - q_[tcpuid].tail) == NSLOTS) {
stat_->full++; stat_[tcpuid].full++;
popcli(); release(&q_[tcpuid].lock);
return -1; return -1;
} }
i = i & (NSLOTS-1); i = i & (NSLOTS-1);
q_->w[i] = w; q_[tcpuid].w[i] = w;
barrier(); barrier();
q_->head++; q_[tcpuid].head++;
inclen(mycpuid()); inclen(tcpuid);
stat_->push++; stat_[tcpuid].push++;
popcli(); release(&q_[tcpuid].lock);
return 0; return 0;
} }
......
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论