提交 7d2a3a47 创建 作者: 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

...@@ -33,9 +33,13 @@ ...@@ -33,9 +33,13 @@
(gdb) c (gdb) c
* Mac cross compiler gcc-4.6.2 * Mac cross compiler gcc-4.6.2
compiler without libstdc++
download, make, make install gmp-5.0.4, mpfr-3.1.0, and mpc-0.9 download, make, make install gmp-5.0.4, mpfr-3.1.0, and mpc-0.9
for mpfr and mpc: ./configure --with-gmp=/usr/local for mpfr and mpc: ./configure --with-gmp=/usr/local
for gcc: ../configure --target=x86_64-jos-elf --with-gmp=/usr/local/ --with-mpfr=/usr/local --enable-languages=c,c++ --without-headers --disable-nls for gcc:
mkdir build
cd build
../configure --target=x86_64-jos-elf --with-gmp=/usr/local/ --with-mpfr=/usr/local --enable-languages=c,c++ --without-headers --disable-nls
* clang * clang
- Version 3.0 or greater is required to build xv6 - Version 3.0 or greater is required to build xv6
......
...@@ -18,6 +18,7 @@ UPROGS= \ ...@@ -18,6 +18,7 @@ UPROGS= \
usertests \ usertests \
lockstat \ lockstat \
preadtest \ preadtest \
scripttest \
ftest \ ftest \
perf perf
......
#include "types.h"
#include "stat.h"
#include "fcntl.h"
#include "user.h"
#include "lib.h"
#include "amd64.h"
#include "ipc.hh"
#include "mmu.h"
int
main(int ac, char **av)
{
char *p = (char*) PGROUNDUP((u64)(sbrk(0) + 0x80000));
u64 len = 1000*4096;
u64 chunk = 128*4096; // max vmnode size
#if 0
char *q = p;
while(q < p + len){
u64 x = len - (q - p);
if(x > chunk)
x = chunk;
if(map(q, x) < 0){
fprintf(1, "map failed\n");
exit();
}
q += x;
}
#else
script(p, len, chunk);
#endif
memset(p, 1, len);
exit();
}
...@@ -47,6 +47,7 @@ long sys_listen(int, int); ...@@ -47,6 +47,7 @@ long sys_listen(int, int);
long sys_accept(int, void*, void*); long sys_accept(int, void*, void*);
long sys_pread(int fd, void *ubuf, size_t count, off_t offset); long sys_pread(int fd, void *ubuf, size_t count, off_t offset);
long sys_async(int, size_t, off_t, u32, u32); long sys_async(int, size_t, off_t, u32, u32);
long sys_script(void *addr, u64 len, u64 chunk);
extern long (*syscalls[])(u64, u64, u64, u64, u64, u64); extern long (*syscalls[])(u64, u64, u64, u64, u64, u64);
// other exported/imported functions // other exported/imported functions
......
...@@ -29,4 +29,5 @@ ...@@ -29,4 +29,5 @@
#define SYS_accept 28 #define SYS_accept 28
#define SYS_pread 29 #define SYS_pread 29
#define SYS_async 30 #define SYS_async 30
#define SYS_ncount 31 /* total number of system calls */ #define SYS_script 31
#define SYS_ncount 32 /* total number of system calls */
...@@ -29,6 +29,7 @@ int unmap(void *addr, int len); ...@@ -29,6 +29,7 @@ int unmap(void *addr, int len);
void halt(void); void halt(void);
ssize_t pread(int, void*, size_t, off_t); ssize_t pread(int, void*, size_t, off_t);
int async(int, size_t, off_t, u32, u32); int async(int, size_t, off_t, u32, u32);
int script(void *addr, u64 len, u64 chunk);
// ulib.c // ulib.c
int stat(char*, struct stat*); int stat(char*, struct stat*);
......
...@@ -10,21 +10,21 @@ using std::atomic; ...@@ -10,21 +10,21 @@ using std::atomic;
enum vmntype { EAGER, ONDEMAND }; enum vmntype { EAGER, ONDEMAND };
struct vmnode { struct vmnode {
u64 npages; const u64 npages;
char *page[128]; atomic<char*> page[128];
atomic<u64> ref; atomic<u64> ref;
enum vmntype type; const enum vmntype type;
struct inode *ip; struct inode *const ip;
u64 offset; const u64 offset;
u64 sz; const u64 sz;
vmnode(u64 npg, vmntype type = EAGER); vmnode(u64 npg, vmntype type = EAGER,
inode *i = 0, u64 off = 0, u64 s = 0);
~vmnode(); ~vmnode();
void decref(); void decref();
int allocpg(); int allocpg();
vmnode* copy(); vmnode* copy();
int load(inode *ip, u64 offset, u64 sz);
int demand_load(); int demand_load();
}; };
...@@ -49,7 +49,6 @@ struct vma : public range { ...@@ -49,7 +49,6 @@ struct vma : public range {
struct vmap { struct vmap {
struct crange cr; struct crange cr;
atomic<u64> ref; atomic<u64> ref;
u64 alloc;
pgmap *const pml4; // Page table pgmap *const pml4; // Page table
char *const kshared; char *const kshared;
...@@ -61,7 +60,7 @@ struct vmap { ...@@ -61,7 +60,7 @@ struct vmap {
void decref(); void decref();
vmap* copy(int share); vmap* copy(int share);
vma* lookup(uptr start, uptr len); vma* lookup(uptr start, uptr len);
int insert(vmnode *n, uptr va_start); int insert(vmnode *n, uptr va_start, int dotlb);
int remove(uptr start, uptr len); int remove(uptr start, uptr len);
int pagefault(uptr va, u32 err); int pagefault(uptr va, u32 err);
......
...@@ -44,6 +44,7 @@ OBJS = \ ...@@ -44,6 +44,7 @@ OBJS = \
trap.o \ trap.o \
trapasm.o \ trapasm.o \
wq.o \ wq.o \
script.o \
incbin.o incbin.o
OBJS := $(addprefix $(O)/kernel/, $(OBJS)) OBJS := $(addprefix $(O)/kernel/, $(OBJS))
......
...@@ -78,5 +78,6 @@ long (*syscalls[])(u64, u64, u64, u64, u64, u64) = { ...@@ -78,5 +78,6 @@ long (*syscalls[])(u64, u64, u64, u64, u64, u64) = {
SYSCALL(accept), SYSCALL(accept),
SYSCALL(pread), SYSCALL(pread),
SYSCALL(async), SYSCALL(async),
SYSCALL(script),
}; };
...@@ -54,18 +54,11 @@ dosegment(uptr a0, u64 a1) ...@@ -54,18 +54,11 @@ dosegment(uptr a0, u64 a1)
uptr va_end = PGROUNDUP(ph.vaddr + ph.memsz); uptr va_end = PGROUNDUP(ph.vaddr + ph.memsz);
int npg = (va_end - va_start) / PGSIZE; int npg = (va_end - va_start) / PGSIZE;
if (odp) { if ((vmn = new vmnode(npg, odp ? ONDEMAND : EAGER,
if ((vmn = new vmnode(npg, ONDEMAND)) == 0) args->ip, ph.offset, ph.filesz)) == 0)
goto bad;
} else {
if ((vmn = new vmnode(npg)) == 0)
goto bad;
}
if(vmn->load(args->ip, ph.offset, ph.filesz) < 0)
goto bad; goto bad;
if(args->vmap->insert(vmn, ph.vaddr) < 0) if(args->vmap->insert(vmn, ph.vaddr, 1) < 0)
goto bad; goto bad;
prof_end(dosegment_prof); prof_end(dosegment_prof);
...@@ -89,7 +82,7 @@ static void dostack(uptr a0, u64 a1) ...@@ -89,7 +82,7 @@ static void dostack(uptr a0, u64 a1)
// Allocate a one-page stack at the top of the (user) address space // Allocate a one-page stack at the top of the (user) address space
if((vmn = new vmnode(USTACKPAGES)) == 0) if((vmn = new vmnode(USTACKPAGES)) == 0)
goto bad; goto bad;
if(args->vmap->insert(vmn, USERTOP-(USTACKPAGES*PGSIZE)) < 0) if(args->vmap->insert(vmn, USERTOP-(USTACKPAGES*PGSIZE), 1) < 0)
goto bad; goto bad;
vmn = 0; vmn = 0;
...@@ -140,7 +133,7 @@ static void doheap(uptr a0, u64 a1) ...@@ -140,7 +133,7 @@ static void doheap(uptr a0, u64 a1)
// XXX pre-allocate 32 pages.. // XXX pre-allocate 32 pages..
if((vmn = new vmnode(32)) == 0) if((vmn = new vmnode(32)) == 0)
goto bad; goto bad;
if(args->vmap->insert(vmn, BRK) < 0) if(args->vmap->insert(vmn, BRK, 1) < 0)
goto bad; goto bad;
vmn = 0; vmn = 0;
prof_end(doheap_prof); prof_end(doheap_prof);
......
...@@ -277,7 +277,7 @@ inituser(void) ...@@ -277,7 +277,7 @@ inituser(void)
vmnode *vmn = new vmnode(PGROUNDUP(_initcode_size) / PGSIZE); vmnode *vmn = new vmnode(PGROUNDUP(_initcode_size) / PGSIZE);
if(vmn == 0) if(vmn == 0)
panic("userinit: vmn_allocpg"); panic("userinit: vmn_allocpg");
if(p->vmap->insert(vmn, 0) < 0) if(p->vmap->insert(vmn, 0, 1) < 0)
panic("userinit: vmap_insert"); panic("userinit: vmap_insert");
if(p->vmap->copyout(0, _initcode_start, _initcode_size) < 0) if(p->vmap->copyout(0, _initcode_start, _initcode_size) < 0)
panic("userinit: copyout"); panic("userinit: copyout");
...@@ -391,6 +391,7 @@ scheduler(void) ...@@ -391,6 +391,7 @@ scheduler(void)
if (idle[mycpu()->id]) { if (idle[mycpu()->id]) {
int worked; int worked;
do { do {
assert(mycpu()->ncli == 0);
worked = wq_trywork(); worked = wq_trywork();
} while(worked); } while(worked);
sti(); sti();
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
#include "cpu.hh" #include "cpu.hh"
#include "bits.hh" #include "bits.hh"
#include "kmtrace.hh" #include "kmtrace.hh"
#include "sched.h" #include "sched.hh"
#include "vm.hh" #include "vm.hh"
#include <stddef.h> #include <stddef.h>
......
#include "types.h"
#include "kernel.hh"
#include "spinlock.h"
#include "condvar.h"
#include "cpu.hh"
#include "proc.hh"
#include "fs.h"
#include "wq.hh"
#include "ipc.hh"
#include "vm.hh"
#include "file.hh"
void
script_mmap_work(struct work *w, void *a0, void *a1, void *a2, void *a3)
{
void *addr = (void *) a0;
u64 len = (u64) a1;
atomic<int> *donep = (atomic<int> *) a2;
struct proc *p = (struct proc *) a3;
vmnode *vmn = new vmnode(PGROUNDUP(len) / PGSIZE);
if(vmn == 0)
panic("sys_script: new vmnode");
if(p->vmap->insert(vmn, PGROUNDDOWN((u64)addr), 0) < 0)
panic("sys_script: insert");
*donep += 1;
}
long
sys_script(void *addr, u64 len, u64 chunk)
{
atomic<int> done;
done = 0;
int queued = 0;
char *q = (char*) addr;
while(q < (char*)addr + len){
u64 x = len - (q - (char*)addr);
if(x > chunk)
x = chunk;
struct work *w = allocwork();
if(w == 0)
panic("sys_script allocwork");
w->rip = (void*) script_mmap_work;
w->arg0 = (void *) q;
w->arg1 = (void *) x;
w->arg2 = (void *) &done;
w->arg3 = (void *) myproc();
if(wq_push(w) < 0)
panic("sys_script wq_push");
queued++;
q += chunk;
}
while(done < queued){
// yield();
wq_trywork();
}
tlbflush();
return 0;
}
...@@ -111,7 +111,7 @@ sys_map(void) ...@@ -111,7 +111,7 @@ sys_map(void)
if (vmn == 0) if (vmn == 0)
return -1; return -1;
if (myproc()->vmap->insert(vmn, PGROUNDDOWN(addr)) < 0) { if (myproc()->vmap->insert(vmn, PGROUNDDOWN(addr), 1) < 0) {
delete vmn; delete vmn;
return -1; return -1;
} }
......
...@@ -20,14 +20,17 @@ enum { vm_debug = 0 }; ...@@ -20,14 +20,17 @@ enum { vm_debug = 0 };
* vmnode * vmnode
*/ */
vmnode::vmnode(u64 npg, vmntype ntype) vmnode::vmnode(u64 npg, vmntype ntype, inode *i, u64 off, u64 s)
: npages(npg), ref(0), type(ntype), ip(0), offset(0), sz(0) : npages(npg), ref(0), type(ntype), ip(i), offset(off), sz(s)
{ {
if (npg > NELEM(page)) if (npg > NELEM(page))
panic("vmnode too big\n"); panic("vmnode too big\n");
memset(page, 0, sizeof(page)); memset(page, 0, sizeof(page));
if (type == EAGER) if (type == EAGER) {
assert(allocpg() == 0); assert(allocpg() == 0);
if (ip)
assert(demand_load() == 0);
}
} }
vmnode::~vmnode() vmnode::~vmnode()
...@@ -38,10 +41,8 @@ vmnode::~vmnode() ...@@ -38,10 +41,8 @@ vmnode::~vmnode()
page[i] = 0; page[i] = 0;
} }
} }
if (ip) { if (ip)
iput(ip); iput(ip);
ip = 0;
}
} }
void void
...@@ -55,9 +56,18 @@ int ...@@ -55,9 +56,18 @@ int
vmnode::allocpg() vmnode::allocpg()
{ {
for(u64 i = 0; i < npages; i++) { for(u64 i = 0; i < npages; i++) {
if((page[i] = kalloc()) == 0) if (page[i])
continue;
char *p = kalloc();
if (!p) {
cprintf("allocpg: out of memory, leaving half-filled vmnode\n");
return -1; return -1;
memset((char *) page[i], 0, PGSIZE); }
memset(p, 0, PGSIZE);
if(!cmpxch(&page[i], (char*) 0, p))
kfree(p);
} }
return 0; return 0;
} }
...@@ -65,25 +75,24 @@ vmnode::allocpg() ...@@ -65,25 +75,24 @@ vmnode::allocpg()
vmnode * vmnode *
vmnode::copy() vmnode::copy()
{ {
vmnode *c = new vmnode(npages, type); vmnode *c = new vmnode(npages, type,
if(c != 0) { (type==ONDEMAND) ? idup(ip) : 0,
c->type = type; offset, sz);
if (type == ONDEMAND) { if(c == 0)
c->ip = idup(ip); return 0;
c->offset = offset;
c->sz = c->sz; if (!page[0]) // If first page is absent, all pages are absent
} return c;
if (page[0]) { // If the first page is present, all of them are present
if (c->allocpg() < 0) { if (c->allocpg() < 0) {
cprintf("vmn_copy: out of memory\n"); cprintf("vmn_copy: out of memory\n");
delete c; delete c;
return 0; return 0;
}
for(u64 i = 0; i < npages; i++) {
memmove(c->page[i], page[i], PGSIZE);
}
}
} }
for(u64 i = 0; i < npages; i++)
if (page[i])
memmove(c->page[i], page[i], PGSIZE);
return c; return c;
} }
...@@ -97,24 +106,17 @@ vmnode::demand_load() ...@@ -97,24 +106,17 @@ vmnode::demand_load()
n = sz - i; n = sz - i;
else else
n = PGSIZE; n = PGSIZE;
/*
* Possible race condition with concurrent demand_load() calls,
* if the underlying inode's contents change..
*/
if (readi(ip, p, offset+i, n) != n) if (readi(ip, p, offset+i, n) != n)
return -1; return -1;
} }
return 0; return 0;
} }
int
vmnode::load(inode *iparg, u64 offarg, u64 szarg)
{
ip = iparg;
offset = offarg;
sz = szarg;
if (type == ONDEMAND)
return 0;
return demand_load();
}
/* /*
* vma * vma
*/ */
...@@ -138,11 +140,8 @@ vma::~vma() ...@@ -138,11 +140,8 @@ vma::~vma()
*/ */
vmap::vmap() vmap::vmap()
: cr(10), pml4(setupkvm()), kshared((char*) ksalloc(slab_kshared)) : cr(10), ref(1), pml4(setupkvm()), kshared((char*) ksalloc(slab_kshared))
{ {
ref = 1;
alloc = 0;
if (pml4 == 0) { if (pml4 == 0) {
cprintf("vmap_alloc: setupkvm out of memory\n"); cprintf("vmap_alloc: setupkvm out of memory\n");
goto err; goto err;
...@@ -173,7 +172,6 @@ vmap::~vmap() ...@@ -173,7 +172,6 @@ vmap::~vmap()
ksfree(slab_kshared, kshared); ksfree(slab_kshared, kshared);
if (pml4) if (pml4)
freevm(pml4); freevm(pml4);
alloc = 0;
} }
void void
...@@ -277,7 +275,7 @@ vmap::lookup(uptr start, uptr len) ...@@ -277,7 +275,7 @@ vmap::lookup(uptr start, uptr len)
} }
int int
vmap::insert(vmnode *n, uptr vma_start) vmap::insert(vmnode *n, uptr vma_start, int dotlb)
{ {
vma *e; vma *e;
...@@ -311,7 +309,8 @@ vmap::insert(vmnode *n, uptr vma_start) ...@@ -311,7 +309,8 @@ vmap::insert(vmnode *n, uptr vma_start)
break; break;
} }
}); });
tlbflush(); if(dotlb)
tlbflush();
return 0; return 0;
} }
......
...@@ -38,3 +38,4 @@ SYSCALL(listen) ...@@ -38,3 +38,4 @@ SYSCALL(listen)
SYSCALL(accept) SYSCALL(accept)
SYSCALL(pread) SYSCALL(pread)
SYSCALL(async) SYSCALL(async)
SYSCALL(script)
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论