]> Zhao Yanbai Git Server - minix.git/commitdiff
VM: static data structure for mem allocation
authorBen Gras <ben@minix3.org>
Tue, 18 Sep 2012 11:17:48 +0000 (13:17 +0200)
committerBen Gras <ben@minix3.org>
Tue, 18 Sep 2012 11:17:48 +0000 (13:17 +0200)
 . allocate physical memory using a fixed, pre-allocated bitmap so there
   are no call cycles and it's avilable earlier

servers/vm/Makefile
servers/vm/addravl.c [deleted file]
servers/vm/addravl.h [deleted file]
servers/vm/addravl_defs.h [deleted file]
servers/vm/alloc.c
servers/vm/arch/i386/pagetable.c
servers/vm/glo.h
servers/vm/main.c
servers/vm/pagerange.h [deleted file]
servers/vm/slaballoc.c

index c3b1395690ffdb462afea7dbfbcfc595198421c4..e5f7c850fbd8d0c9fc30c97bd20a1c923cfde8af 100644 (file)
@@ -3,7 +3,7 @@
 
 PROG=  vm
 SRCS=  main.c alloc.c utility.c exit.c fork.c break.c \
-       mmap.c slaballoc.c region.c pagefaults.c addravl.c \
+       mmap.c slaballoc.c region.c pagefaults.c \
        physravl.c rs.c queryexit.c yieldedavl.c regionavl.c
 
 DPADD+=        ${LIBSYS}
diff --git a/servers/vm/addravl.c b/servers/vm/addravl.c
deleted file mode 100644 (file)
index 9028823..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-
-#include "proto.h"
-#include "sanitycheck.h"
-#include "pagerange.h"
-#include "addravl_defs.h"
-#include "cavl_if.h"
-#include "cavl_impl.h"
-
diff --git a/servers/vm/addravl.h b/servers/vm/addravl.h
deleted file mode 100644 (file)
index eaa57d3..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-
-#ifndef ADDRAVL
-#define ADDRAVL 1
-
-#include "addravl_defs.h"
-#include "cavl_if.h"
-#include "unavl.h"
-
-#endif
diff --git a/servers/vm/addravl_defs.h b/servers/vm/addravl_defs.h
deleted file mode 100644 (file)
index 84ce476..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-#define AVL_UNIQUE(id) addr_ ## id
-#define AVL_HANDLE pagerange_t *
-#define AVL_KEY phys_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) (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)->addr)
-#define AVL_COMPARE_NODE_NODE(h1, h2) AVL_COMPARE_KEY_KEY((h1)->addr, (h2)->addr)
-#define AVL_INSIDE_STRUCT char pad[4];
-
index fceedfb7d8bc4ad8ec6fdff848880b7819736f2e..a1842ede13a229e2aa61d45ac0ad32ec213bee1e 100644 (file)
 #include "proto.h"
 #include "util.h"
 #include "glo.h"
-#include "pagerange.h"
-#include "addravl.h"
 #include "sanitycheck.h"
 #include "memlist.h"
 
-/* AVL tree of free pages. */
-addr_avl addravl;
+/* Number of physical pages in a 32-bit address space */
+#define NUMBER_PHYSICAL_PAGES (0x100000000ULL/VM_PAGE_SIZE)
+#define PAGE_BITMAP_CHUNKS BITMAP_CHUNKS(NUMBER_PHYSICAL_PAGES)
+static bitchunk_t free_pages_bitmap[PAGE_BITMAP_CHUNKS];
+#define PAGE_CACHE_MAX 10000
+static int free_page_cache[PAGE_CACHE_MAX];
+static int free_page_cache_size = 0;
 
 /* Used for sanity check. */
 static phys_bytes mem_low, mem_high;
@@ -47,6 +50,8 @@ static phys_bytes alloc_pages(int pages, int flags, phys_bytes *ret);
 static bitchunk_t pagemap[CHUNKS];
 #endif
 
+#define page_isfree(i) GET_BIT(free_pages_bitmap, i)
+
 /*===========================================================================*
  *                             alloc_mem                                    *
  *===========================================================================*/
@@ -125,10 +130,10 @@ struct memory *chunks;            /* list of free memory chunks */
  */
   int i, first = 0;
 
-  addr_init(&addravl);
-
   total_pages = 0;
 
+  memset(free_pages_bitmap, 0, sizeof(free_pages_bitmap));
+
   /* Use the chunks of physical memory to allocate holes. */
   for (i=NR_MEMS-1; i>=0; i--) {
        if (chunks[i].size > 0) {
@@ -146,40 +151,64 @@ struct memory *chunks;            /* list of free memory chunks */
 #if SANITYCHECKS
 void mem_sanitycheck(char *file, int line)
 {
-       pagerange_t *p, *prevp = NULL;
-       addr_iter iter;
-       addr_start_iter_least(&addravl, &iter);
-       while((p=addr_get_iter(&iter))) {
-               SLABSANE(p);
-               assert(p->size > 0);
-               if(prevp) {
-                       assert(prevp->addr < p->addr);
-                       assert(prevp->addr + prevp->size < p->addr);
-               }
-               usedpages_add(p->addr * VM_PAGE_SIZE, p->size * VM_PAGE_SIZE);
-               prevp = p;
-               addr_incr_iter(&iter);
+       int i;
+       for(i = 0; i < NUMBER_PHYSICAL_PAGES; i++) {
+               if(!page_isfree(i)) continue;
+               usedpages_add(i * VM_PAGE_SIZE, VM_PAGE_SIZE);
        }
 }
 #endif
 
 void memstats(int *nodes, int *pages, int *largest)
 {
-       pagerange_t *p;
-       addr_iter iter;
-       addr_start_iter_least(&addravl, &iter);
+       int i;
        *nodes = 0;
        *pages = 0;
        *largest = 0;
 
-       while((p=addr_get_iter(&iter))) {
-               SLABSANE(p);
+       for(i = 0; i < NUMBER_PHYSICAL_PAGES; i++) {
+               int size = 0;
+               while(i < NUMBER_PHYSICAL_PAGES && page_isfree(i)) {
+                       size++;
+                       i++;
+               }
+               if(size == 0) continue;
                (*nodes)++;
-               (*pages)+= p->size;
-               if(p->size > *largest)
-                       *largest = p->size;
-               addr_incr_iter(&iter);
+               (*pages)+= size;
+               if(size > *largest)
+                       *largest = size;
+       }
+}
+
+static int findbit(int low, int startscan, int pages, int memflags, int *len)
+{
+       int run_length = 0, i, freerange_start;
+
+       for(i = startscan; i >= low; i--) {
+               if(!page_isfree(i)) {
+                       int pi;
+                       int chunk = i/BITCHUNK_BITS, moved = 0;
+                       run_length = 0;
+                       pi = i;
+                       while(chunk > 0 &&
+                          !MAP_CHUNK(free_pages_bitmap, chunk*BITCHUNK_BITS)) {
+                               chunk--;
+                               moved = 1;
+                       }
+                       if(moved) { i = chunk * BITCHUNK_BITS + BITCHUNK_BITS; }
+                       continue;
+               }
+               if(!run_length) { freerange_start = i; run_length = 1; }
+               else { freerange_start--; run_length++; }
+               assert(run_length <= pages);
+               if(run_length == pages || (memflags & PAF_FIRSTBLOCK)) {
+                       /* good block found! */
+                       *len = run_length;
+                       return freerange_start;
+               }
        }
+
+       return NO_MEM;
 }
 
 /*===========================================================================*
@@ -187,16 +216,12 @@ void memstats(int *nodes, int *pages, int *largest)
  *===========================================================================*/
 static phys_bytes alloc_pages(int pages, int memflags, phys_bytes *len)
 {
-       addr_iter iter;
-       pagerange_t *pr;
-       int incr;
        phys_bytes boundary16 = 16 * 1024 * 1024 / VM_PAGE_SIZE;
        phys_bytes boundary1  =  1 * 1024 * 1024 / VM_PAGE_SIZE;
-       phys_bytes mem;
-#if SANITYCHECKS
-       int firstnodes, firstpages, wantnodes, wantpages;
-       int finalnodes, finalpages;
-       int largest;
+       phys_bytes mem = NO_MEM;
+       int maxpage = NUMBER_PHYSICAL_PAGES - 1, i;
+       static int lastscan = -1;
+       int startscan, run_length;
 
 #if NONCONTIGUOUS
        /* If NONCONTIGUOUS is on, allocate physical pages single
@@ -209,84 +234,60 @@ static phys_bytes alloc_pages(int pages, int memflags, phys_bytes *len)
        }
 #endif
 
-       memstats(&firstnodes, &firstpages, &largest);
-       wantnodes = firstnodes;
-       wantpages = firstpages - pages;
-#endif
-
-       if(memflags & (PAF_LOWER16MB|PAF_LOWER1MB)) {
-               addr_start_iter_least(&addravl, &iter);
-               incr = 1;
-       } else {
-               addr_start_iter_greatest(&addravl, &iter);
-               incr = 0;
-       }
-
-       while((pr = addr_get_iter(&iter))) {
-               SLABSANE(pr);
-               assert(pr->size > 0);
-               if(pr->size >= pages || (memflags & PAF_FIRSTBLOCK)) {
-                       if(memflags & PAF_LOWER16MB) {
-                               if(pr->addr + pages > boundary16)
-                                       return NO_MEM;
-                       }
-
-                       if(memflags & PAF_LOWER1MB) {
-                               if(pr->addr + pages > boundary1)
-                                       return NO_MEM;
+       if(memflags & PAF_LOWER16MB)
+               maxpage = boundary16 - 1;
+       else if(memflags & PAF_LOWER1MB)
+               maxpage = boundary1 - 1;
+       else {
+               /* no position restrictions: check page cache */
+               if((pages == 1 || (memflags & PAF_FIRSTBLOCK))) {
+                       while(free_page_cache_size > 0) {
+                               i = free_page_cache[free_page_cache_size-1];
+                               if(page_isfree(i)) {
+                                       free_page_cache_size--;
+                                       mem = i;
+                                       assert(mem != NO_MEM);
+                                       run_length = 1;
+                                       break;
+                               }
+                               free_page_cache_size--;
                        }
-
-                       /* good block found! */
-                       break;
                }
-               if(incr)
-                       addr_incr_iter(&iter);
-               else
-                       addr_decr_iter(&iter);
        }
 
-       if(!pr) {
+       if(lastscan < maxpage && lastscan >= 0)
+               startscan = lastscan;
+       else    startscan = maxpage;
+
+       if(mem == NO_MEM)
+               mem = findbit(0, startscan, pages, memflags, &run_length);
+       if(mem == NO_MEM)
+               mem = findbit(0, maxpage, pages, memflags, &run_length);
+
+       if(mem == NO_MEM) {
                if(len)
                        *len = 0;
-#if SANITYCHECKS
-               assert(largest < pages);
-#endif
-          return NO_MEM;
+               return NO_MEM;
        }
 
-       SLABSANE(pr);
+       /* remember for next time */
+       lastscan = mem;
 
        if(memflags & PAF_FIRSTBLOCK) {
                assert(len);
                /* block doesn't have to as big as requested;
                 * return its size though.
                 */
-               if(pr->size < pages) {
-                       pages = pr->size;
-#if SANITYCHECKS
-                       wantpages = firstpages - pages;
-#endif
+               if(run_length < pages) {
+                       pages = run_length;
                }
        }
 
        if(len)
                *len = pages;
 
-       /* Allocated chunk is off the end. */
-       mem = pr->addr + pr->size - pages;
-
-       assert(pr->size >= pages);
-       if(pr->size == pages) {
-               pagerange_t *prr;
-               prr = addr_remove(&addravl, pr->addr);
-               assert(prr);
-               assert(prr == pr);
-               SLABFREE(pr);
-#if SANITYCHECKS
-               wantnodes--;
-#endif
-       } else {
-               USE(pr, pr->size -= pages;);
+       for(i = mem; i < mem + pages; i++) {
+               UNSET_BIT(free_pages_bitmap, i);
        }
 
        if(memflags & PAF_CLEAR) {
@@ -296,13 +297,6 @@ static phys_bytes alloc_pages(int pages, int memflags, phys_bytes *len)
                        panic("alloc_mem: sys_memset failed: %d", s);
        }
 
-#if SANITYCHECKS
-       memstats(&finalnodes, &finalpages, &largest);
-
-       assert(finalnodes == wantnodes);
-       assert(finalpages == wantpages);
-#endif
-
        return mem;
 }
 
@@ -311,19 +305,7 @@ static phys_bytes alloc_pages(int pages, int memflags, phys_bytes *len)
  *===========================================================================*/
 static void free_pages(phys_bytes pageno, int npages)
 {
-       pagerange_t *pr, *p;
-       addr_iter iter;
-#if SANITYCHECKS
-       int firstnodes, firstpages, wantnodes, wantpages;
-       int finalnodes, finalpages, largest;
-
-       memstats(&firstnodes, &firstpages, &largest);
-
-       wantnodes = firstnodes;
-       wantpages = firstpages + npages;
-#endif
-
-       assert(!addr_search(&addravl, pageno, AVL_EQUAL));
+       int i, lim = pageno + npages - 1;
 
 #if JUNKFREE
        if(sys_memset(NONE, 0xa5a5a5a5, VM_PAGE_SIZE * pageno,
@@ -331,54 +313,12 @@ static void free_pages(phys_bytes pageno, int npages)
                        panic("free_pages: sys_memset failed");
 #endif
 
-       /* try to merge with higher neighbour */
-       if((pr=addr_search(&addravl, pageno+npages, AVL_EQUAL))) {
-               USE(pr, pr->addr -= npages;
-                       pr->size += npages;);
-       } else {
-               if(!SLABALLOC(pr))
-                       panic("alloc_pages: can't alloc");
-#if SANITYCHECKS
-               memstats(&firstnodes, &firstpages, &largest);
-
-               wantnodes = firstnodes;
-               wantpages = firstpages + npages;
-
-#endif
-               assert(npages > 0);
-               USE(pr, pr->addr = pageno;
-                        pr->size = npages;);
-               addr_insert(&addravl, pr);
-#if SANITYCHECKS
-               wantnodes++;
-#endif
-       }
-
-       addr_start_iter(&addravl, &iter, pr->addr, AVL_EQUAL);
-       p = addr_get_iter(&iter);
-       assert(p);
-       assert(p == pr);
-
-       addr_decr_iter(&iter);
-       if((p = addr_get_iter(&iter))) {
-               SLABSANE(p);
-               if(p->addr + p->size == pr->addr) {
-                       USE(p, p->size += pr->size;);
-                       addr_remove(&addravl, pr->addr);
-                       SLABFREE(pr);
-#if SANITYCHECKS
-                       wantnodes--;
-#endif
+       for(i = pageno; i <= lim; i++) {
+               SET_BIT(free_pages_bitmap, i);
+               if(free_page_cache_size < PAGE_CACHE_MAX) {
+                       free_page_cache[free_page_cache_size++] = i;
                }
        }
-
-
-#if SANITYCHECKS
-       memstats(&finalnodes, &finalpages,  &largest);
-
-       assert(finalnodes == wantnodes);
-       assert(finalpages == wantpages);
-#endif
 }
 
 /*===========================================================================*
index 0f0a6401dcefb7115bdf73dfa18dc42d1ccc0f0b..8870a94a05a345e840501791bb471040206687ac 100644 (file)
@@ -259,6 +259,8 @@ static void *vm_checkspares(void)
        return NULL;
 }
 
+static int pt_init_done;
+
 /*===========================================================================*
  *                             vm_allocpage                                 *
  *===========================================================================*/
@@ -280,7 +282,7 @@ void *vm_allocpage(phys_bytes *phys, int reason)
        assert(level >= 1);
        assert(level <= 2);
 
-       if(level > 1 || !meminit_done) {
+       if((level > 1) || !pt_init_done) {
                void *s;
                s=vm_getsparepage(phys);
                level--;
@@ -1021,6 +1023,8 @@ void pt_init(void)
        assert(vmproc[VM_PROC_NR].vm_endpoint == VM_PROC_NR);
        pt_bind(newpt, &vmproc[VM_PROC_NR]);
 
+       pt_init_done = 1;
+
         /* All OK. */
         return;
 }
index 2d7998bdddd4ac098e48029dd85bffb8096dc6ff..6ec7c02a564f4762adfa0851f6fe61c586e30e6c 100644 (file)
@@ -29,5 +29,3 @@ EXTERN long vm_sanitychecklevel;
 
 /* total number of memory pages */
 EXTERN int total_pages;
-
-EXTERN int meminit_done;
index ecf24db8504f8167f638981d28d443632e5118cf..a381089aa6e793f4dbfa3e8e2c3f53da8b6fcb6d 100644 (file)
@@ -332,14 +332,13 @@ void init_vm(void)
        /* region management initialization. */
        map_region_init();
 
+       /* Initialize tables to all physical memory. */
+       mem_init(mem_chunks);
+
        /* Architecture-dependent initialization. */
        init_proc(VM_PROC_NR);
        pt_init();
 
-       /* Initialize tables to all physical memory. */
-       mem_init(mem_chunks);
-       meminit_done = 1;
-
        /* Give these processes their own page table. */
        for (ip = &kernel_boot_info.boot_procs[0];
                ip < &kernel_boot_info.boot_procs[NR_BOOT_PROCS]; ip++) {
diff --git a/servers/vm/pagerange.h b/servers/vm/pagerange.h
deleted file mode 100644 (file)
index edf84e9..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-#include <minix/callnr.h>
-#include <minix/com.h>
-#include <minix/config.h>
-#include <minix/const.h>
-#include <minix/ds.h>
-#include <minix/endpoint.h>
-#include <minix/keymap.h>
-#include <minix/minlib.h>
-#include <minix/type.h>
-#include <minix/ipc.h>
-#include <minix/sysutil.h>
-#include <minix/syslib.h>
-#include <minix/const.h>
-
-typedef struct pagerange {
-       phys_bytes      addr;   /* in pages */
-       phys_bytes      size;   /* in pages */
-
-       /* AVL fields */
-       struct pagerange *less, *greater;       /* children */
-       int             factor; /* AVL balance factor */
-} pagerange_t;
index 1711a318c90837ee7a17ee8b0f95e57f7601dd5f..425a43475dd5574e80a07e07f2403424bc513585 100644 (file)
@@ -18,7 +18,6 @@
 
 #include <assert.h>
 #include <errno.h>
-#include <assert.h>
 #include <string.h>
 #include <env.h>
 
@@ -387,7 +386,7 @@ void *slaballoc(int bytes)
 /*===========================================================================*
  *                             int objstats                                 *
  *===========================================================================*/
-static int objstats(void *mem, int bytes,
+static inline int objstats(void *mem, int bytes,
        struct slabheader **sp, struct slabdata **fp, int *ip)
 {
 #if SANITYCHECKS