]> Zhao Yanbai Git Server - minix.git/commitdiff
vm: replace phys avl by array
authorBen Gras <ben@minix3.org>
Mon, 17 Dec 2012 18:26:52 +0000 (18:26 +0000)
committerBen Gras <ben@minix3.org>
Wed, 26 Dec 2012 16:14:41 +0000 (16:14 +0000)
 . make vm be able to use malloc() by overriding brk()
   and minix_mmap() functions
 . phys regions can then be malloc()ed and free()d instead
   of being in an avl tree, which is slightly faster
 . 'offset' field in phys_region can go too (offset is implied
   by position in array) but leads to bigger code changes

15 files changed:
lib/libc/stdlib/malloc.c
servers/vm/Makefile
servers/vm/arch/i386/pagetable.c
servers/vm/mem_anon_contig.c
servers/vm/mem_shared.c
servers/vm/pb.c
servers/vm/phys_region.h
servers/vm/physravl.c [deleted file]
servers/vm/physravl.h [deleted file]
servers/vm/physravl_defs.h [deleted file]
servers/vm/proto.h
servers/vm/region.c
servers/vm/region.h
servers/vm/utility.c
servers/vm/vmproc.h

index 2578b32006823437efe525086bf4185ec4498e6b..a07a572169b0d6293f2b9f3d951bbc9aba6373e9 100644 (file)
@@ -95,6 +95,13 @@ void utrace(struct ut *, int);
 #   define _MALLOC_UNLOCK()            if (__isthreaded) _SPINUNLOCK(&thread_lock);
 #endif /* __FreeBSD__ */
 
+/* #undef these things so that malloc uses the non-internal symbols.
+ * This is necessary for VM to be able to define its own versions, and
+ * use this malloc.
+ */
+#undef minix_mmap
+#undef minix_munmap
+
 #include <assert.h>
 
 #include <sys/types.h>
index 22edc6ded25bb49b7ac303996205fcf5a6bf0d87..c87f50a0b0c696c1a12ae9c1651b8933f285164a 100644 (file)
@@ -4,7 +4,7 @@
 PROG=  vm
 SRCS=  main.c alloc.c utility.c exit.c fork.c break.c \
        mmap.c slaballoc.c region.c pagefaults.c \
-       physravl.c rs.c queryexit.c yieldedavl.c regionavl.c pb.c \
+       rs.c queryexit.c yieldedavl.c regionavl.c pb.c \
        mem_anon.c mem_directphys.c mem_anon_contig.c mem_shared.c
 
 DPADD+=        ${LIBSYS}
index 9ceac74095b2ad272e3229ed96ab4769cba47e3d..19051299b9e5ad814703d730ebf19828dc382fe3 100644 (file)
@@ -54,25 +54,22 @@ struct vmproc *vmprocess = &vmproc[VM_PROC_NR];
  * circular dependency on allocating memory and writing it into VM's
  * page table.
  */
-#if defined(__i386__)
 #if SANITYCHECKS
 #define SPAREPAGES 100
 #define STATIC_SPAREPAGES 90
 #else
-#define SPAREPAGES 15
-#define STATIC_SPAREPAGES 10
+#define SPAREPAGES 20
+#define STATIC_SPAREPAGES 15
 #endif
-#elif defined(__arm__)
+
 #define SPAREPAGEDIRS 11
 #define STATIC_SPAREPAGEDIRS 10
-#define SPAREPAGES 250
-#define STATIC_SPAREPAGES 100
+
 int missing_sparedirs = SPAREPAGEDIRS;
 static struct {
        void *pagedir;
        phys_bytes phys;
 } sparepagedirs[SPAREPAGEDIRS];
-#endif
 
 int missing_spares = SPAREPAGES;
 static struct {
@@ -143,11 +140,7 @@ void pt_sanitycheck(pt_t *pt, char *file, int line)
 /*===========================================================================*
  *                             findhole                                     *
  *===========================================================================*/
-#if defined(__i386__)
-static u32_t findhole(void)
-#elif defined(__arm__)
 static u32_t findhole(int pages)
-#endif
 {
 /* Find a space in the virtual address space of VM. */
        u32_t curv;
@@ -159,7 +152,9 @@ static u32_t findhole(int pages)
        u32_t holev;
 #endif
 
-       vmin = (vir_bytes) (&_end) & ARCH_VM_ADDR_MASK; /* marks end of VM BSS */
+       vmin = (vir_bytes) (&_end); /* marks end of VM BSS */
+       vmin += 1024*1024*1024; /* reserve 1GB virtual address space for VM heap */
+       vmin &= ARCH_VM_ADDR_MASK; 
        vmax = VM_STACKTOP;
 
        /* Input sanity check. */
@@ -298,10 +293,10 @@ static void *vm_getsparepage(phys_bytes *phys)
                        return sp;
                }
        }
+       printf("no spare found, %d missing\n", missing_spares);
        return NULL;
 }
 
-#if defined(__arm__)
 /*===========================================================================*
  *                             vm_getsparepagedir                           *
  *===========================================================================*/
@@ -322,7 +317,6 @@ static void *vm_getsparepagedir(phys_bytes *phys)
        }
        return NULL;
 }
-#endif
 
 /*===========================================================================*
  *                             vm_checkspares                               *
@@ -332,7 +326,7 @@ static void *vm_checkspares(void)
        int s, n = 0;
        static int total = 0, worst = 0;
        assert(missing_spares >= 0 && missing_spares <= SPAREPAGES);
-       for(s = 0; s < SPAREPAGES && missing_spares > 0; s++)
+       for(s = 0; s < SPAREPAGES && missing_spares > 0; s++) {
            if(!sparepages[s].page) {
                n++;
                if((sparepages[s].page = vm_allocpage(&sparepages[s].phys, 
@@ -343,6 +337,7 @@ static void *vm_checkspares(void)
                } else {
                        printf("VM: warning: couldn't get new spare page\n");
                }
+          }
        }
        if(worst < n) worst = n;
        total += n;
@@ -376,14 +371,14 @@ static void *vm_checksparedirs(void)
 
        return NULL;
 }
-
 #endif
+
 static int pt_init_done;
 
 /*===========================================================================*
  *                             vm_allocpage                                 *
  *===========================================================================*/
-void *vm_allocpage(phys_bytes *phys, int reason)
+void *vm_allocpages(phys_bytes *phys, int reason, int pages)
 {
 /* Allocate a page for use by VM itself. */
        phys_bytes newpage;
@@ -392,13 +387,13 @@ void *vm_allocpage(phys_bytes *phys, int reason)
        int r;
        static int level = 0;
        void *ret;
-#if defined(__arm__)
-       u32_t mem_bytes, mem_clicks, mem_flags;
-#endif
+       u32_t mem_flags = 0;
 
        pt = &vmprocess->vm_pt;
        assert(reason >= 0 && reason < VMP_CATEGORIES);
 
+       assert(pages > 0);
+
        level++;
 
        assert(level >= 1);
@@ -406,16 +401,13 @@ void *vm_allocpage(phys_bytes *phys, int reason)
 
        if((level > 1) || !pt_init_done) {
                void *s;
-#if defined(__i386__)
+
                s=vm_getsparepage(phys);
-#elif defined(__arm__)
 
-               if (reason == VMP_PAGEDIR)
-                       s=vm_getsparepagedir(phys);
-               else
-                       s=vm_getsparepage(phys);
+               if(pages == 1) s=vm_getsparepage(phys);
+               else if(pages == 4) s=vm_getsparepagedir(phys);
+               else panic("%d pages", pages);
 
-#endif
                level--;
                if(!s) {
                        util_stacktrace();
@@ -427,23 +419,14 @@ void *vm_allocpage(phys_bytes *phys, int reason)
 
 #if defined(__arm__)
        if (reason == VMP_PAGEDIR) {
-               mem_bytes = ARCH_PAGEDIR_SIZE;
-               mem_flags = PAF_ALIGN16K;
-       } else {
-               mem_bytes = VM_PAGE_SIZE;
-               mem_flags = 0;
+               mem_flags |= PAF_ALIGN16K;
        }
-       mem_clicks = mem_bytes / VM_PAGE_SIZE * CLICKSPERPAGE;
-
 #endif
+
        /* VM does have a pagetable, so get a page and map it in there.
         * Where in our virtual address space can we put it?
         */
-#if defined(__i386__)
-       loc = findhole();
-#elif defined(__arm__)
-       loc = findhole(mem_bytes / VM_PAGE_SIZE);
-#endif
+       loc = findhole(pages);
        if(loc == NO_MEM) {
                level--;
                printf("VM: vm_allocpage: findhole failed\n");
@@ -453,11 +436,7 @@ void *vm_allocpage(phys_bytes *phys, int reason)
        /* Allocate page of memory for use by VM. As VM
         * is trusted, we don't have to pre-clear it.
         */
-#if defined(__i386__)
-       if((newpage = alloc_mem(CLICKSPERPAGE, 0)) == NO_MEM) {
-#elif defined(__arm__)
-       if((newpage = alloc_mem(mem_clicks, mem_flags)) == NO_MEM) {
-#endif
+       if((newpage = alloc_mem(pages, mem_flags)) == NO_MEM) {
                level--;
                printf("VM: vm_allocpage: alloc_mem failed\n");
                return NULL;
@@ -466,16 +445,13 @@ void *vm_allocpage(phys_bytes *phys, int reason)
        *phys = CLICK2ABS(newpage);
 
        /* Map this page into our address space. */
-#if defined(__i386__)
-       if((r=pt_writemap(vmprocess, pt, loc, *phys, VM_PAGE_SIZE,
-               ARCH_VM_PTE_PRESENT | ARCH_VM_PTE_USER | ARCH_VM_PTE_RW, 0)) != OK) {
-               free_mem(newpage, CLICKSPERPAGE);
-#elif defined(__arm__)
-       if((r=pt_writemap(vmprocess, pt, loc, *phys, mem_bytes,
-               ARCH_VM_PTE_PRESENT | ARCH_VM_PTE_USER | ARCH_VM_PTE_RW |
-               ARM_VM_PTE_WB | ARM_VM_PTE_SHAREABLE, 0)) != OK) {
-               free_mem(newpage, mem_clicks);
+       if((r=pt_writemap(vmprocess, pt, loc, *phys, VM_PAGE_SIZE*pages,
+               ARCH_VM_PTE_PRESENT | ARCH_VM_PTE_USER | ARCH_VM_PTE_RW
+#if defined(__arm__)
+               | ARM_VM_PTE_WB | ARM_VM_PTE_SHAREABLE
 #endif
+               , 0)) != OK) {
+               free_mem(newpage, pages);
                printf("vm_allocpage writemap failed\n");
                level--;
                return NULL;
@@ -494,6 +470,11 @@ void *vm_allocpage(phys_bytes *phys, int reason)
        return ret;
 }
 
+void *vm_allocpage(phys_bytes *phys, int reason)
+{
+       return vm_allocpages(phys, reason, 1);
+}
+
 /*===========================================================================*
  *                             vm_pagelock                                  *
  *===========================================================================*/
@@ -1089,12 +1070,12 @@ int pt_new(pt_t *pt)
         * the page directories (the page_directories data).
         */
         if(!pt->pt_dir &&
-          !(pt->pt_dir = vm_allocpage((phys_bytes *)&pt->pt_dir_phys, VMP_PAGEDIR))) {
+          !(pt->pt_dir = vm_allocpages((phys_bytes *)&pt->pt_dir_phys,
+               VMP_PAGEDIR, ARCH_PAGEDIR_SIZE/VM_PAGE_SIZE))) {
                return ENOMEM;
        }
-#if defined(__arm__)
+
        assert(!((u32_t)pt->pt_dir_phys % ARCH_PAGEDIR_SIZE));
-#endif
 
        for(i = 0; i < ARCH_VM_DIR_ENTRIES; i++) {
                pt->pt_dir[i] = 0; /* invalid entry (PRESENT bit = 0) */
@@ -1360,6 +1341,8 @@ void pt_init(void)
 
        pt_init_done = 1;
 
+       vm_checkspares();
+
         /* All OK. */
         return;
 }
index ec61ceadcabfb099aa645f52e3291759b72a0464..f11adc6767e5b508582765d8e5646cfaa30ab79e 100644 (file)
@@ -39,7 +39,6 @@ static int anon_contig_new(struct vir_region *region)
         u32_t allocflags;
        phys_bytes new_pages, new_page_cl, cur_ph;
        int p, pages;
-       physr_iter iter;
 
         allocflags = vrallocflags(region->flags);
 
@@ -68,20 +67,15 @@ static int anon_contig_new(struct vir_region *region)
 
        cur_ph = new_pages = CLICK2ABS(new_page_cl);
 
-        physr_start_iter_least(region->phys, &iter);
-
        for(p = 0; p < pages; p++) {
-               struct phys_region *pr = physr_get_iter(&iter);
+               struct phys_region *pr = physblock_get(region, p * VM_PAGE_SIZE);
                assert(pr);
                assert(pr->ph);
                assert(pr->ph->phys == MAP_NONE);
                assert(pr->offset == p * VM_PAGE_SIZE);
                pr->ph->phys = cur_ph + pr->offset;
-               physr_incr_iter(&iter);
        }
 
-       assert(!physr_get_iter(&iter));
-
        return OK;
 }
 
index f5b9d6ce535cda27c542e17977cd871aa4fb0a7e..17252efe5893cb7ade720e73a4df39d45ce17e0a 100644 (file)
@@ -129,12 +129,11 @@ static int shared_pagefault(struct vmproc *vmp, struct vir_region *region,
        assert(ph->ph->phys == MAP_NONE);
        pb_free(ph->ph);
 
-       if(!(pr = physr_search(src_region->phys, ph->offset, AVL_EQUAL))) {
+       if(!(pr = physblock_get(src_region, ph->offset))) {
                int r;
                if((r=map_pf(src_vmp, src_region, ph->offset, write)) != OK)
                        return r;
-               if(!(pr = physr_search(src_region->phys, ph->offset,
-                       AVL_EQUAL))) {
+               if(!(pr = physblock_get(src_region, ph->offset))) {
                        panic("missing region after pagefault handling");
                }
        }
index 736c7f9861f8a035da5a3bfdf1b55d2e8708af00..b2d33c1bfe64f96902878d6578eb5eabead03bd3 100644 (file)
@@ -27,7 +27,6 @@
 #include "glo.h"
 #include "region.h"
 #include "sanitycheck.h"
-#include "physravl.h"
 #include "memlist.h"
 
 struct phys_block *pb_new(phys_bytes phys)
@@ -84,7 +83,7 @@ struct        phys_region *pb_reference(struct phys_block *newpb,
        /* New physical region. */
        pb_link(newphysr, newpb, offset, region);
 
-       physr_insert(region->phys, newphysr);
+       physblock_set(region, offset, newphysr);
 
        return newphysr;
 }
@@ -129,5 +128,5 @@ void pb_unreferenced(struct vir_region *region, struct phys_region *pr, int rm)
 
        pr->ph = NULL;
 
-       if(rm) physr_remove(region->phys, pr->offset);
+       if(rm) physblock_set(region, pr->offset, NULL);
 }
index ca68fa9dbfe92f70f232854d1cd5e5ad1d07e2a5..f8e1b5e0dbd1de999836faf65dd1cc9e8fbf9869 100644 (file)
@@ -17,10 +17,6 @@ typedef struct phys_region {
 
        /* list of phys_regions that reference the same phys_block */
        struct phys_region      *next_ph_list;  
-
-       /* AVL fields */
-       struct phys_region      *less, *greater;
-       int                     factor;
 } phys_region_t;
 
 #endif
diff --git a/servers/vm/physravl.c b/servers/vm/physravl.c
deleted file mode 100644 (file)
index e96014e..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-
-#include "proto.h"
-#include "sanitycheck.h"
-#include "phys_region.h"
-#include "physravl_defs.h"
-#include "cavl_impl.h"
-
diff --git a/servers/vm/physravl.h b/servers/vm/physravl.h
deleted file mode 100644 (file)
index 10b526a..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-
-#ifndef _PHYSRAVL_H 
-#define _PHYSRAVL_H 
-
-#include "phys_region.h"
-#include "physravl_defs.h"
-#include "cavl_if.h"
-#include "unavl.h"
-
-#endif
diff --git a/servers/vm/physravl_defs.h b/servers/vm/physravl_defs.h
deleted file mode 100644 (file)
index b188a61..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-
-#include <minix/u64.h>
-
-#define AVL_UNIQUE(id) physr_ ## id
-#define AVL_HANDLE phys_region_t *
-#define AVL_KEY vir_bytes
-#define AVL_MAX_DEPTH 30 /* good for 2 million nodes */
-#define AVL_NULL NULL
-#define AVL_GET_LESS(h, a) (h)->less
-#define AVL_GET_GREATER(h, a) (h)->greater
-#define AVL_SET_LESS(h1, h2) USE((h1), (h1)->less = h2;);
-#define AVL_SET_GREATER(h1, h2) USE((h1), (h1)->greater = h2;);
-#define AVL_GET_BALANCE_FACTOR(h) (h)->factor
-#define AVL_SET_BALANCE_FACTOR(h, f) USE((h), (h)->factor = f;);
-#define AVL_SET_ROOT(h, v) USE((h), (h)->root = v;);
-#define AVL_COMPARE_KEY_KEY(k1, k2)  ((k1) > (k2) ? 1 : ((k1) < (k2) ? -1 : 0))
-#define AVL_COMPARE_KEY_NODE(k, h) AVL_COMPARE_KEY_KEY((k), (h)->offset)
-#define AVL_COMPARE_NODE_NODE(h1, h2) AVL_COMPARE_KEY_KEY((h1)->offset, (h2)->offset)
-#define AVL_INSIDE_STRUCT char pad[4];   
-
index d38f590222184b617e89e0205b6a3a36d73c462e..1882cafe9a0daf0590e419d3ef3bcc368111ea6e 100644 (file)
@@ -92,6 +92,7 @@ int pt_writemap(struct vmproc * vmp, pt_t *pt, vir_bytes v, phys_bytes
 int pt_checkrange(pt_t *pt, vir_bytes v, size_t bytes, int write);
 int pt_bind(pt_t *pt, struct vmproc *who);
 void *vm_allocpage(phys_bytes *p, int cat);
+void *vm_allocpages(phys_bytes *p, int cat, int pages);
 void *vm_allocpagedir(phys_bytes *p);
 void pt_cycle(void);
 int pt_mapkernel(pt_t *pt);
@@ -145,9 +146,12 @@ void printregionstats(struct vmproc *vmp);
 void map_setparent(struct vmproc *vmp);
 int yielded_block_cmp(struct block_id *, struct block_id *);
 struct phys_region *map_clone_ph_block(struct vmproc *vmp,
-        struct vir_region *region, struct phys_region *ph, physr_iter *iter);
+        struct vir_region *region, struct phys_region *ph);
 u32_t vrallocflags(u32_t flags);
 int map_free(struct vir_region *region);
+struct phys_region *physblock_get(struct vir_region *region, vir_bytes offset);
+void physblock_set(struct vir_region *region, vir_bytes offset,
+       struct phys_region *newphysr);
 
 struct vir_region * map_region_lookup_tag(struct vmproc *vmp, u32_t
        tag);
index ee54cef69bb77e6f08e1ffa9fd12ffe73a9e2377..21b6e70441824e1f04aa315ab2e4ab881b7fce50 100644 (file)
@@ -14,6 +14,7 @@
 #include <sys/mman.h>
 
 #include <limits.h>
+#include <stdlib.h>
 #include <string.h>
 #include <assert.h>
 #include <stdint.h>
@@ -25,7 +26,7 @@
 #include "glo.h"
 #include "region.h"
 #include "sanitycheck.h"
-#include "physravl.h"
+#include "yieldedavl.h"
 #include "memlist.h"
 #include "memtype.h"
 
@@ -74,23 +75,50 @@ static yielded_avl *get_yielded_avl(block_id_t id)
        return &vm_yielded_blocks[h];
 }
 
-void map_printregion(struct vmproc *vmp, struct vir_region *vr)
+void map_printregion(struct vir_region *vr)
 {
-       physr_iter iter;
+       int i;
        struct phys_region *ph;
        printf("map_printmap: map_name: %s\n", vr->memtype->name);
        printf("\t%lx (len 0x%lx, %lukB), %p\n",
                vr->vaddr, vr->length, vr->length/1024, vr->memtype->name);
        printf("\t\tphysblocks:\n");
-       physr_start_iter_least(vr->phys, &iter);
-       while((ph = physr_get_iter(&iter))) {
+       for(i = 0; i < vr->length/VM_PAGE_SIZE; i++) {
+               if(!(ph=vr->physblocks[i])) continue;
                printf("\t\t@ %lx (refs %d): phys 0x%lx\n",
                        (vr->vaddr + ph->offset),
                        ph->ph->refcount, ph->ph->phys);
-               physr_incr_iter(&iter);
        }
 }
 
+struct phys_region *physblock_get(struct vir_region *region, vir_bytes offset)
+{
+       int i;
+       struct phys_region *foundregion;
+       assert(!(offset % VM_PAGE_SIZE));
+       assert(offset >= 0 && offset < region->length);
+       i = offset/VM_PAGE_SIZE;
+       if((foundregion =  region->physblocks[i]))
+               assert(foundregion->offset == offset);
+       return foundregion;
+}
+
+void physblock_set(struct vir_region *region, vir_bytes offset,
+       struct phys_region *newphysr)
+{
+       int i;
+       assert(!(offset % VM_PAGE_SIZE));
+       assert(offset >= 0 && offset < region->length);
+       i = offset/VM_PAGE_SIZE;
+       if(newphysr) {
+               assert(!region->physblocks[i]);
+               assert(newphysr->offset == offset);
+       } else {
+               assert(region->physblocks[i]);
+       }
+       region->physblocks[i] = newphysr;
+}
+
 /*===========================================================================*
  *                             map_printmap                                 *
  *===========================================================================*/
@@ -104,7 +132,7 @@ struct vmproc *vmp;
 
        region_start_iter_least(&vmp->vm_regions_avl, &iter);
        while((vr = region_get_iter(&iter))) {
-               map_printregion(vmp, vr);
+               map_printregion(vr);
                region_incr_iter(&iter);
        }
 }
@@ -156,7 +184,7 @@ static int map_sanitycheck_pt(struct vmproc *vmp,
        if(r != OK) {
                printf("proc %d phys_region 0x%lx sanity check failed\n",
                        vmp->vm_endpoint, pr->offset);
-               map_printregion(vmp, vr);
+               map_printregion(vr);
        }
 
        return r;
@@ -176,19 +204,20 @@ void map_sanitycheck(char *file, int line)
  */
 #define ALLREGIONS(regioncode, physcode)                       \
        for(vmp = vmproc; vmp < &vmproc[VMP_NR]; vmp++) {       \
+               vir_bytes voffset;                              \
                region_iter v_iter;                             \
                struct vir_region *vr;                          \
                if(!(vmp->vm_flags & VMF_INUSE))                \
                        continue;                               \
                region_start_iter_least(&vmp->vm_regions_avl, &v_iter); \
                while((vr = region_get_iter(&v_iter))) {        \
-                       physr_iter iter;                        \
                        struct phys_region *pr;                 \
                        regioncode;                             \
-                       physr_start_iter_least(vr->phys, &iter); \
-                       while((pr = physr_get_iter(&iter))) {   \
+                       for(voffset = 0; voffset < vr->length; \
+                               voffset += VM_PAGE_SIZE) {      \
+                               if(!(pr = physblock_get(vr, voffset)))  \
+                                       continue;       \
                                physcode;                       \
-                               physr_incr_iter(&iter);         \
                        }                                       \
                        region_incr_iter(&v_iter);              \
                }                                               \
@@ -201,6 +230,7 @@ void map_sanitycheck(char *file, int line)
 
        /* Do counting for consistency check. */
        ALLREGIONS(;,USE(pr->ph, pr->ph->seencount = 0;););
+       ALLREGIONS(;,MYASSERT(pr->offset == voffset););
        ALLREGIONS(;,USE(pr->ph, pr->ph->seencount++;);
                if(pr->ph->seencount == 1) {
                        if(pr->parent->memtype->ev_sanitycheck)
@@ -466,12 +496,19 @@ static vir_bytes region_find_slot(struct vmproc *vmp,
        return region_find_slot_range(vmp, minv, maxv, length);
 }
 
+static int phys_slot(vir_bytes len)
+{
+       assert(!(len % VM_PAGE_SIZE));
+       return len / VM_PAGE_SIZE;
+}
+
 struct vir_region *region_new(struct vmproc *vmp, vir_bytes startv, vir_bytes length,
        int flags, mem_type_t *memtype)
 {
-       physr_avl *phavl;
        struct vir_region *newregion;
+       struct phys_region **physregions;
        static u32_t id;
+       int slots = phys_slot(length);
 
        if(!(SLABALLOC(newregion))) {
                printf("vm: region_new: could not allocate\n");
@@ -490,14 +527,13 @@ USE(newregion,
        newregion->lower = newregion->higher = NULL;
        newregion->parent = vmp;);
 
-       SLABALLOC(phavl);
-       if(!phavl) {
-               printf("VM: region_new: allocating phys avl failed\n");
+       if(!(physregions = calloc(slots, sizeof(struct phys_region *)))) {
+               printf("VM: region_new: allocating phys blocks failed\n");
                SLABFREE(newregion);
                return NULL;
        }
-       USE(newregion, newregion->phys = phavl;);
-       physr_init(newregion->phys);
+
+       USE(newregion, newregion->physblocks = physregions;);
 
        return newregion;
 }
@@ -543,8 +579,9 @@ mem_type_t *memtype;
        if(mapflags & MF_PREALLOC) {
                if(map_handle_memory(vmp, newregion, 0, length, 1) != OK) {
                        printf("VM: map_page_region: prealloc failed\n");
+                       free(newregion->physblocks);
                        USE(newregion,
-                               SLABFREE(newregion->phys););
+                               newregion->physblocks = NULL;);
                        SLABFREE(newregion);
                        return NULL;
                }
@@ -580,51 +617,37 @@ static int map_subfree(struct vir_region *region,
        vir_bytes start, vir_bytes len)
 {
        struct phys_region *pr;
-       physr_iter iter;
        vir_bytes end = start+len;
-
-       int full = 0;
+       vir_bytes voffset;
 
 #if SANITYCHECKS
-       {
        SLABSANE(region);
-       SLABSANE(region->phys);
-       physr_start_iter_least(region->phys, &iter);
-       while((pr = physr_get_iter(&iter))) {
+       for(voffset = 0; voffset < phys_slot(region->length);
+               voffset += VM_PAGE_SIZE) {
                struct phys_region *others;
                struct phys_block *pb;
 
+               if(!(pr = physblock_get(region, voffset)))
+                       continue;
+
                pb = pr->ph;
 
                for(others = pb->firstregion; others;
                        others = others->next_ph_list) {
                        assert(others->ph == pb);
                }
-               physr_incr_iter(&iter);
-       }
        }
 #endif
 
-       if(start == 0 && len == region->length)
-               full = 1;
-
-       physr_init_iter(&iter);
-       physr_start_iter(region->phys, &iter, start, AVL_GREATER_EQUAL);
-       while((pr = physr_get_iter(&iter))) {
-               physr_incr_iter(&iter);
-               if(pr->offset >= end)
-                       break;
-               pb_unreferenced(region, pr, !full);
-               if(!full) {
-                       physr_start_iter(region->phys, &iter,
-                               pr->offset, AVL_GREATER_EQUAL);
-               }
+       for(voffset = start; voffset < end; voffset+=VM_PAGE_SIZE) {
+               if(!(pr = physblock_get(region, voffset)))
+                       continue;
+               assert(pr->offset >= start);
+               assert(pr->offset < end);
+               pb_unreferenced(region, pr, 1);
                SLABFREE(pr);
        }
 
-       if(full)
-               physr_init(region->phys);
-
        return OK;
 }
 
@@ -642,9 +665,8 @@ int map_free(struct vir_region *region)
 
        if(region->memtype->ev_delete)
                region->memtype->ev_delete(region);
-
-       USE(region,
-               SLABFREE(region->phys););
+       free(region->physblocks);
+       region->physblocks = NULL;
        SLABFREE(region);
 
        return OK;
@@ -829,7 +851,7 @@ struct phys_region **physr;
                if(offset >= r->vaddr && offset < r->vaddr + r->length) {
                        ph = offset - r->vaddr;
                        if(physr) {
-                               *physr = physr_search(r->phys, ph, AVL_EQUAL);
+                               *physr = physblock_get(r, ph);
                                if(*physr) assert((*physr)->offset == ph);
                        }
                        return r;
@@ -862,11 +884,10 @@ u32_t vrallocflags(u32_t flags)
 /*===========================================================================*
  *                             map_clone_ph_block                           *
  *===========================================================================*/
-struct phys_region *map_clone_ph_block(vmp, region, ph, iter)
+struct phys_region *map_clone_ph_block(vmp, region, ph)
 struct vmproc *vmp;
 struct vir_region *region;
 struct phys_region *ph;
-physr_iter *iter;
 {
        vir_bytes offset;
        u32_t allocflags;
@@ -927,15 +948,10 @@ physr_iter *iter;
        if(copy_abs2region(physaddr, region, offset, VM_PAGE_SIZE) != OK)
                panic("copy_abs2region failed, no good reason for that");
 
-       newpr = physr_search(region->phys, offset, AVL_EQUAL);
+       newpr = physblock_get(region, offset);
        assert(newpr);
        assert(newpr->offset == offset);
 
-       if(iter) {
-               physr_start_iter(region->phys, iter, offset, AVL_EQUAL);
-               assert(physr_get_iter(iter) == newpr);
-       }
-
        SANITYCHECK(SCL_FUNCTIONS);
 
        return newpr;
@@ -964,7 +980,7 @@ int write;
 
        SANITYCHECK(SCL_FUNCTIONS);
 
-       if(!(ph = physr_search(region->phys, offset, AVL_EQUAL))) {
+       if(!(ph = physblock_get(region, offset))) {
                struct phys_block *pb;
 
                /* New block. */
@@ -993,6 +1009,7 @@ int write;
        if(!write || !region->memtype->writable(ph)) {
                assert(region->memtype->ev_pagefault);
                assert(ph->ph);
+
                if((r = region->memtype->ev_pagefault(vmp,
                        region, ph, write)) == SUSPEND) {
                        panic("map_pf: memtype->ev_pagefault returned SUSPEND\n");
@@ -1071,21 +1088,6 @@ int map_pin_memory(struct vmproc *vmp)
        return OK;
 }
 
-#if SANITYCHECKS
-static int count_phys_regions(struct vir_region *vr)
-{
-       int n = 0;
-       struct phys_region *ph;
-       physr_iter iter;
-       physr_start_iter_least(vr->phys, &iter);
-       while((ph = physr_get_iter(&iter))) {
-               n++;
-               physr_incr_iter(&iter);
-       }
-       return n;
-}
-#endif
-
 /*===========================================================================*
  *                             map_copy_region                         *
  *===========================================================================*/
@@ -1102,11 +1104,11 @@ static struct vir_region *map_copy_region(struct vmproc *vmp, struct vir_region
        struct vir_region *newvr;
        struct phys_region *ph;
        int r;
-       physr_iter iter;
 #if SANITYCHECKS
        int cr;
-       cr = count_phys_regions(vr);
+       cr = physregions(vr);
 #endif
+       vir_bytes p;
 
        if(!(newvr = region_new(vr->parent, vr->vaddr, vr->length, vr->flags, vr->memtype)))
                return NULL;
@@ -1117,21 +1119,20 @@ static struct vir_region *map_copy_region(struct vmproc *vmp, struct vir_region
                return NULL;
        }
 
-       physr_start_iter_least(vr->phys, &iter);
-       while((ph = physr_get_iter(&iter))) {
+       for(p = 0; p < phys_slot(vr->length); p++) {
+               if(!(ph = physblock_get(vr, p*VM_PAGE_SIZE))) continue;
                struct phys_region *newph = pb_reference(ph->ph, ph->offset, newvr);
 
                if(!newph) { map_free(newvr); return NULL; }
 
 #if SANITYCHECKS
                USE(newph, newph->written = 0;);
-               assert(count_phys_regions(vr) == cr);
+               assert(physregions(vr) == cr);
 #endif
-               physr_incr_iter(&iter);
        }
 
 #if SANITYCHECKS
-       assert(count_phys_regions(vr) == count_phys_regions(newvr));
+       assert(physregions(vr) == physregions(newvr));
 #endif
 
        return newvr;
@@ -1145,13 +1146,13 @@ int copy_abs2region(phys_bytes abs, struct vir_region *destregion,
 
 {
        assert(destregion);
-       assert(destregion->phys);
+       assert(destregion->physblocks);
        while(len > 0) {
                phys_bytes sublen, suboffset;
                struct phys_region *ph;
                assert(destregion);
-               assert(destregion->phys);
-               if(!(ph = physr_search(destregion->phys, offset, AVL_LESS_EQUAL))) {
+               assert(destregion->physblocks);
+               if(!(ph = physblock_get(destregion, offset))) {
                        printf("VM: copy_abs2region: no phys region found (1).\n");
                        return EFAULT;
                }
@@ -1195,11 +1196,9 @@ int map_writept(struct vmproc *vmp)
        region_start_iter_least(&vmp->vm_regions_avl, &v_iter);
 
        while((vr = region_get_iter(&v_iter))) {
-               physr_iter ph_iter;
-               physr_start_iter_least(vr->phys, &ph_iter);
-
-               while((ph = physr_get_iter(&ph_iter))) {
-                       physr_incr_iter(&ph_iter);
+               vir_bytes p;
+               for(p = 0; p < vr->length; p += VM_PAGE_SIZE) {
+                       if(!(ph = physblock_get(vr, p))) continue;
 
                        if((r=map_ph_writept(vmp, vr, ph)) != OK) {
                                printf("VM: map_writept: failed\n");
@@ -1250,34 +1249,30 @@ struct vir_region *start_src_vr;
        SANITYCHECK(SCL_FUNCTIONS);
 
        while((vr = region_get_iter(&v_iter))) {
-               physr_iter iter_orig, iter_new;
                struct vir_region *newvr;
-               struct phys_region *orig_ph, *new_ph;
                if(!(newvr = map_copy_region(dst, vr))) {
                        map_free_proc(dst);
                        return ENOMEM;
                }
                USE(newvr, newvr->parent = dst;);
                region_insert(&dst->vm_regions_avl, newvr);
-               physr_start_iter_least(vr->phys, &iter_orig);
-               physr_start_iter_least(newvr->phys, &iter_new);
-               while((orig_ph = physr_get_iter(&iter_orig))) {
-                       struct phys_block *pb;
-                       new_ph = physr_get_iter(&iter_new);
-                       /* Check two physregions both are nonnull,
-                        * are different, and match physblocks.
-                        */
+               assert(vr->length == newvr->length);
+
+#if SANITYCHECKS
+       {
+               vir_bytes vaddr;
+               struct phys_region *orig_ph, *new_ph;
+               assert(vr->physblocks != newvr->physblocks);
+               for(vaddr = 0; vaddr < vr->length; vaddr += VM_PAGE_SIZE) {
+                       orig_ph = physblock_get(vr, vaddr);
+                       new_ph = physblock_get(newvr, vaddr);
+                       if(!orig_ph) { assert(!new_ph); continue;}
                        assert(new_ph);
-                       assert(orig_ph);
                        assert(orig_ph != new_ph);
-                       pb = orig_ph->ph;
                        assert(orig_ph->ph == new_ph->ph);
-
-                       /* Get next new physregion */
-                       physr_incr_iter(&iter_orig);
-                       physr_incr_iter(&iter_new);
                }
-               assert(!physr_get_iter(&iter_new));
+       }
+#endif
                region_incr_iter(&v_iter);
        }
 
@@ -1292,6 +1287,8 @@ int map_region_extend_upto_v(struct vmproc *vmp, vir_bytes v)
 {
        vir_bytes offset = v;
        struct vir_region *vr, *nextvr;
+       struct phys_region **newpr;
+       int newslots, prevslots, addedslots;
 
        offset = roundup(offset, VM_PAGE_SIZE);
 
@@ -1300,7 +1297,24 @@ int map_region_extend_upto_v(struct vmproc *vmp, vir_bytes v)
                return ENOMEM;
        }
 
+       if(vr->vaddr + vr->length >= v) return OK;
+
        assert(vr->vaddr <= offset);
+       newslots = phys_slot(offset - vr->vaddr);
+       prevslots = phys_slot(vr->length);
+       assert(newslots >= prevslots);
+       addedslots = newslots - prevslots;
+
+       if(!(newpr = realloc(vr->physblocks,
+               newslots * sizeof(struct phys_region *)))) {
+               printf("VM: map_region_extend_upto_v: realloc failed\n");
+               return ENOMEM;
+       }
+
+       vr->physblocks = newpr;
+       memset(vr->physblocks + prevslots, 0,
+               addedslots * sizeof(struct phys_region *));
+
        if((nextvr = getnextvr(vr))) {
                assert(offset <= nextvr->vaddr);
        }
@@ -1328,6 +1342,7 @@ int map_unmap_region(struct vmproc *vmp, struct vir_region *r,
  * memory it used to reference if any.
  */
        vir_bytes regionstart;
+       int freeslots = phys_slot(len);
 
        SANITYCHECK(SCL_FUNCTIONS);
 
@@ -1344,7 +1359,8 @@ int map_unmap_region(struct vmproc *vmp, struct vir_region *r,
        /* if unmap was at start/end of this region, it actually shrinks */
        if(offset == 0) {
                struct phys_region *pr;
-               physr_iter iter;
+               vir_bytes voffset;
+               int remslots;
 
                region_remove(&vmp->vm_regions_avl, r->vaddr);
 
@@ -1352,20 +1368,23 @@ int map_unmap_region(struct vmproc *vmp, struct vir_region *r,
                r->vaddr += len;
                r->length -= len;);
 
+               remslots = phys_slot(r->length);
+
                region_insert(&vmp->vm_regions_avl, r);
 
                /* vaddr has increased; to make all the phys_regions
                 * point to the same addresses, make them shrink by the
                 * same amount.
                 */
-               physr_init_iter(&iter);
-               physr_start_iter(r->phys, &iter, offset, AVL_GREATER_EQUAL);
-
-               while((pr = physr_get_iter(&iter))) {
+               for(voffset = offset; voffset < r->length;
+                       voffset += VM_PAGE_SIZE) {
+                       if(!(pr = physblock_get(r, voffset))) continue;
                        assert(pr->offset >= offset);
                        USE(pr, pr->offset -= len;);
-                       physr_incr_iter(&iter);
                }
+               if(remslots)
+                       memmove(r->physblocks, r->physblocks + freeslots,
+                               remslots * sizeof(struct phys_region *));
        } else if(offset + len == r->length) {
                assert(len <= r->length);
                r->length -= len;
@@ -1459,10 +1478,10 @@ static void get_usage_info_vm(struct vm_usage_info *vui)
 void get_usage_info(struct vmproc *vmp, struct vm_usage_info *vui)
 {
        struct vir_region *vr;
-       physr_iter iter;
        struct phys_region *ph;
        region_iter v_iter;
        region_start_iter_least(&vmp->vm_regions_avl, &v_iter);
+       vir_bytes voffset;
 
        memset(vui, 0, sizeof(*vui));
 
@@ -1477,8 +1496,8 @@ void get_usage_info(struct vmproc *vmp, struct vm_usage_info *vui)
        }
 
        while((vr = region_get_iter(&v_iter))) {
-               physr_start_iter_least(vr->phys, &iter);
-               while((ph = physr_get_iter(&iter))) {
+               for(voffset = 0; voffset < vr->length; voffset += VM_PAGE_SIZE) {
+                       if(!(ph = physblock_get(vr, voffset))) continue;
                        /* All present pages are counted towards the total. */
                        vui->vui_total += VM_PAGE_SIZE;
 
@@ -1490,7 +1509,6 @@ void get_usage_info(struct vmproc *vmp, struct vm_usage_info *vui)
                                if (vr->flags & VR_SHARED)
                                        vui->vui_shared += VM_PAGE_SIZE;
                        }
-                       physr_incr_iter(&iter);
                }
                region_incr_iter(&v_iter);
        }
@@ -1515,13 +1533,18 @@ int get_region_info(struct vmproc *vmp, struct vm_region_info *vri,
        if(!(vr = region_get_iter(&v_iter))) return 0;
 
        for(count = 0; (vr = region_get_iter(&v_iter)) && count < max; count++, vri++) {
-               struct phys_region *ph1, *ph2;
+               struct phys_region *ph1 = NULL, *ph2 = NULL;
+               vir_bytes voffset;
 
                /* Report part of the region that's actually in use. */
 
                /* Get first and last phys_regions, if any */
-               ph1 = physr_search_least(vr->phys);
-               ph2 = physr_search_greatest(vr->phys);
+               for(voffset = 0; voffset > vr->length; voffset += VM_PAGE_SIZE) {
+                       struct phys_region *ph;
+                       if(!(ph = physblock_get(vr, voffset))) continue;
+                       if(!ph1) ph1 = ph;
+                       ph2 = ph;
+               }
                if(!ph1 || !ph2) { assert(!ph1 && !ph2); continue; }
 
                /* Report start+length of region starting from lowest use. */
@@ -1548,18 +1571,17 @@ void printregionstats(struct vmproc *vmp)
 {
        struct vir_region *vr;
        struct phys_region *pr;
-       physr_iter iter;
        vir_bytes used = 0, weighted = 0;
        region_iter v_iter;
        region_start_iter_least(&vmp->vm_regions_avl, &v_iter);
 
        while((vr = region_get_iter(&v_iter))) {
+               vir_bytes voffset;
                region_incr_iter(&v_iter);
                if(vr->flags & VR_DIRECT)
                        continue;
-               physr_start_iter_least(vr->phys, &iter);
-               while((pr = physr_get_iter(&iter))) {
-                       physr_incr_iter(&iter);
+               for(voffset = 0; voffset < vr->length; voffset+=VM_PAGE_SIZE) {
+                       if(!(pr = physblock_get(vr, voffset))) continue;
                        used += VM_PAGE_SIZE;
                        weighted += VM_PAGE_SIZE / pr->ph->refcount;
                }
@@ -1594,7 +1616,7 @@ get_clean_phys_region(struct vmproc *vmp, vir_bytes vaddr, struct vir_region **r
        assert(ph->ph->refcount > 0);
        if(ph->ph->refcount > 1) {
                if(!(ph = map_clone_ph_block(vmp, region,
-                       ph, NULL))) {
+                       ph))) {
                        printf("VM: get_clean_phys_region: ph copy failed\n");
                        return NULL;
                }
@@ -1893,11 +1915,10 @@ void map_setparent(struct vmproc *vmp)
 int physregions(struct vir_region *vr)
 {
        int n =  0;
-       physr_iter iter;
-       physr_start_iter_least(vr->phys, &iter);
-       while(physr_get_iter(&iter)) {
-               n++;
-               physr_incr_iter(&iter);
+       vir_bytes voffset;
+       for(voffset = 0; voffset < vr->length; voffset += VM_PAGE_SIZE) {
+               if(physblock_get(vr, voffset))
+                       n++;
        }
        return n;
 }
index 4e9365b6a84f9f6d96d3d2fa8551ffe14ceaf496..6899339d9074202d3addc5c2d4aa65c89c4b69e3 100644 (file)
@@ -17,7 +17,6 @@
 #include <minix/const.h>
 
 #include "phys_region.h"
-#include "physravl.h"
 #include "memtype.h"
 #include "vm.h"
 
@@ -38,7 +37,7 @@ struct phys_block {
 typedef struct vir_region {
        vir_bytes       vaddr;  /* virtual address, offset from pagetable */
        vir_bytes       length; /* length in bytes */
-       physr_avl       *phys;  /* avl tree of physical memory blocks */
+       struct phys_region      **physblocks;
        u16_t           flags;
        struct vmproc *parent;  /* Process that owns this vir_region. */
        mem_type_t      *memtype; /* Default instantiated memory type. */
index a23a1996c43885c9ecfc051a8cb33a66f22d6c77..b7d19c111c25076b8c4db82da6645f37b8205bf3 100644 (file)
@@ -24,6 +24,7 @@
 #include <unistd.h>
 #include <assert.h>
 #include <sys/param.h>
+#include <sys/mman.h>
 
 #include "proto.h"
 #include "glo.h"
@@ -264,3 +265,55 @@ int swap_proc_dyn_data(struct vmproc *src_vmp, struct vmproc *dst_vmp)
        return OK;
 }
 
+void *minix_mmap(void *addr, size_t len, int f, int f2, int f3, off_t o)
+{
+       void *ret;
+       phys_bytes p;
+
+       assert(!addr);
+       assert(!(len % VM_PAGE_SIZE));
+
+       ret = vm_allocpages(&p, VMP_SLAB, len/VM_PAGE_SIZE);
+
+       if(!ret) return MAP_FAILED;
+       memset(ret, 0, len);
+       return ret;
+}
+
+int minix_munmap(void * addr, size_t len)
+{
+       vm_freepages((vir_bytes) addr, roundup(len, VM_PAGE_SIZE)/VM_PAGE_SIZE);
+       return 0;
+}
+
+int _brk(void *addr)
+{
+       vir_bytes target = roundup((vir_bytes)addr, VM_PAGE_SIZE), v;
+       extern char _end;
+       extern char *_brksize;
+       static vir_bytes prevbrk = (vir_bytes) &_end;
+       struct vmproc *vmprocess = &vmproc[VM_PROC_NR];
+
+       for(v = roundup(prevbrk, VM_PAGE_SIZE); v < target;
+               v += VM_PAGE_SIZE) {
+               phys_bytes mem, newpage = alloc_mem(1, 0);
+               if(newpage == NO_MEM) return -1;
+               mem = CLICK2ABS(newpage);
+               if(pt_writemap(vmprocess, &vmprocess->vm_pt,
+       v, mem, VM_PAGE_SIZE,
+        ARCH_VM_PTE_PRESENT | ARCH_VM_PTE_USER | ARCH_VM_PTE_RW, 0) != OK) {
+                       free_mem(newpage, 1);
+                       return -1;
+               }
+               prevbrk = v + VM_PAGE_SIZE;
+       }
+
+        _brksize = (char *) addr;
+
+        if(sys_vmctl(SELF, VMCTL_FLUSHTLB, 0) != OK)
+               panic("flushtlb failed");
+
+       return 0;
+}
+
+
index 1c9c488bcadbaa9de30786e53f18c83e1669c4c2..ded51ff441c94cac7605f2dcac34a8f35683785a 100644 (file)
@@ -7,8 +7,6 @@
 
 #include "pt.h"
 #include "vm.h"
-#include "physravl.h"
-#include "yieldedavl.h"
 #include "regionavl.h"
 
 struct vmproc;