Sped up fork/exec significantly
authorAndrew Waterman <waterman@ubuntu.(none)>
Thu, 14 Jan 2010 20:05:51 +0000 (12:05 -0800)
committerAndrew Waterman <waterman@ubuntu.(none)>
Thu, 14 Jan 2010 20:05:51 +0000 (12:05 -0800)
It's still not copy on write, but it's much faster now.
Two main changes: don't have env_segment_free operate
on the entire address space, but rather just the text,
heap, data, and stack.  Also, I implemented pagecopy,
which is like memcpy but assumes a large size/alignment

kern/include/page_alloc.h
kern/include/string.h
kern/src/env.c
kern/src/mm.c
kern/src/page_alloc.c
kern/src/string.c
kern/src/syscall.c
user/parlib/src/hart.c

index 46e797b..acae53d 100644 (file)
@@ -41,7 +41,7 @@ extern page_list_t LCKD(&colored_page_free_list_lock) * RO CT(llc_num_colors)
 void page_alloc_init(void);
 void colored_page_alloc_init(void);
 
-error_t upage_alloc(struct proc* p, page_t *SAFE *page);
+error_t upage_alloc(struct proc* p, page_t *SAFE *page, int zero);
 error_t kpage_alloc(page_t *SAFE *page);
 error_t upage_alloc_specific(struct proc* p, page_t *SAFE *page, size_t ppn);
 error_t kpage_alloc_specific(page_t *SAFE *page, size_t ppn);
index dd8cdb1..bbb4168 100644 (file)
@@ -23,6 +23,7 @@ void * (DMEMSET(1, 2, 3) memset)(void* p, int what, size_t sz);
 int    (DMEMCMP(1, 2, 3) memcmp)(const void* s1, const void* s2, size_t sz);
 void * (DMEMCPY(1, 2, 3) memcpy)(void* dst, const void* src, size_t sz);
 void * (DMEMCPY(1, 2, 3) memmove)(void *dst, const void* src, size_t sz);
+void * pagecopy(void* dst, void* src);
 
 void *BND(s,s+len)     memfind(const void *COUNT(len) s, int c, size_t len);
 
index e837f6a..696e373 100644 (file)
@@ -83,7 +83,7 @@ WRITES(e->env_pgdir, e->env_cr3, e->env_procinfo, e->env_procdata)
         * procinfo structure into the page table
         */
        for(int i=0; i<PROCINFO_NUM_PAGES; i++) {
-               if(upage_alloc(e, &pginfo[i]) < 0)
+               if(upage_alloc(e, &pginfo[i],1) < 0)
                        goto env_setup_vm_error;
                if(page_insert(e->env_pgdir, pginfo[i], (void*SNT)(UINFO + i*PGSIZE),
                               PTE_USER_RO) < 0)
@@ -95,7 +95,7 @@ WRITES(e->env_pgdir, e->env_cr3, e->env_procinfo, e->env_procdata)
         * procdata structure into the page table
         */
        for(int i=0; i<PROCDATA_NUM_PAGES; i++) {
-               if(upage_alloc(e, &pgdata[i]) < 0)
+               if(upage_alloc(e, &pgdata[i],1) < 0)
                        goto env_setup_vm_error;
                if(page_insert(e->env_pgdir, pgdata[i], (void*SNT)(UDATA + i*PGSIZE),
                               PTE_USER_RW) < 0)
@@ -109,16 +109,13 @@ WRITES(e->env_pgdir, e->env_cr3, e->env_procinfo, e->env_procdata)
        e->env_procinfo = (procinfo_t *SAFE) TC(page2kva(pginfo[0]));
        e->env_procdata = (procdata_t *SAFE) TC(page2kva(pgdata[0]));
 
-       memset(e->env_procinfo, 0, sizeof(procinfo_t));
-       memset(e->env_procdata, 0, sizeof(procdata_t));
-
        /* Finally, set up the Global Shared Data page for all processes.
         * Can't be trusted, but still very useful at this stage for us.
         * Consider removing when we have real processes.
         * (TODO).  Note the page is alloced only the first time through
         */
        if (!shared_page) {
-               if(upage_alloc(e, &shared_page) < 0)
+               if(upage_alloc(e, &shared_page,1) < 0)
                        goto env_setup_vm_error;
                // Up it, so it never goes away.  One per user, plus one from page_alloc
                // This is necessary, since it's in the per-process range of memory that
@@ -176,7 +173,7 @@ env_segment_alloc(env_t *e, void *SNT va, size_t len)
                pte = pgdir_walk(e->env_pgdir, start, 0);
                if (pte && *pte & PTE_P)
                        continue;
-               if ((r = upage_alloc(e, &page)) < 0)
+               if ((r = upage_alloc(e, &page, 1)) < 0)
                        panic("env_segment_alloc: %e", r);
                page_insert(e->env_pgdir, page, start, PTE_USER_RW);
        }
index b5d543e..5aeaba4 100644 (file)
@@ -54,7 +54,7 @@ void *mmap(struct proc *p, uintptr_t addr, size_t len, int prot, int flags,
        }
        page_t *a_page;
        for (int i = 0; i < num_pages; i++) {
-               if (upage_alloc(p, &a_page))
+               if (upage_alloc(p, &a_page, 1))
                        goto mmap_abort;
                // TODO: give them the permissions they actually want
                if (page_insert(p->env_pgdir, a_page, (void*SNT)addr + i*PGSIZE,
index 6fdbf98..f6a43c2 100644 (file)
@@ -114,7 +114,7 @@ static error_t __page_alloc_specific(page_t** page, size_t ppn)
  * @return ESUCCESS on success
  * @return -ENOMEM  otherwise
  */
-error_t upage_alloc(struct proc* p, page_t** page)
+error_t upage_alloc(struct proc* p, page_t** page, int zero)
 {
        spin_lock_irqsave(&colored_page_free_list_lock);
        ssize_t ret = __colored_page_alloc(p->cache_colors_map, 
@@ -123,7 +123,8 @@ error_t upage_alloc(struct proc* p, page_t** page)
 
        if(ret >= 0)
        {
-               memset(page2kva(*page),0,PGSIZE);
+               if(zero)
+                       memset(page2kva(*page),0,PGSIZE);
                p->next_cache_color = (ret + 1) & (llc_cache->num_colors-1);
                return 0;
        }
index ba7ab14..2828ae4 100644 (file)
@@ -5,6 +5,7 @@
 #endif
 
 #include <string.h>
+#include <ros/memlayout.h>
 
 int
 strlen(const char *s)
@@ -182,6 +183,25 @@ memcpy16(uint32_t *COUNT(n/sizeof(uint32_t)) _dst,
 }
 
 void *
+pagecopy(void* dst, void* src)
+{
+       uint64_t* s = (uint64_t*)src;
+       uint64_t* d = (uint64_t*)dst;
+       for(int i = 0; i < PGSIZE/sizeof(uint64_t); i += 8)
+       {
+               d[i+0] = s[i+0];
+               d[i+1] = s[i+1];
+               d[i+2] = s[i+2];
+               d[i+3] = s[i+3];
+               d[i+4] = s[i+4];
+               d[i+5] = s[i+5];
+               d[i+6] = s[i+6];
+               d[i+7] = s[i+7];
+       }
+       return dst;
+}
+
+void *
 memset(void *COUNT(_n) v, int c, size_t _n)
 {
        char *BND(v,v+_n) p;
index d5c9b00..47c746f 100644 (file)
@@ -110,12 +110,15 @@ static ssize_t sys_fork(env_t* e)
                        va = (char*)USTACKBOT;
 
                int perms = get_va_perms(e->env_pgdir,va);
-               if(perms) // I think this should always be true
+               if(perms)
                {
                        page_t* pp;
-                       assert(upage_alloc(env,&pp) == 0);
+                       assert(upage_alloc(env,&pp,0) == 0);
                        assert(page_insert(env->env_pgdir,pp,va,perms) == 0);
-                       assert(memcpy_from_user(e,page2kva(pp),va,PGSIZE) == 0);
+
+                       pte_t* pte = pgdir_walk(e->env_pgdir,va,0);
+                       assert(pte);
+                       pagecopy(page2kva(pp),ppn2kva(PTE2PPN(*pte)));
                }
        }
 
@@ -195,18 +198,13 @@ static ssize_t sys_exec(env_t* e, void *DANGEROUS binary_buf, size_t len,
                return -1;
        }
 
-       // TODO: this is probably slow.  as with fork, should walk page table
-       env_segment_free(e,0,USTACKTOP);
+       // TODO: this breaks with mmap
+       env_segment_free(e,0,(intptr_t)e->heap_top);
+       env_segment_free(e,(void*)USTACKBOT,USTACKTOP-USTACKBOT);
 
        env_load_icode(e,NULL,binary,len);
        proc_init_trapframe(current_tf,0);
 
-       /*printk("[PID %d] exec ",e->pid);
-       char argv[PROCINFO_MAX_ARGV_SIZE];
-       int* offsets = (int*)e->env_procinfo->argv_buf;
-       for(int i = 0; offsets[i]; i++)
-               printk("%s%c",e->env_procinfo->argv_buf+offsets[i],offsets[i+1] ? ' ' : '\n');*/
-
        kfree(binary);
        return 0;
 }
@@ -327,7 +325,7 @@ static ssize_t sys_shared_page_alloc(env_t* p1,
                return -EBADPROC;
 
        page_t* page;
-       error_t e = upage_alloc(p1, &page);
+       error_t e = upage_alloc(p1, &page,1);
        if (e < 0) {
                proc_decref(p2, 1);
                return e;
@@ -410,7 +408,7 @@ static void sys_cache_buster(struct proc *p, uint32_t num_writes,
        if (num_pages) {
                spin_lock(&buster_lock);
                for (int i = 0; i < MIN(num_pages, MAX_PAGES); i++) {
-                       upage_alloc(p, &a_page[i]);
+                       upage_alloc(p, &a_page[i],1);
                        page_insert(p->env_pgdir, a_page[i], (void*)INSERT_ADDR + PGSIZE*i,
                                    PTE_USER_RW);
                }
index 61819b7..6460a98 100644 (file)
@@ -30,7 +30,7 @@ static void _hart_init()
 error_t hart_request(size_t k)
 {
        size_t i,j;
-       const int user_stack_size = 1024*1024, tls_size = PARLIB_TLS_SIZE;
+       const int user_stack_size = PARLIB_TLS_SIZE, tls_size = PARLIB_TLS_SIZE;
 
        extern void** stack_ptr_array;
        extern void** tls_array;