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

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

#include "types.h"
#include "stat.h"
#include "user.h"
#include "fs.h"
const char*
fmtname(const char *path)
{
static char buf[DIRSIZ+1];
const char *p;
// Find first character after last slash.
for(p=path+strlen(path); p >= path && *p != '/'; p--)
;
p++;
// Return blank-padded name.
if(strlen(p) >= DIRSIZ)
return p;
memmove(buf, p, strlen(p));
memset(buf+strlen(p), ' ', DIRSIZ-strlen(p));
return buf;
}
void
ls(const char *path)
{
char buf[512], *p;
int fd;
struct dirent de;
struct stat st;
if((fd = open(path, 0)) < 0){
fprintf(2, "ls: cannot open %s\n", path);
return;
}
if(fstat(fd, &st) < 0){
fprintf(2, "ls: cannot stat %s\n", path);
close(fd);
return;
}
switch(st.type){
case T_FILE:
fprintf(1, "%s %d %d %d\n", fmtname(path), st.type, st.ino, st.size);
break;
case T_DIR:
if(strlen(path) + 1 + DIRSIZ + 1 > sizeof buf){
fprintf(1, "ls: path too long\n");
break;
}
strcpy(buf, path);
p = buf+strlen(buf);
*p++ = '/';
while(read(fd, &de, sizeof(de)) == sizeof(de)){
if(de.inum == 0)
continue;
memmove(p, de.name, DIRSIZ);
p[DIRSIZ] = 0;
if(stat(buf, &st) < 0){
fprintf(1, "ls: cannot stat %s\n", buf);
continue;
}
fprintf(1, "%s %d %d %d\n", fmtname(buf), st.type, st.ino, st.size);
}
break;
}
close(fd);
}
void
work(void *arg)
{
u64 tid = (u64)arg;
// grab and push work (may divide into blocks? and call ls on a block)?
// maybe implement getdirent sys call that gives you some unread dir entry
}
int
main(int argc, char *argv[])
{
int i;
int nthread = 4;
for(int i = 0; i < nthread; i++) {
sbrk(8192);
void *tstack = sbrk(0);
// fprintf(1, "tstack %lx\n", tstack);
int tid = forkt(tstack, (void*) thr, (void *)(u64)i);
if (0) fprintf(1, "pls[%d]: child %d\n", getpid(), tid);
}
// push work wq.cc
if(argc < 2){
ls(".");
exit();
}
for(i=1; i<argc; i++)
ls(argv[i]);
for(int i = 0; i < nthread; i++)
wait();
exit();
}
...@@ -263,54 +263,27 @@ struct work * allocwork(void); ...@@ -263,54 +263,27 @@ struct work * allocwork(void);
void freework(struct work *w); void freework(struct work *w);
// cilk.c // cilk.c
void initcilkframe(struct cilkframe*);
#if CILKENABLE #if CILKENABLE
void cilk_push(void (*fn)(uptr, uptr), u64 arg0, u64 arg1); void cilk_push(void (*fn)(uptr, uptr), u64 arg0, u64 arg1);
void cilk_start(void); void cilk_start(void);
void cilk_end(void); u64 cilk_end(void);
void cilk_dump(void); void cilk_dump(void);
int cilk_trywork(void); void cilk_abort(u64 val);
void initcilkframe(struct cilkframe *wq);
#else #else
#define cilk_push(rip, arg0, arg1) do { \ #define cilk_push(rip, arg0, arg1) do { \
void (*fn)(uptr, uptr) = rip; \ void (*fn)(uptr, uptr) = rip; \
fn(arg0, arg1); \ fn(arg0, arg1); \
} while(0) } while(0)
#define cilk_start() do { } while(0) #define cilk_start() do { } while(0)
#define cilk_end() do { } while(0)
#define cilk_end() (myproc()->cilkframe.abort)
#define cilk_dump() do { } while(0) #define cilk_dump() do { } while(0)
#define cilk_trywork() 0 #define cilk_abort(val) do { \
#define initcilkframe(x) do { } while (0) cmpxch(&myproc()->cilkframe.abort, (u64)0, (u64)val); \
} while (0)
#endif #endif
// various init functions
void initpic(void);
void initioapic(void);
void inituart(void);
void initcga(void);
void initconsole(void);
void initpg(void);
void initmp(void);
void initlapic(void);
void inittls(void);
void initnmi(void);
void inittrap(void);
void initseg(void);
void initkalloc(u64 mbaddr);
void initrcu(void);
void initproc(void);
void initbio(void);
void initinode(void);
void initdisk(void);
void inituser(void);
void initcilk(void);
void initsamp(void);
void initpci(void);
void initnet(void);
void initsched(void);
void initlockstat(void);
void initwq(void);
void initsperf(void);
// other exported/imported functions // other exported/imported functions
void cmain(u64 mbmagic, u64 mbaddr); void cmain(u64 mbmagic, u64 mbaddr);
void mpboot(void); void mpboot(void);
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#define PGROUNDUP(sz) (((sz)+PGSIZE-1) & ~(PGSIZE-1)) #define PGROUNDUP(sz) (((sz)+PGSIZE-1) & ~(PGSIZE-1))
#define PGROUNDDOWN(a) ((__typeof__(a))((((uptr)(a)) & ~(PGSIZE-1)))) #define PGROUNDDOWN(a) ((__typeof__(a))((((uptr)(a)) & ~(PGSIZE-1))))
#define PGOFFSET(a) ((a) & ((1<<PGSHIFT)-1))
// Address in page table or page directory entry // Address in page table or page directory entry
#define PTE_ADDR(pte) ((uptr)(pte) & ~0xFFF) #define PTE_ADDR(pte) ((uptr)(pte) & ~0xFFF)
......
...@@ -19,6 +19,7 @@ struct context { ...@@ -19,6 +19,7 @@ struct context {
// Work queue frame // Work queue frame
struct cilkframe { struct cilkframe {
volatile std::atomic<u64> ref; volatile std::atomic<u64> ref;
volatile std::atomic<u64> abort;
}; };
// Per-process, per-stack meta data for mtrace // Per-process, per-stack meta data for mtrace
......
// cilk style run queue // cilk style run queue built on wq.cc:
// A work queue is built from NCPU per-core wqueues. // A core pushes work to the head of its per-core wq.
// A core pushes work to the head of its per-core wqueue. // A core pops work from the head of its per-core wq.
// A core pops work from the head of its per-core wqueue.
// A core pops work from the tail of another core's per-core wqueue. // A core pops work from the tail of another core's per-core wqueue.
// //
// Usage: // Usage:
...@@ -25,7 +24,6 @@ ...@@ -25,7 +24,6 @@
// cprintf("%c %c\n", arg[0], arg[1]); // cprintf("%c %c\n", arg[0], arg[1]);
// } // }
#if CILKENABLE
#include "types.h" #include "types.h"
#include "kernel.hh" #include "kernel.hh"
#include "amd64.h" #include "amd64.h"
...@@ -35,37 +33,18 @@ ...@@ -35,37 +33,18 @@
#include "condvar.h" #include "condvar.h"
#include "queue.h" #include "queue.h"
#include "proc.hh" #include "proc.hh"
#if CILKENABLE
#include "mtrace.h" #include "mtrace.h"
#include "wq.hh" #include "wq.hh"
#include "percpu.hh"
#define NSLOTS (1 << CILKSHIFT)
struct cilkqueue {
struct cilkthread *thread[NSLOTS];
volatile int head __mpalign__;
struct spinlock lock;
volatile int tail;
__padout__;
} __mpalign__;
struct cilkthread {
u64 rip;
u64 arg0;
u64 arg1;
struct cilkframe *frame; // parent cilkframe
__padout__;
} __mpalign__;
struct cilkstat { struct cilkstat {
u64 push; u64 push;
u64 full; u64 full;
u64 steal; u64 steal;
__padout__; };
} __mpalign__; static percpu<cilkstat> stat;
static struct cilkqueue queue[NCPU] __mpalign__;
static struct cilkstat stat[NCPU] __mpalign__;
static struct cilkframe * static struct cilkframe *
cilk_frame(void) cilk_frame(void)
...@@ -73,12 +52,6 @@ cilk_frame(void) ...@@ -73,12 +52,6 @@ cilk_frame(void)
return mycpu()->cilkframe; return mycpu()->cilkframe;
} }
static struct cilkstat *
cilk_stat(void)
{
return &stat[mycpu()->id];
}
static void static void
__cilk_run(struct work *w, void *xfn, void *arg0, void *arg1, void *xframe) __cilk_run(struct work *w, void *xfn, void *arg0, void *arg1, void *xframe)
{ {
...@@ -87,9 +60,10 @@ __cilk_run(struct work *w, void *xfn, void *arg0, void *arg1, void *xframe) ...@@ -87,9 +60,10 @@ __cilk_run(struct work *w, void *xfn, void *arg0, void *arg1, void *xframe)
struct cilkframe *old = mycpu()->cilkframe; struct cilkframe *old = mycpu()->cilkframe;
if (old != frame) if (old != frame)
cilk_stat()->steal++; stat->steal++;
mycpu()->cilkframe = frame; mycpu()->cilkframe = frame;
if (frame->abort == 0)
fn((uptr)arg0, (uptr)arg1); fn((uptr)arg0, (uptr)arg1);
mycpu()->cilkframe = old; mycpu()->cilkframe = old;
frame->ref--; frame->ref--;
...@@ -117,10 +91,10 @@ cilk_push(void (*fn)(uptr, uptr), u64 arg0, u64 arg1) ...@@ -117,10 +91,10 @@ cilk_push(void (*fn)(uptr, uptr), u64 arg0, u64 arg1)
if (wq_push(w)) { if (wq_push(w)) {
freework(w); freework(w);
fn(arg0, arg1); fn(arg0, arg1);
cilk_stat()->full++; stat->full++;
} else { } else {
cilk_frame()->ref++; cilk_frame()->ref++;
cilk_stat()->push++; stat->push++;
} }
} }
...@@ -138,14 +112,26 @@ cilk_start(void) ...@@ -138,14 +112,26 @@ cilk_start(void)
// End of the current work queue frame. // End of the current work queue frame.
// The core works while the reference count of the current // The core works while the reference count of the current
// work queue frame is not 0. // work queue frame is not 0.
void u64
cilk_end(void) cilk_end(void)
{ {
u64 r;
while (cilk_frame()->ref != 0) while (cilk_frame()->ref != 0)
wq_trywork(); wq_trywork();
r = cilk_frame()->abort;
mycpu()->cilkframe = 0; mycpu()->cilkframe = 0;
popcli(); popcli();
return r;
}
void
cilk_abort(u64 val)
{
cmpxch(&cilk_frame()->abort, (u64)0, val);
} }
void void
...@@ -189,19 +175,11 @@ testcilk(void) ...@@ -189,19 +175,11 @@ testcilk(void)
} }
popcli(); popcli();
} }
#endif // CILKENABLE
void void
initcilkframe(struct cilkframe *cilk) initcilkframe(struct cilkframe *cilk)
{ {
memset(cilk, 0, sizeof(*cilk)); cilk->ref = 0;
} cilk->abort = 0;
void
initcilk(void)
{
int i;
for (i = 0; i < NCPU; i++)
initlock(&queue[i].lock, "queue lock", LOCKSTAT_CILK);
} }
#endif // CILKENABLE
...@@ -34,6 +34,10 @@ dosegment(uptr a0, u64 a1) ...@@ -34,6 +34,10 @@ dosegment(uptr a0, u64 a1)
u64 off = a1; u64 off = a1;
struct vmnode *vmn = nullptr; struct vmnode *vmn = nullptr;
struct proghdr ph; struct proghdr ph;
uptr va_start, va_end;
uptr in_off;
uptr in_sz;
int npg;
prof_start(dosegment_prof); prof_start(dosegment_prof);
if(readi(args->ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph)) if(readi(args->ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph))
...@@ -42,33 +46,30 @@ dosegment(uptr a0, u64 a1) ...@@ -42,33 +46,30 @@ dosegment(uptr a0, u64 a1)
goto bad; goto bad;
if(ph.memsz < ph.filesz) if(ph.memsz < ph.filesz)
goto bad; goto bad;
// XXX(sbw) vaddr doesn't have to be page aligned.. if (ph.offset < PGOFFSET(ph.vaddr))
if(ph.vaddr % PGSIZE) {
cprintf("unaligned ph.va\n");
goto bad; goto bad;
}
{ va_start = PGROUNDDOWN(ph.vaddr);
uptr va_start = PGROUNDDOWN(ph.vaddr); va_end = PGROUNDUP(ph.vaddr + ph.memsz);
uptr va_end = PGROUNDUP(ph.vaddr + ph.memsz); in_off = ph.offset - PGOFFSET(ph.vaddr);
in_sz = ph.filesz + PGOFFSET(ph.vaddr);
int npg = (va_end - va_start) / PGSIZE; npg = (va_end - va_start) / PGSIZE;
if ((vmn = new vmnode(npg, odp ? ONDEMAND : EAGER, if ((vmn = new vmnode(npg, odp ? ONDEMAND : EAGER,
args->ip, ph.offset, ph.filesz)) == 0) args->ip, in_off, in_sz)) == 0)
goto bad; goto bad;
if(args->vmap->insert(vmn, ph.vaddr, 1) < 0) if(args->vmap->insert(vmn, va_start, 1) < 0)
goto bad; goto bad;
prof_end(dosegment_prof); prof_end(dosegment_prof);
return; return;
}
bad: bad:
panic("dosegment: Oops"); cilk_abort(-1);
} }
static void dostack(uptr a0, u64 a1) static void __attribute__((unused)) dostack(uptr a0, u64 a1)
{ {
struct vmnode *vmn = nullptr; struct vmnode *vmn = nullptr;
struct eargs *args = (eargs*) a0; struct eargs *args = (eargs*) a0;
...@@ -110,18 +111,19 @@ static void dostack(uptr a0, u64 a1) ...@@ -110,18 +111,19 @@ static void dostack(uptr a0, u64 a1)
for(last=s=args->path; *s; s++) for(last=s=args->path; *s; s++)
if(*s == '/') if(*s == '/')
last = s+1; last = s+1;
safestrcpy(args->proc->name, last, sizeof(args->proc->name));
// XXX(sbw) Oops, don't want to do this, unless we have abort
safestrcpy(args->proc->name, last, sizeof(args->proc->name));
args->proc->tf->rsp = sp; args->proc->tf->rsp = sp;
prof_end(dostack_prof); prof_end(dostack_prof);
return; return;
bad: bad:
panic("dostack: Oops"); cilk_abort(-1);
} }
static void doheap(uptr a0, u64 a1) static void __attribute__((unused)) doheap(uptr a0, u64 a1)
{ {
struct vmnode *vmn = nullptr; struct vmnode *vmn = nullptr;
struct eargs *args = (eargs*) a0; struct eargs *args = (eargs*) a0;
...@@ -138,7 +140,7 @@ static void doheap(uptr a0, u64 a1) ...@@ -138,7 +140,7 @@ static void doheap(uptr a0, u64 a1)
return; return;
bad: bad:
panic("doheap: Oops"); cilk_abort(-1);
} }
int int
...@@ -204,7 +206,8 @@ exec(const char *path, char **argv) ...@@ -204,7 +206,8 @@ exec(const char *path, char **argv)
//cilk_push(dostack, (uptr)&args, (uptr)0); //cilk_push(dostack, (uptr)&args, (uptr)0);
dostack((uptr)&args, (uptr)0); dostack((uptr)&args, (uptr)0);
cilk_end(); if (cilk_end())
goto bad;
// Commit to the user image. // Commit to the user image.
oldvmap = myproc()->vmap; oldvmap = myproc()->vmap;
......
...@@ -9,8 +9,34 @@ ...@@ -9,8 +9,34 @@
#include "condvar.h" #include "condvar.h"
#include "proc.hh" #include "proc.hh"
extern void initidle(void); void initpic(void);
extern void idleloop(void); void initioapic(void);
void inituart(void);
void initcga(void);
void initconsole(void);
void initpg(void);
void initmp(void);
void initlapic(void);
void inittls(void);
void initnmi(void);
void inittrap(void);
void initseg(void);
void initkalloc(u64 mbaddr);
void initrcu(void);
void initproc(void);
void initbio(void);
void initinode(void);
void initdisk(void);
void inituser(void);
void initsamp(void);
void initpci(void);
void initnet(void);
void initsched(void);
void initlockstat(void);
void initwq(void);
void initsperf(void);
void initidle(void);
void idleloop(void);
static volatile int bstate; static volatile int bstate;
...@@ -89,9 +115,6 @@ cmain(u64 mbmagic, u64 mbaddr) ...@@ -89,9 +115,6 @@ cmain(u64 mbmagic, u64 mbaddr)
initinode(); // inode cache initinode(); // inode cache
initdisk(); // disk initdisk(); // disk
initwq(); initwq();
#if CILKENABLE
initcilk();
#endif
initsamp(); initsamp();
initlockstat(); initlockstat();
initpci(); initpci();
......
...@@ -109,10 +109,18 @@ wq_push2(void (*fn)(struct work*, void*, void*), void *a0, void *a1) ...@@ -109,10 +109,18 @@ wq_push2(void (*fn)(struct work*, void*, void*), void *a0, void *a1)
return 0; return 0;
} }
static struct work * static void
__wq_run(struct work *w)
{
void (*fn)(struct work*, void*, void*, void*, void*, void*) =
(void(*)(work*,void*,void*,void*,void*,void*))w->rip;
fn(w, w->arg0, w->arg1, w->arg2, w->arg3, w->arg4);
freework(w);
}
static inline struct work *
__wq_pop(int c) __wq_pop(int c)
{ {
// Called with cli
struct wqueue *wq = &queue[c]; struct wqueue *wq = &queue[c];
struct work *w; struct work *w;
int i; int i;
...@@ -136,10 +144,9 @@ __wq_pop(int c) ...@@ -136,10 +144,9 @@ __wq_pop(int c)
return w; return w;
} }
static struct work * static inline struct work *
__wq_steal(int c) __wq_steal(int c)
{ {
// Called with cli
struct wqueue *wq = &queue[c]; struct wqueue *wq = &queue[c];
struct work *w; struct work *w;
int i; int i;
...@@ -160,42 +167,34 @@ __wq_steal(int c) ...@@ -160,42 +167,34 @@ __wq_steal(int c)
return w; return w;
} }
static void
__wq_run(struct work *w)
{
void (*fn)(struct work*, void*, void*, void*, void*, void*) =
(void(*)(work*,void*,void*,void*,void*,void*))w->rip;
fn(w, w->arg0, w->arg1, w->arg2, w->arg3, w->arg4);
freework(w);
}
int int
wq_trywork(void) wq_trywork(void)
{ {
struct work *w; struct work *w;
int i; int i, k;
// A "random" victim CPU
k = rdtsc();
//pushcli();
w = __wq_pop(mycpu()->id); w = __wq_pop(mycpu()->id);
if (w != nullptr) { if (w != nullptr) {
__wq_run(w); __wq_run(w);
//popcli();
return 1; return 1;
} }
// XXX(sbw) should be random
for (i = 0; i < NCPU; i++) { for (i = 0; i < NCPU; i++) {
if (i == mycpu()->id) int j = (i+k) % NCPU;
if (j == mycpu()->id)
continue; continue;
w = __wq_steal(i); w = __wq_steal(j);
if (w != nullptr) { if (w != nullptr) {
__wq_run(w); __wq_run(w);
//popcli();
return 1; return 1;
} }
} }
//popcli();
return 0; return 0;
} }
......
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论