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

Parallelize exec more -- decrease performance of exec more.

上级 cb1ecafb
...@@ -21,16 +21,18 @@ ...@@ -21,16 +21,18 @@
static const int odp = 1; static const int odp = 1;
DEFINE_PROFCTR(dosegment_prof);
struct eargs { struct eargs {
struct proc *proc;
struct inode *ip; struct inode *ip;
struct vmap *vmap; struct vmap *vmap;
char *path;
char **argv;
}; };
static void static void
dosegment(uptr a0, u64 a1) dosegment(uptr a0, u64 a1)
{ {
static DEFINE_PROFCTR(dosegment_prof);
struct eargs *args = (void*) a0; struct eargs *args = (void*) a0;
u64 off = a1; u64 off = a1;
struct vmnode *vmn = NULL; struct vmnode *vmn = NULL;
...@@ -74,151 +76,97 @@ bad: ...@@ -74,151 +76,97 @@ bad:
panic("dosegment: Oops"); panic("dosegment: Oops");
} }
int static void dostack(uptr a0, u64 a1)
exec(char *path, char **argv)
{ {
struct inode *ip = NULL; static DEFINE_PROFCTR(dostack_prof);
struct vmap *vmap = NULL;
struct vmnode *vmn = NULL; struct vmnode *vmn = NULL;
struct elfhdr elf; struct eargs *args = (void*) a0;
struct proghdr ph;
uptr brk = 0;
u64 off;
int i;
uptr sp;
int argc; int argc;
uptr sp;
uptr ustack[1+MAXARG+1]; uptr ustack[1+MAXARG+1];
char *s, *last; char *s, *last;
struct vmap *oldvmap;
if((ip = namei(path)) == 0)
return -1;
rcu_begin_read();
// Check ELF header
if(ip->type != T_FILE)
goto bad;
if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf))
goto bad;
if(elf.magic != ELF_MAGIC)
goto bad;
if((vmap = vmap_alloc()) == 0)
goto bad;
struct eargs args;
args.ip = ip;
args.vmap = vmap;
wq_start();
for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){
Elf64_Word type;
if(readi(ip, (char*)&type,
off+offsetof(struct proghdr, type),
sizeof(type)) != sizeof(type))
goto bad;
if(type != ELF_PROG_LOAD)
continue;
wq_push(dosegment, (uptr)&args, (uptr)off);
}
if (odp) {
// iunlock(ip);
} else {
// iunlockput(ip);
iput(ip);
ip = 0;
}
brk = BRK;
// Allocate a vmnode for the heap.
// XXX pre-allocate 32 pages..
if((vmn = vmn_allocpg(32)) == 0)
goto bad;
if(vmap_insert(vmap, vmn, brk) < 0)
goto bad;
vmn = 0;
// Allocate a one-page stack at the top of the (user) address space prof_start(dostack_prof);
// Allocate a one-page stack at the top of the (user) address space
if((vmn = vmn_allocpg(USTACKPAGES)) == 0) if((vmn = vmn_allocpg(USTACKPAGES)) == 0)
goto bad; goto bad;
if(vmap_insert(vmap, vmn, USERTOP-(USTACKPAGES*PGSIZE)) < 0) if(vmap_insert(args->vmap, vmn, USERTOP-(USTACKPAGES*PGSIZE)) < 0)
goto bad; goto bad;
vmn = 0; vmn = 0;
// Push argument strings, prepare rest of stack in ustack. // Push argument strings, prepare rest of stack in ustack.
sp = USERTOP; sp = USERTOP;
for(argc = 0; argv[argc]; argc++) { for(argc = 0; args->argv[argc]; argc++) {
if(argc >= MAXARG) if(argc >= MAXARG)
goto bad; goto bad;
sp -= strlen(argv[argc]) + 1; sp -= strlen(args->argv[argc]) + 1;
sp &= ~7; sp &= ~7;
if(copyout(vmap, sp, argv[argc], strlen(argv[argc]) + 1) < 0) if(copyout(args->vmap, sp, args->argv[argc], strlen(args->argv[argc]) + 1) < 0)
goto bad; goto bad;
ustack[1+argc] = sp; ustack[1+argc] = sp;
} }
ustack[1+argc] = 0; ustack[1+argc] = 0;
//prof_start(exec3_prof);
ustack[0] = 0xffffffffffffffffull; // fake return PC ustack[0] = 0xffffffffffffffffull; // fake return PC
myproc()->tf->rdi = argc; args->proc->tf->rdi = argc;
myproc()->tf->rsi = sp - (argc+1)*8; args->proc->tf->rsi = sp - (argc+1)*8;
sp -= (1+argc+1) * 8; sp -= (1+argc+1) * 8;
if(copyout(vmap, sp, ustack, (1+argc+1)*8) < 0) if(copyout(args->vmap, sp, ustack, (1+argc+1)*8) < 0)
goto bad; goto bad;
// Save program name for debugging. // Save program name for debugging.
for(last=s=path; *s; s++) for(last=s=args->path; *s; s++)
if(*s == '/') if(*s == '/')
last = s+1; last = s+1;
safestrcpy(myproc()->name, last, sizeof(myproc()->name)); safestrcpy(args->proc->name, last, sizeof(args->proc->name));
wq_end();
// Commit to the user image. args->proc->tf->rsp = sp;
oldvmap = myproc()->vmap;
myproc()->vmap = vmap;
myproc()->brk = brk + 8; // XXX so that brk-1 points within heap vma..
myproc()->tf->rip = elf.entry; // main
myproc()->tf->rsp = sp;
switchuvm(myproc());
vmap_decref(oldvmap);
migrate(myproc()); prof_end(dostack_prof);
return;
rcu_end_read(); bad:
return 0; panic("dostack: Oops");
}
bad: static void doheap(uptr a0, u64 a1)
cprintf("exec failed\n"); {
if(vmap) static DEFINE_PROFCTR(doheap_prof);
vmap_decref(vmap); struct vmnode *vmn = NULL;
if(vmn) struct eargs *args = (void*) a0;
vmn_free(vmn);
rcu_end_read();
return 0; prof_start(doheap_prof);
// Allocate a vmnode for the heap.
// XXX pre-allocate 32 pages..
if((vmn = vmn_allocpg(32)) == 0)
goto bad;
if(vmap_insert(args->vmap, vmn, BRK) < 0)
goto bad;
vmn = 0;
prof_end(doheap_prof);
return;
bad:
panic("doheap: Oops");
} }
#if 0
int int
exec(char *path, char **argv) exec(char *path, char **argv)
{ {
static DEFINE_PROFCTR(exec_prof);
struct inode *ip = NULL; struct inode *ip = NULL;
struct vmap *vmap = NULL; struct vmap *vmap = NULL;
struct vmnode *vmn = NULL; struct vmnode *vmn = NULL;
struct elfhdr elf; struct elfhdr elf;
struct proghdr ph; struct proghdr ph;
uptr brk = 0;
u64 off; u64 off;
int i; int i;
uptr sp;
int argc;
uptr ustack[1+MAXARG+1];
char *s, *last;
struct vmap *oldvmap; struct vmap *oldvmap;
prof_start(exec_prof);
if((ip = namei(path)) == 0) if((ip = namei(path)) == 0)
return -1; return -1;
...@@ -235,39 +183,24 @@ exec(char *path, char **argv) ...@@ -235,39 +183,24 @@ exec(char *path, char **argv)
if((vmap = vmap_alloc()) == 0) if((vmap = vmap_alloc()) == 0)
goto bad; goto bad;
// Load program into memory. // Arguments for work queue
struct eargs args;
args.proc = myproc();
args.ip = ip;
args.vmap = vmap;
args.path = path;
args.argv = argv;
wq_start();
for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){ for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){
if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph)) Elf64_Word type;
if(readi(ip, (char*)&type,
off+offsetof(struct proghdr, type),
sizeof(type)) != sizeof(type))
goto bad; goto bad;
if(ph.type != ELF_PROG_LOAD) if(type != ELF_PROG_LOAD)
continue; continue;
if(ph.memsz < ph.filesz) wq_push(dosegment, (uptr)&args, (uptr)off);
goto bad;
// XXX(sbw) vaddr doesn't have to be page aligned..
if(ph.vaddr % PGSIZE) {
cprintf("unaligned ph.va\n");
goto bad;
}
uptr va_start = PGROUNDDOWN(ph.vaddr);
uptr va_end = PGROUNDUP(ph.vaddr + ph.memsz);
if(va_end > brk)
brk = va_end;
int npg = (va_end - va_start) / PGSIZE;
if (odp) {
if ((vmn = vmn_alloc(npg, ONDEMAND)) == 0)
goto bad;
} else {
if ((vmn = vmn_allocpg(npg)) == 0)
goto bad;
}
if(vmn_load(vmn, ip, ph.offset, ph.filesz) < 0)
goto bad;
if(vmap_insert(vmap, vmn, ph.vaddr) < 0)
goto bad;
vmn = 0;
} }
if (odp) { if (odp) {
...@@ -278,63 +211,26 @@ exec(char *path, char **argv) ...@@ -278,63 +211,26 @@ exec(char *path, char **argv)
ip = 0; ip = 0;
} }
brk = BRK; wq_push(doheap, (uptr)&args, (uptr)0);
// Allocate a vmnode for the heap.
// XXX pre-allocate 32 pages..
if((vmn = vmn_allocpg(32)) == 0)
goto bad;
if(vmap_insert(vmap, vmn, brk) < 0)
goto bad;
vmn = 0;
// Allocate a one-page stack at the top of the (user) address space // dostack reads from the user address space. The wq
if((vmn = vmn_allocpg(USTACKPAGES)) == 0) // stuff doesn't switch to the user address space.
goto bad; //wq_push(dostack, (uptr)&args, (uptr)0);
if(vmap_insert(vmap, vmn, USERTOP-(USTACKPAGES*PGSIZE)) < 0) dostack((uptr)&args, (uptr)0);
goto bad;
vmn = 0;
// Push argument strings, prepare rest of stack in ustack. wq_end();
sp = USERTOP;
for(argc = 0; argv[argc]; argc++) {
if(argc >= MAXARG)
goto bad;
sp -= strlen(argv[argc]) + 1;
sp &= ~7;
if(copyout(vmap, sp, argv[argc], strlen(argv[argc]) + 1) < 0)
goto bad;
ustack[1+argc] = sp;
}
ustack[1+argc] = 0;
ustack[0] = 0xffffffffffffffffull; // fake return PC
myproc()->tf->rdi = argc;
myproc()->tf->rsi = sp - (argc+1)*8;
sp -= (1+argc+1) * 8;
if(copyout(vmap, sp, ustack, (1+argc+1)*8) < 0)
goto bad;
// Save program name for debugging.
for(last=s=path; *s; s++)
if(*s == '/')
last = s+1;
safestrcpy(myproc()->name, last, sizeof(myproc()->name));
// Commit to the user image. // Commit to the user image.
oldvmap = myproc()->vmap; oldvmap = myproc()->vmap;
myproc()->vmap = vmap; myproc()->vmap = vmap;
myproc()->brk = brk + 8; // XXX so that brk-1 points within heap vma.. myproc()->brk = BRK + 8; // XXX so that brk-1 points within heap vma..
myproc()->tf->rip = elf.entry; // main myproc()->tf->rip = elf.entry; // main
myproc()->tf->rsp = sp;
switchuvm(myproc()); switchuvm(myproc());
vmap_decref(oldvmap); vmap_decref(oldvmap);
migrate(myproc());
rcu_end_read(); rcu_end_read();
prof_end(exec_prof);
return 0; return 0;
bad: bad:
...@@ -347,4 +243,3 @@ exec(char *path, char **argv) ...@@ -347,4 +243,3 @@ exec(char *path, char **argv)
return 0; return 0;
} }
#endif
...@@ -18,4 +18,4 @@ ...@@ -18,4 +18,4 @@
#define CPUKSTACKS (NPROC + NCPU) #define CPUKSTACKS (NPROC + NCPU)
#define QUANTUN 10 // scheduling time quantum and tick length (in msec) #define QUANTUN 10 // scheduling time quantum and tick length (in msec)
#define WQSHIFT 4 // 2^WORKSHIFT work queue slots #define WQSHIFT 4 // 2^WORKSHIFT work queue slots
#define WQENABLE 1 // Enable work queue #define WQENABLE 0 // Enable work queue
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论