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

half-working threads

上级 1944e2f1
...@@ -139,7 +139,7 @@ tags: $(OBJS) bootother.S _init ...@@ -139,7 +139,7 @@ tags: $(OBJS) bootother.S _init
vectors.S: vectors.pl vectors.S: vectors.pl
perl vectors.pl > vectors.S perl vectors.pl > vectors.S
ULIB = ulib.o usys.o printf.o umalloc.o ULIB = ulib.o usys.o printf.o umalloc.o uthread.o
_%: %.o $(ULIB) _%: %.o $(ULIB)
$(LD) $(LDFLAGS) -N -e main -Ttext 0 -o $@ $^ $(LD) $(LDFLAGS) -N -e main -Ttext 0 -o $@ $^
...@@ -172,6 +172,7 @@ UPROGS=\ ...@@ -172,6 +172,7 @@ UPROGS=\
_wc\ _wc\
_zombie\ _zombie\
_halt\ _halt\
_thrtest\
fs.img: mkfs README $(UPROGS) fs.img: mkfs README $(UPROGS)
./mkfs fs.img README $(UPROGS) ./mkfs fs.img README $(UPROGS)
......
...@@ -104,7 +104,7 @@ void addrun(struct proc *); ...@@ -104,7 +104,7 @@ void addrun(struct proc *);
struct proc* copyproc(struct proc*); struct proc* copyproc(struct proc*);
void delrun(struct proc*); void delrun(struct proc*);
void exit(void); void exit(void);
int fork(void); int fork(int);
int growproc(int); int growproc(int);
int kill(int); int kill(int);
void pinit(void); void pinit(void);
...@@ -171,7 +171,7 @@ struct vmnode * vmn_allocpg(uint); ...@@ -171,7 +171,7 @@ struct vmnode * vmn_allocpg(uint);
void vmn_free(struct vmnode *); void vmn_free(struct vmnode *);
int vmn_load(struct vmnode *, struct inode*, uint, uint); int vmn_load(struct vmnode *, struct inode*, uint, uint);
struct vmap * vmap_alloc(void); struct vmap * vmap_alloc(void);
void vmap_free(struct vmap *); void vmap_decref(struct vmap *);
int vmap_insert(struct vmap *, struct vmnode *n, uint); int vmap_insert(struct vmap *, struct vmnode *n, uint);
struct vma * vmap_lookup(struct vmap *, uint); struct vma * vmap_lookup(struct vmap *, uint);
struct vmap * vmap_copy(struct vmap *); struct vmap * vmap_copy(struct vmap *);
......
...@@ -121,7 +121,7 @@ exec(char *path, char **argv) ...@@ -121,7 +121,7 @@ exec(char *path, char **argv)
proc->tf->esp = sp; proc->tf->esp = sp;
switchuvm(proc); switchuvm(proc);
freevm(oldpgdir); freevm(oldpgdir);
vmap_free(oldvmap); vmap_decref(oldvmap);
return 0; return 0;
...@@ -132,7 +132,7 @@ exec(char *path, char **argv) ...@@ -132,7 +132,7 @@ exec(char *path, char **argv)
if(ip) if(ip)
iunlockput(ip); iunlockput(ip);
if(vmap) if(vmap)
vmap_free(vmap); vmap_decref(vmap);
if(vmn) if(vmn)
vmn_free(vmn); vmn_free(vmn);
return -1; return -1;
......
...@@ -40,7 +40,7 @@ forktest(void) ...@@ -40,7 +40,7 @@ forktest(void)
mtrace_enable_set(1, "xv6-forktest"); mtrace_enable_set(1, "xv6-forktest");
for(n=0; n<N; n++){ for(n=0; n<N; n++){
pid = fork(); pid = fork(0);
if(pid < 0) if(pid < 0)
break; break;
if(pid == 0) if(pid == 0)
......
...@@ -21,7 +21,7 @@ main(void) ...@@ -21,7 +21,7 @@ main(void)
for(;;){ for(;;){
printf(1, "init: starting sh\n"); printf(1, "init: starting sh\n");
pid = fork(); pid = fork(0);
if(pid < 0){ if(pid < 0){
printf(1, "init: fork failed\n"); printf(1, "init: fork failed\n");
exit(); exit();
......
...@@ -195,7 +195,7 @@ growproc(int n) ...@@ -195,7 +195,7 @@ growproc(int n)
// Sets up stack to return as if from system call. // Sets up stack to return as if from system call.
// Caller must set state of returned proc to RUNNABLE. // Caller must set state of returned proc to RUNNABLE.
int int
fork(void) fork(int flags)
{ {
int i, pid; int i, pid;
struct proc *np; struct proc *np;
...@@ -211,14 +211,20 @@ fork(void) ...@@ -211,14 +211,20 @@ fork(void)
return -1; return -1;
} }
// Copy process state from p. if(flags == 0) {
if((np->vmap = vmap_copy(proc->vmap)) == 0){ // Copy process state from p.
freevm(np->pgdir); if((np->vmap = vmap_copy(proc->vmap)) == 0){
kfree(np->kstack); freevm(np->pgdir);
np->kstack = 0; kfree(np->kstack);
np->state = UNUSED; np->kstack = 0;
return -1; np->state = UNUSED;
return -1;
}
} else {
np->vmap = proc->vmap;
__sync_fetch_and_add(&np->vmap->ref, 1);
} }
np->brk = proc->brk; np->brk = proc->brk;
np->parent = proc; np->parent = proc;
*np->tf = *proc->tf; *np->tf = *proc->tf;
...@@ -312,7 +318,7 @@ wait(void) ...@@ -312,7 +318,7 @@ wait(void)
kfree(p->kstack); kfree(p->kstack);
p->kstack = 0; p->kstack = 0;
freevm(p->pgdir); freevm(p->pgdir);
vmap_free(p->vmap); vmap_decref(p->vmap);
p->state = UNUSED; p->state = UNUSED;
p->pid = 0; p->pid = 0;
p->parent = 0; p->parent = 0;
......
...@@ -49,6 +49,7 @@ struct vma { ...@@ -49,6 +49,7 @@ struct vma {
struct vmap { struct vmap {
struct vma e[16]; struct vma e[16];
struct spinlock lock; // serialize map/lookup/unmap struct spinlock lock; // serialize map/lookup/unmap
uint ref;
uint alloc; uint alloc;
}; };
......
...@@ -184,7 +184,7 @@ fork1(void) ...@@ -184,7 +184,7 @@ fork1(void)
{ {
int pid; int pid;
pid = fork(); pid = fork(0);
if(pid == -1) if(pid == -1)
panic("fork"); panic("fork");
return pid; return pid;
......
...@@ -20,7 +20,7 @@ main(int argc, char *argv[]) ...@@ -20,7 +20,7 @@ main(int argc, char *argv[])
printf(1, "stressfs starting\n"); printf(1, "stressfs starting\n");
for(i = 0; i < 4; i++) for(i = 0; i < 4; i++)
if(fork() > 0) if(fork(0) > 0)
break; break;
printf(1, "%d\n", i); printf(1, "%d\n", i);
......
...@@ -11,7 +11,11 @@ ...@@ -11,7 +11,11 @@
int int
sys_fork(void) sys_fork(void)
{ {
return fork(); int flags;
if(argint(0, &flags) < 0)
return -1;
return fork(flags);
} }
int int
......
struct stat; struct stat;
// system calls // system calls
int fork(void); int fork(int);
int exit(void) __attribute__((noreturn)); int exit(void) __attribute__((noreturn));
int wait(void); int wait(void);
int pipe(int*); int pipe(int*);
...@@ -37,3 +37,7 @@ void* memset(void*, int, uint); ...@@ -37,3 +37,7 @@ void* memset(void*, int, uint);
void* malloc(uint); void* malloc(uint);
void free(void*); void free(void*);
int atoi(const char*); int atoi(const char*);
// uthread.S
int forkt(void *sp, void *pc);
...@@ -210,7 +210,7 @@ pipe1(void) ...@@ -210,7 +210,7 @@ pipe1(void)
printf(1, "pipe() failed\n"); printf(1, "pipe() failed\n");
exit(); exit();
} }
pid = fork(); pid = fork(0);
seq = 0; seq = 0;
if(pid == 0){ if(pid == 0){
close(fds[0]); close(fds[0]);
...@@ -244,7 +244,7 @@ pipe1(void) ...@@ -244,7 +244,7 @@ pipe1(void)
close(fds[0]); close(fds[0]);
wait(); wait();
} else { } else {
printf(1, "fork() failed\n"); printf(1, "fork(0) failed\n");
exit(); exit();
} }
printf(1, "pipe1 ok\n"); printf(1, "pipe1 ok\n");
...@@ -258,18 +258,18 @@ preempt(void) ...@@ -258,18 +258,18 @@ preempt(void)
int pfds[2]; int pfds[2];
printf(1, "preempt: "); printf(1, "preempt: ");
pid1 = fork(); pid1 = fork(0);
if(pid1 == 0) if(pid1 == 0)
for(;;) for(;;)
; ;
pid2 = fork(); pid2 = fork(0);
if(pid2 == 0) if(pid2 == 0)
for(;;) for(;;)
; ;
pipe(pfds); pipe(pfds);
pid3 = fork(); pid3 = fork(0);
if(pid3 == 0){ if(pid3 == 0){
close(pfds[0]); close(pfds[0]);
if(write(pfds[1], "x", 1) != 1) if(write(pfds[1], "x", 1) != 1)
...@@ -303,7 +303,7 @@ exitwait(void) ...@@ -303,7 +303,7 @@ exitwait(void)
int i, pid; int i, pid;
for(i = 0; i < 100; i++){ for(i = 0; i < 100; i++){
pid = fork(); pid = fork(0);
if(pid < 0){ if(pid < 0){
printf(1, "fork failed\n"); printf(1, "fork failed\n");
return; return;
...@@ -328,7 +328,7 @@ mem(void) ...@@ -328,7 +328,7 @@ mem(void)
printf(1, "mem test\n"); printf(1, "mem test\n");
ppid = getpid(); ppid = getpid();
if((pid = fork()) == 0){ if((pid = fork(0)) == 0){
m1 = 0; m1 = 0;
while((m2 = malloc(10001)) != 0){ while((m2 = malloc(10001)) != 0){
*(char**)m2 = m1; *(char**)m2 = m1;
...@@ -369,7 +369,7 @@ sharedfd(void) ...@@ -369,7 +369,7 @@ sharedfd(void)
printf(1, "fstests: cannot open sharedfd for writing"); printf(1, "fstests: cannot open sharedfd for writing");
return; return;
} }
pid = fork(); pid = fork(0);
memset(buf, pid==0?'c':'p', sizeof(buf)); memset(buf, pid==0?'c':'p', sizeof(buf));
for(i = 0; i < 1000; i++){ for(i = 0; i < 1000; i++){
if(write(fd, buf, sizeof(buf)) != sizeof(buf)){ if(write(fd, buf, sizeof(buf)) != sizeof(buf)){
...@@ -417,7 +417,7 @@ twofiles(void) ...@@ -417,7 +417,7 @@ twofiles(void)
unlink("f1"); unlink("f1");
unlink("f2"); unlink("f2");
pid = fork(); pid = fork(0);
if(pid < 0){ if(pid < 0){
printf(1, "fork failed\n"); printf(1, "fork failed\n");
return; return;
...@@ -477,7 +477,7 @@ createdelete(void) ...@@ -477,7 +477,7 @@ createdelete(void)
char name[32]; char name[32];
printf(1, "createdelete test\n"); printf(1, "createdelete test\n");
pid = fork(); pid = fork(0);
if(pid < 0){ if(pid < 0){
printf(1, "fork failed\n"); printf(1, "fork failed\n");
exit(); exit();
...@@ -672,7 +672,7 @@ concreate(void) ...@@ -672,7 +672,7 @@ concreate(void)
for(i = 0; i < 40; i++){ for(i = 0; i < 40; i++){
file[1] = '0' + i; file[1] = '0' + i;
unlink(file); unlink(file);
pid = fork(); pid = fork(0);
if(pid && (i % 3) == 1){ if(pid && (i % 3) == 1){
link("C0", file); link("C0", file);
} else if(pid == 0 && (i % 5) == 1){ } else if(pid == 0 && (i % 5) == 1){
...@@ -720,7 +720,7 @@ concreate(void) ...@@ -720,7 +720,7 @@ concreate(void)
for(i = 0; i < 40; i++){ for(i = 0; i < 40; i++){
file[1] = '0' + i; file[1] = '0' + i;
pid = fork(); pid = fork(0);
if(pid < 0){ if(pid < 0){
printf(1, "fork failed\n"); printf(1, "fork failed\n");
exit(); exit();
...@@ -1207,7 +1207,7 @@ forktest(void) ...@@ -1207,7 +1207,7 @@ forktest(void)
printf(1, "fork test\n"); printf(1, "fork test\n");
for(n=0; n<1000; n++){ for(n=0; n<1000; n++){
pid = fork(); pid = fork(0);
if(pid < 0) if(pid < 0)
break; break;
if(pid == 0) if(pid == 0)
...@@ -1256,7 +1256,7 @@ sbrktest(void) ...@@ -1256,7 +1256,7 @@ sbrktest(void)
*b = 1; *b = 1;
a = b + 1; a = b + 1;
} }
pid = fork(); pid = fork(0);
if(pid < 0){ if(pid < 0){
printf(stdout, "sbrk test fork failed\n"); printf(stdout, "sbrk test fork failed\n");
exit(); exit();
...@@ -1324,7 +1324,7 @@ sbrktest(void) ...@@ -1324,7 +1324,7 @@ sbrktest(void)
// can we read the kernel's memory? // can we read the kernel's memory?
for(a = (char*)(640*1024); a < (char*)2000000; a += 50000){ for(a = (char*)(640*1024); a < (char*)2000000; a += 50000){
ppid = getpid(); ppid = getpid();
pid = fork(); pid = fork(0);
if(pid < 0){ if(pid < 0){
printf(stdout, "fork failed\n"); printf(stdout, "fork failed\n");
exit(); exit();
...@@ -1345,7 +1345,7 @@ sbrktest(void) ...@@ -1345,7 +1345,7 @@ sbrktest(void)
exit(); exit();
} }
for(i = 0; i < sizeof(pids)/sizeof(pids[0]); i++){ for(i = 0; i < sizeof(pids)/sizeof(pids[0]); i++){
if((pids[i] = fork()) == 0){ if((pids[i] = fork(0)) == 0){
// allocate the full 640K // allocate the full 640K
sbrk((640 * 1024) - (uint)sbrk(0)); sbrk((640 * 1024) - (uint)sbrk(0));
write(fds[1], "x", 1); write(fds[1], "x", 1);
...@@ -1398,7 +1398,7 @@ validatetest(void) ...@@ -1398,7 +1398,7 @@ validatetest(void)
hi = 1100*1024; hi = 1100*1024;
for(p = 0; p <= (uint)hi; p += 4096){ for(p = 0; p <= (uint)hi; p += 4096){
if((pid = fork()) == 0){ if((pid = fork(0)) == 0){
// try to crash the kernel by passing in a badly placed integer // try to crash the kernel by passing in a badly placed integer
validateint((int*)p); validateint((int*)p);
exit(); exit();
...@@ -1443,7 +1443,7 @@ bigargtest(void) ...@@ -1443,7 +1443,7 @@ bigargtest(void)
int pid, ppid; int pid, ppid;
ppid = getpid(); ppid = getpid();
pid = fork(); pid = fork(0);
if(pid == 0){ if(pid == 0){
char *args[32+1]; char *args[32+1];
int i; int i;
......
...@@ -270,13 +270,14 @@ vmap_alloc(void) ...@@ -270,13 +270,14 @@ vmap_alloc(void)
m->e[j].lock.name = "vma"; m->e[j].lock.name = "vma";
} }
m->lock.name = "vmap"; m->lock.name = "vmap";
m->ref = 1;
return m; return m;
} }
} }
panic("out of vmaps"); panic("out of vmaps");
} }
void static void
vmap_free(struct vmap *m) vmap_free(struct vmap *m)
{ {
for(uint i = 0; i < sizeof(m->e) / sizeof(m->e[0]); i++) for(uint i = 0; i < sizeof(m->e) / sizeof(m->e[0]); i++)
...@@ -285,6 +286,13 @@ vmap_free(struct vmap *m) ...@@ -285,6 +286,13 @@ vmap_free(struct vmap *m)
m->alloc = 0; m->alloc = 0;
} }
void
vmap_decref(struct vmap *m)
{
if(__sync_sub_and_fetch(&m->ref, 1) == 0)
vmap_free(m);
}
int int
vmap_insert(struct vmap *m, struct vmnode *n, uint va_start) vmap_insert(struct vmap *m, struct vmnode *n, uint va_start)
{ {
...@@ -346,7 +354,7 @@ vmap_copy(struct vmap *m) ...@@ -346,7 +354,7 @@ vmap_copy(struct vmap *m)
c->e[i].n = vmn_copy(m->e[i].n); c->e[i].n = vmn_copy(m->e[i].n);
if(c->e[i].n == 0) { if(c->e[i].n == 0) {
release(&m->lock); release(&m->lock);
vmap_free(c); vmap_decref(c);
return 0; return 0;
} }
__sync_fetch_and_add(&c->e[i].n->ref, 1); __sync_fetch_and_add(&c->e[i].n->ref, 1);
......
#pragma once
// Routines to let C code use special x86 instructions. // Routines to let C code use special x86 instructions.
static inline uchar static inline uchar
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
int int
main(void) main(void)
{ {
if(fork() > 0) if(fork(0) > 0)
sleep(5); // Let child exit before parent. sleep(5); // Let child exit before parent.
exit(); exit();
} }
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论