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

Parallelize exec more -- decrease performance of exec more.

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