Made fork/exec slow but correct.
authorAndrew Waterman <waterman@parcad.millennium.berkeley.edu>
Wed, 27 Jan 2010 21:32:45 +0000 (13:32 -0800)
committerAndrew Waterman <waterman@parcad.millennium.berkeley.edu>
Wed, 27 Jan 2010 21:32:45 +0000 (13:32 -0800)
Since mmap is actually used now, we need to scan the whole
virtual address range to determine what to copy or unmap.
But this is really slow, so need to walk the pagetable for
efficiency (using env_user_mem_walk or the like)

kern/src/syscall.c
user/parlib/src/parlibmain.c
user/parlib/src/sparc/newlib_backend.c

index 3a372f3..a0f7daa 100644 (file)
@@ -102,12 +102,13 @@ static ssize_t sys_fork(env_t* e)
                        cache_color_alloc(llc_cache, env->cache_colors_map);
 
        // copy page table and page contents.
-       // TODO: does not work with mmap.  only text, heap, stack are copied.
        for(char* va = 0; va < (char*)UTOP; va += PGSIZE)
        {
-               // copy [0,heaptop] and [stackbot,utop]
-               if(va == env->heap_top)
-                       va = (char*)USTACKBOT;
+               // TODO: this is slow but correct.
+               // don't skip any va's so fork will copy mmap'd pages
+               // // copy [0,heaptop] and [stackbot,utop]
+               //if(va == ROUNDUP(env->heap_top,PGSIZE))
+               //      va = (char*)USTACKBOT;
 
                int perms = get_va_perms(e->env_pgdir,va);
                if(perms)
@@ -178,15 +179,13 @@ static ssize_t sys_trywait(env_t* e, pid_t pid, int* status)
 }
 
 static ssize_t sys_exec(env_t* e, void *DANGEROUS binary_buf, size_t len,
-                        void*DANGEROUS arg, void*DANGEROUS env)
+                        procinfo_t*DANGEROUS procinfo)
 {
        // TODO: right now we only support exec for single-core processes
        if(e->state != PROC_RUNNING_S)
                return -1;
 
-       if(memcpy_from_user(e,e->env_procinfo->argv_buf,arg,PROCINFO_MAX_ARGV_SIZE))
-               return -1;
-       if(memcpy_from_user(e,e->env_procinfo->env_buf,env,PROCINFO_MAX_ENV_SIZE))
+       if(memcpy_from_user(e,e->env_procinfo,procinfo,sizeof(*procinfo)))
                return -1;
 
        void* binary = kmalloc(len,0);
@@ -198,9 +197,11 @@ static ssize_t sys_exec(env_t* e, void *DANGEROUS binary_buf, size_t len,
                return -1;
        }
 
-       // TODO: this breaks with mmap
-       env_segment_free(e,0,(intptr_t)e->heap_top);
-       env_segment_free(e,(void*)USTACKBOT,USTACKTOP-USTACKBOT);
+       // TODO: this is slow but correct.
+       // don't skip any va's so exec behaves right
+       env_segment_free(e,0,USTACKTOP);
+       //env_segment_free(e,0,ROUNDUP((intptr_t)e->heap_top,PGSIZE));
+       //env_segment_free(e,(void*)USTACKBOT,USTACKTOP-USTACKBOT);
 
        proc_init_trapframe(current_tf,0);
        env_load_icode(e,NULL,binary,len);
@@ -585,7 +586,7 @@ static error_t sys_proc_run(struct proc *p, unsigned pid)
 static void* sys_brk(struct proc *p, void* addr) {
        size_t range;
 
-       if((addr < p->heap_bottom) || (addr >= (void*)USTACKBOT))
+       if((addr < p->heap_bottom) || (addr >= (void*)UMMAP_START))
                goto out;
 
        if (addr > p->heap_top) {
@@ -662,6 +663,19 @@ intreg_t syscall(struct proc *p, uintreg_t syscallno, uintreg_t a1,
                [SYS_write] = (syscall_t)sys_write,
                [SYS_open] = (syscall_t)sys_open,
                [SYS_close] = (syscall_t)sys_close,
+               [SYS_fstat] = (syscall_t)sys_fstat,
+               [SYS_stat] = (syscall_t)sys_stat,
+               [SYS_lstat] = (syscall_t)sys_lstat,
+               [SYS_fcntl] = (syscall_t)sys_fcntl,
+               [SYS_access] = (syscall_t)sys_access,
+               [SYS_umask] = (syscall_t)sys_umask,
+               [SYS_chmod] = (syscall_t)sys_chmod,
+               [SYS_lseek] = (syscall_t)sys_lseek,
+               [SYS_link] = (syscall_t)sys_link,
+               [SYS_unlink] = (syscall_t)sys_unlink,
+               [SYS_chdir] = (syscall_t)sys_chdir,
+               [SYS_getcwd] = (syscall_t)sys_getcwd,
+               [SYS_gettimeofday] = (syscall_t)sys_gettimeofday,
        #endif
        };
 
index 4e091e4..2276833 100644 (file)
@@ -40,7 +40,7 @@ void parlib_ctors()
 // build argv from procinfo.argv_buf
 char** parlib_build_argc_argv(char* buf, int* argc)
 {
-       intreg_t* offset = (intreg_t*)buf;
+       char** offset = (char**)buf;
        for(*argc = 0; offset[*argc]; (*argc)++)
                ;
 
@@ -48,7 +48,7 @@ char** parlib_build_argc_argv(char* buf, int* argc)
        assert(argv);
        for(int i = 0; i < *argc; i++)
        {
-               argv[i] = strdup(buf + offset[i]);
+               argv[i] = strdup(offset[i]);
                assert(argv[i]);
        }
        argv[*argc] = 0;
index e120a56..81f612c 100644 (file)
@@ -423,7 +423,7 @@ fork(void)
 }
 
 static int
-pack_argv(const char* const argv[], char* buf, size_t bufsz)
+pack_argv(const char* const argv[], void* base, char* buf, size_t bufsz)
 {
        int argc = 0, size = sizeof(intreg_t);
        while(argv[argc])
@@ -436,11 +436,11 @@ pack_argv(const char* const argv[], char* buf, size_t bufsz)
                return -1;
 
        intreg_t* offset = (intreg_t*)buf;
-       offset[0] = (argc+1)*sizeof(intreg_t);
+       offset[0] = (argc+1)*sizeof(intreg_t)+(intreg_t)base;
        for(int i = 0; i < argc; i++)
        {
                int len = strlen(argv[i])+1;
-               memcpy(buf+offset[i],argv[i],len);
+               memcpy(buf+offset[i]-(intreg_t)base,argv[i],len);
                offset[i+1] = offset[i]+len;
        }
        offset[argc] = 0;
@@ -495,9 +495,9 @@ readfile(const char* filename, void** binary, int* size)
 int
 execve(const char* name, char* const argv[], char* const env[])
 {
-       char argv_buf[PROCINFO_MAX_ARGV_SIZE],env_buf[PROCINFO_MAX_ENV_SIZE];
-       if(pack_argv(argv,argv_buf,PROCINFO_MAX_ARGV_SIZE) ||
-          pack_argv(env,env_buf,PROCINFO_MAX_ENV_SIZE))
+       procinfo_t pi;
+       if(pack_argv(argv,procinfo.argv_buf,pi.argv_buf,PROCINFO_MAX_ARGV_SIZE)
+          || pack_argv(env,procinfo.env_buf,pi.env_buf,PROCINFO_MAX_ENV_SIZE))
        {
                errno = ENOMEM;
                return -1;
@@ -509,7 +509,7 @@ execve(const char* name, char* const argv[], char* const env[])
                return -1;
 
        return syscall(SYS_exec,(intreg_t)binary,(intreg_t)binarysz,
-                       (intreg_t)argv_buf,(intreg_t)env_buf,0);
+                       (intreg_t)&pi,0,0);
 }
 
 int
@@ -631,6 +631,8 @@ lseek(int fd, off_t ptr, int dir)
 ssize_t
 write(int fd, const void* ptr, size_t len)
 {
+       return syscall(SYS_write,fd,ptr,len,0,0);
+
        for(int pos = 0; pos < len; )
        {
                int thislen = MIN(PGSIZE,len-pos);
@@ -652,6 +654,8 @@ write(int fd, const void* ptr, size_t len)
 ssize_t
 read(int fd, void* ptr, size_t len)
 {
+       return syscall(SYS_read,fd,ptr,len,0,0);
+
        for(int pos = 0; pos < len; )
        {
                int thislen = MIN(PGSIZE,len-pos);
@@ -675,10 +679,15 @@ read(int fd, void* ptr, size_t len)
 int
 open(const char* name, int flags, ...)
 {
-       va_list vl;
-       va_start(vl,flags);
-       int mode = va_arg(vl,int);
-       va_end(vl);
+       int mode;
+       if(flags & O_CREAT)
+       {
+               va_list vl;
+               va_start(vl,flags);
+               mode = va_arg(vl,int);
+               va_end(vl);
+       }
+       return syscall(SYS_open,name,flags,mode,0,0);
 
        size_t len = strlen(name)+1;
        if(len > RAMP_MAXPATH)
@@ -691,6 +700,8 @@ open(const char* name, int flags, ...)
 int
 close(int fd)
 {
+       return syscall(SYS_close,fd,0,0,0,0);
+
        return fe(close,fd,0,0,0);
 }
 
@@ -718,11 +729,7 @@ gettimeofday(struct timeval* tp, void* tzp)
 {
        static struct timeval tp0 __attribute__((aligned(sizeof(*tp))));
        if(tp0.tv_sec == 0)
-       {
-               int ret = fe(gettimeofday,&tp0,0,0,OUT0);
-               if(ret)
-                       return ret;
-       }
+               tp0.tv_sec = fe(time,0,0,0,0);
 
        long long dt = read_tsc();
        tp->tv_sec = tp0.tv_sec + dt/procinfo.tsc_freq;