]> Zhao Yanbai Git Server - minix.git/commitdiff
vm - hash table for block cache
authorBen Gras <ben@minix3.org>
Fri, 15 Oct 2010 09:10:14 +0000 (09:10 +0000)
committerBen Gras <ben@minix3.org>
Fri, 15 Oct 2010 09:10:14 +0000 (09:10 +0000)
servers/vm/exec.c
servers/vm/exit.c
servers/vm/fork.c
servers/vm/main.c
servers/vm/proto.h
servers/vm/region.c
servers/vm/slaballoc.c
servers/vm/utility.c
servers/vm/vmproc.h
servers/vm/yielded.h
servers/vm/yieldedavl_defs.h

index 049280e769975fc4f0e023998bd8f4ea3c18f041..8d1d5752ce4e162486bc1053557f614b9d2feee7 100644 (file)
@@ -392,8 +392,5 @@ PUBLIC int proc_new(struct vmproc *vmp,
                        panic("exec_newmem: pt_bind failed: %d", s);
        }
 
-       /* No yielded memory blocks. */
-       yielded_init(&vmp->vm_yielded_blocks);
-
        return OK;
 }
index 1c876ed9c94dc459191b835c200c56e1d9b14494..45bc25f390e5fa83e0dcd7b72d69803dffe0d9bf 100644 (file)
@@ -45,6 +45,7 @@ PUBLIC void clear_proc(struct vmproc *vmp)
        vmp->vm_callback = NULL;        /* No pending vfs callback. */
        vmp->vm_flags = 0;              /* Clear INUSE, so slot is free. */
        vmp->vm_heap = NULL;
+       vmp->vm_yielded = 0;
 #if VMSTATS
        vmp->vm_bytecopies = 0;
 #endif
index 289a296a194a6df7d9559d0da365f4eb0c4ece71..e2b690f6f2886524e2a16b06850a6367118cbbc1 100644 (file)
@@ -70,7 +70,6 @@ PUBLIC int do_fork(message *msg)
   *vmc = *vmp;
   vmc->vm_slot = childproc;
   region_init(&vmc->vm_regions_avl);
-  yielded_init(&vmc->vm_yielded_blocks);
   vmc->vm_endpoint = NONE;     /* In case someone tries to use it. */
   vmc->vm_pt = origpt;
   vmc->vm_flags &= ~VMF_HASPT;
index 0ee74440a91d2261050e2ce81ca2f976142e87c7..c17cde965d65c3d9c15da4e6334b32a30712700d 100644 (file)
@@ -255,6 +255,9 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
                        vmp->vm_flags |= VMF_SEPARATE;
        }
 
+       /* region management initialization. */
+       map_region_init();
+
        /* Architecture-dependent initialization. */
        pt_init(limit);
 
index 98ffd6e5bd3e94c19fc622f5dfb69daa5efdd50e..4651afd80660358c3b3f5747a83e204650ef50f7 100644 (file)
@@ -16,6 +16,7 @@ struct phys_region;
 #include <pagetable.h>
 
 #include "vm.h"
+#include "yielded.h"
 
 /* alloc.c */
 _PROTOTYPE( phys_clicks alloc_mem, (phys_clicks clicks, u32_t flags)   );
@@ -137,6 +138,7 @@ _PROTOTYPE(int slabsane_f,(char *file, int line, void *mem, int bytes));
 #endif
 
 /* region.c */
+_PROTOTYPE(void map_region_init, (void));
 _PROTOTYPE(struct vir_region * map_page_region,(struct vmproc *vmp, \
        vir_bytes min, vir_bytes max, vir_bytes length, vir_bytes what, \
        u32_t flags, int mapflags));
@@ -159,6 +161,7 @@ _PROTOTYPE(int map_writept, (struct vmproc *vmp));
 _PROTOTYPE(void printregionstats, (struct vmproc *vmp));
 _PROTOTYPE(phys_bytes map_lookup_phys, (struct vmproc *vmp, u32_t tag));
 _PROTOTYPE(void map_setparent, (struct vmproc *vmp));
+_PROTOTYPE(int yielded_block_cmp, (struct block_id *, struct block_id *));
 
 _PROTOTYPE(struct vir_region * map_region_lookup_tag, (struct vmproc *vmp, u32_t tag));
 _PROTOTYPE(void map_region_set_tag, (struct vir_region *vr, u32_t tag));
index 1f33982b8d6bae736ae6729996612e65e889f813..89af5afcad67efcc78242581ebc7e00f8f08c78d 100644 (file)
@@ -10,6 +10,7 @@
 #include <minix/syslib.h>
 #include <minix/debug.h>
 #include <minix/bitmap.h>
+#include <minix/hash.h>
 
 #include <sys/mman.h>
 
@@ -56,6 +57,36 @@ FORWARD _PROTOTYPE(struct phys_region *map_clone_ph_block, (struct vmproc *vmp,
 FORWARD _PROTOTYPE(void lrucheck, (void));
 #endif
 
+/* hash table of yielded blocks */
+#define YIELD_HASHSIZE 65536
+PRIVATE yielded_avl vm_yielded_blocks[YIELD_HASHSIZE];
+
+PRIVATE int avl_inited = 0;
+
+PUBLIC void map_region_init(void)
+{
+       int h;
+       assert(!avl_inited);
+       for(h = 0; h < YIELD_HASHSIZE; h++)
+               yielded_init(&vm_yielded_blocks[h]);
+       avl_inited = 1;
+}
+
+PRIVATE yielded_avl *get_yielded_avl(block_id_t id)
+{
+       u32_t h;
+
+       assert(avl_inited);
+
+       hash_i_64(id.owner, id.id, h);
+       h = h % YIELD_HASHSIZE;
+
+       assert(h >= 0);
+       assert(h < YIELD_HASHSIZE);
+
+       return &vm_yielded_blocks[h];
+}
+
 PRIVATE char *map_name(struct vir_region *vr)
 {
        static char name[100];
@@ -435,9 +466,6 @@ PRIVATE vir_bytes region_find_slot_range(struct vmproc *vmp,
                        nextvr = region_get_iter(&iter);
                        FREEVRANGE(vr->vaddr + vr->length,
                          nextvr ? nextvr->vaddr : VM_DATATOP);
-                       if(!foundflag) {
-                               printf("incr from 0x%lx to 0x%lx; v range 0x%lx-0x%lx\n", vr->vaddr, nextvr->vaddr);
-                       }
                }
        }
 
@@ -721,27 +749,52 @@ PRIVATE int map_free(struct vmproc *vmp, struct vir_region *region)
        return OK;
 }
 
+/*===========================================================================*
+ *                             yielded_block_cmp                            *
+ *===========================================================================*/
+PUBLIC int yielded_block_cmp(struct block_id *id1, struct block_id *id2)
+{
+       if(id1->owner < id2->owner)
+               return -1;
+       if(id1->owner > id2->owner)
+               return 1;
+       return cmp64(id1->id, id2->id);
+}
+
 
 /*===========================================================================*
  *                             free_yielded_proc                            *
  *===========================================================================*/
 PRIVATE vir_bytes free_yielded_proc(struct vmproc *vmp)
 {
-       yielded_t *yb;
-       int y = 0;
        vir_bytes total = 0;
+       int h;
 
        SANITYCHECK(SCL_FUNCTIONS);
 
        /* Free associated regions. */
-       while((yb = yielded_search_root(&vmp->vm_yielded_blocks))) {
-               SLABSANE(yb);
-               total += freeyieldednode(yb, 1);
-               y++;
+       for(h = 0; h < YIELD_HASHSIZE && vmp->vm_yielded > 0; h++) {
+               yielded_t *yb;
+               yielded_iter iter;
+               yielded_avl *avl = &vm_yielded_blocks[h];
+               yielded_start_iter_least(avl, &iter);
+               while((yb = yielded_get_iter(&iter))) {
+                       yielded_t *next_yb;
+                       SLABSANE(yb);
+                       yielded_incr_iter(&iter);
+                       if(yb->id.owner != vmp->vm_endpoint)
+                               continue;
+                       next_yb = yielded_get_iter(&iter); 
+                       total += freeyieldednode(yb, 1);
+                       /* the above removal invalidated our iter; restart it
+                        * for the node we want to start at.
+                        */
+                       if(!next_yb) break; 
+                       yielded_start_iter(avl, &iter, next_yb->id, AVL_EQUAL);
+                       assert(yielded_get_iter(&iter) == next_yb);
+               }
        }
 
-       yielded_init(&vmp->vm_yielded_blocks);
-
        return total;
 }
 
@@ -749,8 +802,9 @@ PRIVATE vir_bytes free_yielded_proc(struct vmproc *vmp)
 PRIVATE phys_bytes freeyieldednode(yielded_t *node, int freemem)
 {
        yielded_t *older, *younger, *removed;
-       int p;
        vir_bytes len;
+       yielded_avl *avl; 
+       int p;
 
        SLABSANE(node);
 
@@ -783,11 +837,13 @@ PRIVATE phys_bytes freeyieldednode(yielded_t *node, int freemem)
 
        /* Update AVL. */
 
-       if(vm_isokendpt(node->owner, &p) != OK)
-               panic("out of date owner of yielded block %d", node->owner);
-
-       removed = yielded_remove(&vmproc[p].vm_yielded_blocks, node->id);
+       if(vm_isokendpt(node->id.owner, &p) != OK)
+               panic("out of date owner of yielded block %d", node->id.owner);
+       avl = get_yielded_avl(node->id);
+       removed = yielded_remove(avl, node->id);
        assert(removed == node);
+       assert(vmproc[p].vm_yielded > 0);
+       vmproc[p].vm_yielded--;
 
        /* Free associated memory if requested. */
 
@@ -1199,7 +1255,6 @@ PUBLIC int map_pin_memory(struct vmproc *vmp)
                }
                region_incr_iter(&iter);
        }
-
        return OK;
 }
 
@@ -2388,9 +2443,14 @@ PRIVATE int getblock(struct vmproc *vmp, u64_t id,
        yielded_t *yb;
        struct phys_region *ph;
        struct vir_region *region;
+       yielded_avl *avl;
+       block_id_t blockid;
 
        /* Try to get the yielded block */
-       if(!(yb = yielded_search(&vmp->vm_yielded_blocks, id, AVL_EQUAL))) {
+       blockid.owner = vmp->vm_endpoint;
+       blockid.id = id;
+       avl = get_yielded_avl(blockid);
+       if(!(yb = yielded_search(avl, blockid, AVL_EQUAL))) {
                return ESRCH;
        }
 
@@ -2434,11 +2494,16 @@ PRIVATE int yieldblock(struct vmproc *vmp, u64_t id,
        vir_bytes mem_clicks, newmem, clicks;
        struct vir_region *region;
        struct phys_region *ph;
+       yielded_avl *avl;
+       block_id_t blockid;
 
        /* Makes no sense if yielded block ID already exists, and
         * is likely a serious bug in the caller.
         */
-       if(yielded_search(&vmp->vm_yielded_blocks, id, AVL_EQUAL)) {
+       blockid.id = id;
+       blockid.owner = vmp->vm_endpoint;
+       avl = get_yielded_avl(blockid);
+       if(yielded_search(avl, blockid, AVL_EQUAL)) {
                printf("!");
                return EINVAL;
        }
@@ -2465,10 +2530,9 @@ PRIVATE int yieldblock(struct vmproc *vmp, u64_t id,
 
        /* Update yielded block info. */
        USE(newyb,
-               newyb->id = id;
+               newyb->id = blockid;
                newyb->addr = ph->ph->phys;
                newyb->len = ph->ph->length;
-               newyb->owner = vmp->vm_endpoint;
                newyb->younger = NULL;);
 
        /* Set new phys block to new addr and update pagetable. */
@@ -2482,7 +2546,9 @@ PRIVATE int yieldblock(struct vmproc *vmp, u64_t id,
        }
 
        /* Remember yielded block. */
-       yielded_insert(&vmp->vm_yielded_blocks, newyb);
+
+       yielded_insert(avl, newyb);
+       vmp->vm_yielded++;
 
        /* Add to LRU list too. It's the youngest block. */
        LRUCHECK;
@@ -2542,6 +2608,8 @@ PUBLIC int do_forgetblock(message *m)
        endpoint_t caller = m->m_source;
        yielded_t *yb;
        u64_t id;
+       block_id_t blockid;
+       yielded_avl *avl;
 
        if(vm_isokendpt(caller, &n) != OK)
                panic("do_yield_block: message from strange source: %d",
@@ -2556,7 +2624,10 @@ PUBLIC int do_forgetblock(message *m)
 
        id = make64(m->VMFB_IDLO, m->VMFB_IDHI);
 
-       if((yb = yielded_search(&vmp->vm_yielded_blocks, id, AVL_EQUAL))) {
+       blockid.id = id;
+       blockid.owner = vmp->vm_endpoint;
+       avl = get_yielded_avl(blockid);
+       if((yb = yielded_search(avl, blockid, AVL_EQUAL))) {
                freeyieldednode(yb, 1);
        }
 
index a937c9db4d52997321bf260aa6690812d0386cef..cf2a51c9d9c16b6371a554dd7db0d78fb7157846 100644 (file)
@@ -467,6 +467,9 @@ PUBLIC void slabfree(void *mem, int bytes)
 #if SANITYCHECKS
 #if MEMPROTECT
        slabunlock(mem, bytes);
+#endif
+#if JUNKFREE
+       memset(mem, 0xa6, bytes);
 #endif
        *(u32_t *) mem = JUNK;
        nojunkwarning++;
index 126c8f7d8c1091652647c4cd02968e0d770f7ba5..b25395bac9622f579ed0382ff19151788e1e8b5c 100644 (file)
@@ -274,10 +274,6 @@ PUBLIC int swap_proc_slot(struct vmproc *src_vmp, struct vmproc *dst_vmp)
        dst_vmp->vm_endpoint = orig_dst_vmproc.vm_endpoint;
        dst_vmp->vm_slot = orig_dst_vmproc.vm_slot;
 
-       /* Preserve yielded blocks. */
-       src_vmp->vm_yielded_blocks = orig_src_vmproc.vm_yielded_blocks;
-       dst_vmp->vm_yielded_blocks = orig_dst_vmproc.vm_yielded_blocks;
-
 #if LU_DEBUG
        printf("VM: swap_proc: swapped %d (%d) and %d (%d)\n",
            src_vmp->vm_endpoint, src_vmp->vm_slot,
index 2f67db371a3362376438b9117d255a072fbbea82..0b7956bb7fde7ee0e66588dc0e0a3c4d87a012ba 100644 (file)
@@ -32,7 +32,6 @@ struct vmproc {
        /* Regions in virtual address space. */
        region_avl vm_regions_avl;
        vir_bytes  vm_region_top;       /* highest vaddr last inserted */
-       yielded_avl     vm_yielded_blocks;       /* avl of yielded physblocks */
 
        /* Heap for brk() to extend. */
        struct vir_region *vm_heap;
@@ -46,6 +45,7 @@ struct vmproc {
        int vm_callback_type; /* expected message type */
 
        int vm_slot;            /* process table slot */
+       int vm_yielded;         /* yielded regions */
 
        union {
                struct {
index 4df1647796a8e531c11586d25ddd2707982a2d34..a4f86c8a12f4d0bfde2a9f46b7a9b26b341c910d 100644 (file)
@@ -4,10 +4,17 @@
 
 #include <minix/type.h>
 
-typedef struct yielded {
+typedef struct block_id {
        u64_t           id;
-       phys_bytes      addr, len;
        endpoint_t      owner;
+} block_id_t;
+
+typedef struct yielded {
+       /* the owner-given id and owner together
+        * uniquely identify a yielded block.
+        */
+       block_id_t      id;
+       phys_bytes      addr, len;
 
        /* LRU fields */
        struct yielded  *younger, *older;
index e7233f8066a47600e63d38cbc1be21f36dc9a7ef..43eda779d731683337a1a2dc02805c78ff69c9f2 100644 (file)
@@ -2,7 +2,7 @@
 
 #define AVL_UNIQUE(id) yielded_ ## id
 #define AVL_HANDLE yielded_t *
-#define AVL_KEY u64_t
+#define AVL_KEY block_id_t
 #define AVL_MAX_DEPTH 30 /* good for 2 million nodes */
 #define AVL_NULL NULL
 #define AVL_GET_LESS(h, a) (h)->less
@@ -12,7 +12,7 @@
 #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) cmp64((k1), (k2))
+#define AVL_COMPARE_KEY_KEY(k1, k2) yielded_block_cmp(&(k1), &(k2))
 #define AVL_COMPARE_KEY_NODE(k, h) AVL_COMPARE_KEY_KEY((k), (h)->id)
 #define AVL_COMPARE_NODE_NODE(h1, h2) AVL_COMPARE_KEY_KEY((h1)->id, (h2)->id)
 #define AVL_INSIDE_STRUCT char pad[4];