VM: abstract datastructures a bit
. a little less duplication in region.c
This commit is contained in:
parent
0d1f2e6be2
commit
16c3870b2e
@ -4,7 +4,7 @@
|
|||||||
PROG= vm
|
PROG= vm
|
||||||
SRCS= main.c alloc.c utility.c exit.c fork.c break.c \
|
SRCS= main.c alloc.c utility.c exit.c fork.c break.c \
|
||||||
mmap.c slaballoc.c region.c pagefaults.c \
|
mmap.c slaballoc.c region.c pagefaults.c \
|
||||||
physravl.c rs.c queryexit.c yieldedavl.c regionavl.c
|
physravl.c rs.c queryexit.c yieldedavl.c regionavl.c pb.c
|
||||||
|
|
||||||
DPADD+= ${LIBSYS}
|
DPADD+= ${LIBSYS}
|
||||||
LDADD+= -lsys -lexec
|
LDADD+= -lsys -lexec
|
||||||
|
120
servers/vm/pb.c
Normal file
120
servers/vm/pb.c
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
|
||||||
|
#define _SYSTEM 1
|
||||||
|
|
||||||
|
#include <minix/com.h>
|
||||||
|
#include <minix/callnr.h>
|
||||||
|
#include <minix/type.h>
|
||||||
|
#include <minix/config.h>
|
||||||
|
#include <minix/const.h>
|
||||||
|
#include <minix/sysutil.h>
|
||||||
|
#include <minix/syslib.h>
|
||||||
|
#include <minix/debug.h>
|
||||||
|
#include <minix/bitmap.h>
|
||||||
|
#include <minix/hash.h>
|
||||||
|
|
||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <memory.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
|
||||||
|
#include "vm.h"
|
||||||
|
#include "proto.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "glo.h"
|
||||||
|
#include "region.h"
|
||||||
|
#include "sanitycheck.h"
|
||||||
|
#include "physravl.h"
|
||||||
|
#include "memlist.h"
|
||||||
|
|
||||||
|
struct phys_block *pb_new(phys_bytes phys)
|
||||||
|
{
|
||||||
|
struct phys_block *newpb;
|
||||||
|
|
||||||
|
if(!SLABALLOC(newpb)) {
|
||||||
|
printf("vm: pb_new: couldn't allocate phys block\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(!(phys % VM_PAGE_SIZE));
|
||||||
|
assert(phys != MAP_NONE);
|
||||||
|
|
||||||
|
USE(newpb,
|
||||||
|
newpb->phys = phys;
|
||||||
|
newpb->refcount = 0;
|
||||||
|
newpb->firstregion = NULL;
|
||||||
|
);
|
||||||
|
|
||||||
|
return newpb;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct phys_region *pb_reference(struct phys_block *newpb, vir_bytes offset, struct vir_region *region)
|
||||||
|
{
|
||||||
|
struct phys_region *newphysr;
|
||||||
|
|
||||||
|
if(!SLABALLOC(newphysr)) {
|
||||||
|
printf("vm: pb_reference: couldn't allocate phys region\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* New physical region. */
|
||||||
|
USE(newphysr,
|
||||||
|
newphysr->offset = offset;
|
||||||
|
newphysr->ph = newpb;
|
||||||
|
newphysr->parent = region;
|
||||||
|
newphysr->next_ph_list = newpb->firstregion;
|
||||||
|
newpb->firstregion = newphysr;);
|
||||||
|
|
||||||
|
newpb->refcount++;
|
||||||
|
physr_insert(region->phys, newphysr);
|
||||||
|
|
||||||
|
return newphysr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* pb_unreferenced *
|
||||||
|
*===========================================================================*/
|
||||||
|
void pb_unreferenced(struct vir_region *region, struct phys_region *pr)
|
||||||
|
{
|
||||||
|
struct phys_block *pb;
|
||||||
|
|
||||||
|
pb = pr->ph;
|
||||||
|
assert(pb->refcount > 0);
|
||||||
|
USE(pb, pb->refcount--;);
|
||||||
|
assert(pb->refcount >= 0);
|
||||||
|
|
||||||
|
if(pb->firstregion == pr) {
|
||||||
|
USE(pb, pb->firstregion = pr->next_ph_list;);
|
||||||
|
} else {
|
||||||
|
struct phys_region *others;
|
||||||
|
|
||||||
|
for(others = pb->firstregion; others;
|
||||||
|
others = others->next_ph_list) {
|
||||||
|
assert(others->ph == pb);
|
||||||
|
if(others->next_ph_list == pr) {
|
||||||
|
USE(others, others->next_ph_list = pr->next_ph_list;);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(others); /* Otherwise, wasn't on the list. */
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pb->refcount == 0) {
|
||||||
|
assert(!pb->firstregion);
|
||||||
|
if(region->flags & VR_ANON) {
|
||||||
|
free_mem(ABS2CLICK(pb->phys), 1);
|
||||||
|
} else if(region->flags & VR_DIRECT) {
|
||||||
|
; /* No action required. */
|
||||||
|
} else {
|
||||||
|
panic("strange phys flags");
|
||||||
|
}
|
||||||
|
SLABFREE(pb);
|
||||||
|
}
|
||||||
|
|
||||||
|
physr_remove(region->phys, pr->offset);
|
||||||
|
}
|
@ -184,3 +184,9 @@ int do_query_exit(message *m);
|
|||||||
int do_watch_exit(message *m);
|
int do_watch_exit(message *m);
|
||||||
int do_notify_sig(message *m);
|
int do_notify_sig(message *m);
|
||||||
void init_query_exit(void);
|
void init_query_exit(void);
|
||||||
|
|
||||||
|
/* pb.c */
|
||||||
|
struct phys_block *pb_new(phys_bytes phys);
|
||||||
|
struct phys_region *pb_reference(struct phys_block *newpb,
|
||||||
|
vir_bytes offset, struct vir_region *region);
|
||||||
|
void pb_unreferenced(struct vir_region *region, struct phys_region *pr);
|
||||||
|
@ -342,7 +342,7 @@ void blockstats(void)
|
|||||||
LRUCHECK;
|
LRUCHECK;
|
||||||
|
|
||||||
for(list = lru_youngest; list; list = list->older) {
|
for(list = lru_youngest; list; list = list->older) {
|
||||||
mem += list->len;
|
mem += VM_PAGE_SIZE;
|
||||||
blocks++;
|
blocks++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -512,6 +512,37 @@ static vir_bytes region_find_slot(struct vmproc *vmp,
|
|||||||
return region_find_slot_range(vmp, minv, maxv, length);
|
return region_find_slot_range(vmp, minv, maxv, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct vir_region *region_new(struct vmproc *vmp, vir_bytes startv, vir_bytes length, int flags)
|
||||||
|
{
|
||||||
|
physr_avl *phavl;
|
||||||
|
struct vir_region *newregion;
|
||||||
|
|
||||||
|
if(!(SLABALLOC(newregion))) {
|
||||||
|
printf("vm: region_new: could not allocate\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fill in node details. */
|
||||||
|
USE(newregion,
|
||||||
|
newregion->vaddr = startv;
|
||||||
|
newregion->length = length;
|
||||||
|
newregion->flags = flags;
|
||||||
|
newregion->tag = VRT_NONE;
|
||||||
|
newregion->lower = newregion->higher = NULL;
|
||||||
|
newregion->parent = vmp;);
|
||||||
|
|
||||||
|
SLABALLOC(phavl);
|
||||||
|
if(!phavl) {
|
||||||
|
printf("VM: region_new: allocating phys avl failed\n");
|
||||||
|
SLABFREE(newregion);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
USE(newregion, newregion->phys = phavl;);
|
||||||
|
physr_init(newregion->phys);
|
||||||
|
|
||||||
|
return newregion;
|
||||||
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* map_page_region *
|
* map_page_region *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
@ -527,7 +558,6 @@ int mapflags;
|
|||||||
{
|
{
|
||||||
struct vir_region *newregion;
|
struct vir_region *newregion;
|
||||||
vir_bytes startv;
|
vir_bytes startv;
|
||||||
physr_avl *phavl;
|
|
||||||
|
|
||||||
assert(!(length % VM_PAGE_SIZE));
|
assert(!(length % VM_PAGE_SIZE));
|
||||||
|
|
||||||
@ -543,29 +573,11 @@ int mapflags;
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* Now we want a new region. */
|
/* Now we want a new region. */
|
||||||
if(!SLABALLOC(newregion)) {
|
if(!(newregion = region_new(vmp, startv, length, flags))) {
|
||||||
printf("VM: map_page_region: allocating region failed\n");
|
printf("VM: map_page_region: allocating region failed\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fill in node details. */
|
|
||||||
USE(newregion,
|
|
||||||
newregion->vaddr = startv;
|
|
||||||
newregion->length = length;
|
|
||||||
newregion->flags = flags;
|
|
||||||
newregion->tag = VRT_NONE;
|
|
||||||
newregion->parent = vmp;);
|
|
||||||
|
|
||||||
SLABALLOC(phavl);
|
|
||||||
if(!phavl) {
|
|
||||||
printf("VM: map_page_region: allocating phys avl failed\n");
|
|
||||||
SLABFREE(newregion);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
USE(newregion, newregion->phys = phavl;);
|
|
||||||
|
|
||||||
physr_init(newregion->phys);
|
|
||||||
|
|
||||||
/* If we know what we're going to map to, map it right away. */
|
/* If we know what we're going to map to, map it right away. */
|
||||||
if(what != MAP_NONE) {
|
if(what != MAP_NONE) {
|
||||||
assert(!(what % VM_PAGE_SIZE));
|
assert(!(what % VM_PAGE_SIZE));
|
||||||
@ -614,48 +626,6 @@ USE(newregion,
|
|||||||
return newregion;
|
return newregion;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* pb_unreferenced *
|
|
||||||
*===========================================================================*/
|
|
||||||
void pb_unreferenced(struct vir_region *region, struct phys_region *pr)
|
|
||||||
{
|
|
||||||
struct phys_block *pb;
|
|
||||||
|
|
||||||
pb = pr->ph;
|
|
||||||
assert(pb->refcount > 0);
|
|
||||||
USE(pb, pb->refcount--;);
|
|
||||||
assert(pb->refcount >= 0);
|
|
||||||
|
|
||||||
if(pb->firstregion == pr) {
|
|
||||||
USE(pb, pb->firstregion = pr->next_ph_list;);
|
|
||||||
} else {
|
|
||||||
struct phys_region *others;
|
|
||||||
|
|
||||||
for(others = pb->firstregion; others;
|
|
||||||
others = others->next_ph_list) {
|
|
||||||
assert(others->ph == pb);
|
|
||||||
if(others->next_ph_list == pr) {
|
|
||||||
USE(others, others->next_ph_list = pr->next_ph_list;);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(others); /* Otherwise, wasn't on the list. */
|
|
||||||
}
|
|
||||||
|
|
||||||
if(pb->refcount == 0) {
|
|
||||||
assert(!pb->firstregion);
|
|
||||||
if(region->flags & VR_ANON) {
|
|
||||||
free_mem(ABS2CLICK(pb->phys), 1);
|
|
||||||
} else if(region->flags & VR_DIRECT) {
|
|
||||||
; /* No action required. */
|
|
||||||
} else {
|
|
||||||
panic("strange phys flags");
|
|
||||||
}
|
|
||||||
SLABFREE(pb);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct phys_region *reset_physr_iter(struct vir_region *region,
|
static struct phys_region *reset_physr_iter(struct vir_region *region,
|
||||||
physr_iter *iter, vir_bytes offset)
|
physr_iter *iter, vir_bytes offset)
|
||||||
{
|
{
|
||||||
@ -672,8 +642,7 @@ static struct phys_region *reset_physr_iter(struct vir_region *region,
|
|||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* map_subfree *
|
* map_subfree *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
static int map_subfree(struct vmproc *vmp,
|
static int map_subfree(struct vir_region *region, vir_bytes len)
|
||||||
struct vir_region *region, vir_bytes len)
|
|
||||||
{
|
{
|
||||||
struct phys_region *pr;
|
struct phys_region *pr;
|
||||||
physr_iter iter;
|
physr_iter iter;
|
||||||
@ -706,7 +675,6 @@ static int map_subfree(struct vmproc *vmp,
|
|||||||
break;
|
break;
|
||||||
if(pr->offset + VM_PAGE_SIZE <= len) {
|
if(pr->offset + VM_PAGE_SIZE <= len) {
|
||||||
pb_unreferenced(region, pr);
|
pb_unreferenced(region, pr);
|
||||||
physr_remove(region->phys, pr->offset);
|
|
||||||
physr_start_iter_least(region->phys, &iter);
|
physr_start_iter_least(region->phys, &iter);
|
||||||
SLABFREE(pr);
|
SLABFREE(pr);
|
||||||
}
|
}
|
||||||
@ -718,11 +686,11 @@ static int map_subfree(struct vmproc *vmp,
|
|||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* map_free *
|
* map_free *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
static int map_free(struct vmproc *vmp, struct vir_region *region)
|
static int map_free(struct vir_region *region)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if((r=map_subfree(vmp, region, region->length)) != OK) {
|
if((r=map_subfree(region, region->length)) != OK) {
|
||||||
printf("%d\n", __LINE__);
|
printf("%d\n", __LINE__);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@ -874,7 +842,7 @@ struct vmproc *vmp;
|
|||||||
nocheck++;
|
nocheck++;
|
||||||
#endif
|
#endif
|
||||||
region_remove(&vmp->vm_regions_avl, r->vaddr); /* For sanity checks. */
|
region_remove(&vmp->vm_regions_avl, r->vaddr); /* For sanity checks. */
|
||||||
map_free(vmp, r);
|
map_free(r);
|
||||||
#if SANITYCHECKS
|
#if SANITYCHECKS
|
||||||
nocheck--;
|
nocheck--;
|
||||||
#endif
|
#endif
|
||||||
@ -989,7 +957,8 @@ int written;
|
|||||||
struct phys_block *newpb = NULL;
|
struct phys_block *newpb = NULL;
|
||||||
|
|
||||||
/* Allocate things necessary for this chunk of memory. */
|
/* Allocate things necessary for this chunk of memory. */
|
||||||
if(!SLABALLOC(newphysr) || !SLABALLOC(newpb)) {
|
if(!(newpb = pb_new(ml->phys)) ||
|
||||||
|
!(newphysr = pb_reference(newpb, offset, region))) {
|
||||||
printf("map_new_physblock: no memory for the ph slabs\n");
|
printf("map_new_physblock: no memory for the ph slabs\n");
|
||||||
if(newphysr) SLABFREE(newphysr);
|
if(newphysr) SLABFREE(newphysr);
|
||||||
if(newpb) SLABFREE(newpb);
|
if(newpb) SLABFREE(newpb);
|
||||||
@ -997,27 +966,6 @@ int written;
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(!(ml->phys % VM_PAGE_SIZE));
|
|
||||||
|
|
||||||
assert(ml->phys != MAP_NONE);
|
|
||||||
|
|
||||||
USE(newpb,
|
|
||||||
newpb->phys = ml->phys;
|
|
||||||
newpb->refcount = 1;
|
|
||||||
newpb->firstregion = newphysr;);
|
|
||||||
|
|
||||||
/* New physical region. */
|
|
||||||
USE(newphysr,
|
|
||||||
newphysr->offset = offset;
|
|
||||||
newphysr->ph = newpb;
|
|
||||||
newphysr->parent = region;
|
|
||||||
/* No other references to this block. */
|
|
||||||
newphysr->next_ph_list = NULL;);
|
|
||||||
|
|
||||||
#if SANITYCHECKS
|
|
||||||
USE(newphysr, newphysr->written = written;);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Update pagetable. */
|
/* Update pagetable. */
|
||||||
if(map_ph_writept(vmp, region, newphysr) != OK) {
|
if(map_ph_writept(vmp, region, newphysr) != OK) {
|
||||||
printf("map_new_physblock: map_ph_writept failed\n");
|
printf("map_new_physblock: map_ph_writept failed\n");
|
||||||
@ -1025,8 +973,6 @@ int written;
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
physr_insert(region->phys, newphysr);
|
|
||||||
|
|
||||||
offset += VM_PAGE_SIZE;
|
offset += VM_PAGE_SIZE;
|
||||||
mapped += VM_PAGE_SIZE;
|
mapped += VM_PAGE_SIZE;
|
||||||
}
|
}
|
||||||
@ -1040,7 +986,6 @@ int written;
|
|||||||
AVL_EQUAL))) {
|
AVL_EQUAL))) {
|
||||||
assert(physr->ph->refcount == 1);
|
assert(physr->ph->refcount == 1);
|
||||||
pb_unreferenced(region, physr);
|
pb_unreferenced(region, physr);
|
||||||
physr_remove(region->phys, physr->offset);
|
|
||||||
SLABFREE(physr);
|
SLABFREE(physr);
|
||||||
}
|
}
|
||||||
offset += VM_PAGE_SIZE;
|
offset += VM_PAGE_SIZE;
|
||||||
@ -1080,7 +1025,7 @@ physr_iter *iter;
|
|||||||
|
|
||||||
/* Warning: this function will free the passed
|
/* Warning: this function will free the passed
|
||||||
* phys_region *ph and replace it (in the same offset)
|
* phys_region *ph and replace it (in the same offset)
|
||||||
* with one or more others! So both the pointer to it
|
* with another! So both the pointer to it
|
||||||
* and any iterators over the phys_regions in the vir_region
|
* and any iterators over the phys_regions in the vir_region
|
||||||
* will be invalid on successful return. (Iterators over
|
* will be invalid on successful return. (Iterators over
|
||||||
* the vir_region could be invalid on unsuccessful return too.)
|
* the vir_region could be invalid on unsuccessful return too.)
|
||||||
@ -1109,7 +1054,6 @@ physr_iter *iter;
|
|||||||
assert(ph->ph->refcount > 1);
|
assert(ph->ph->refcount > 1);
|
||||||
pb_unreferenced(region, ph);
|
pb_unreferenced(region, ph);
|
||||||
assert(ph->ph->refcount >= 1);
|
assert(ph->ph->refcount >= 1);
|
||||||
physr_remove(region->phys, offset);
|
|
||||||
SLABFREE(ph);
|
SLABFREE(ph);
|
||||||
|
|
||||||
SANITYCHECK(SCL_DETAIL);
|
SANITYCHECK(SCL_DETAIL);
|
||||||
@ -1400,44 +1344,22 @@ static struct vir_region *map_copy_region(struct vmproc *vmp, struct vir_region
|
|||||||
struct vir_region *newvr;
|
struct vir_region *newvr;
|
||||||
struct phys_region *ph;
|
struct phys_region *ph;
|
||||||
physr_iter iter;
|
physr_iter iter;
|
||||||
physr_avl *phavl;
|
|
||||||
#if SANITYCHECKS
|
#if SANITYCHECKS
|
||||||
int cr;
|
int cr;
|
||||||
cr = count_phys_regions(vr);
|
cr = count_phys_regions(vr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(!SLABALLOC(newvr))
|
if(!(newvr = region_new(vr->parent, vr->vaddr, vr->length, vr->flags)))
|
||||||
return NULL;
|
return NULL;
|
||||||
SLABALLOC(phavl);
|
|
||||||
if(!phavl) {
|
|
||||||
SLABFREE(newvr);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
USE(newvr,
|
|
||||||
*newvr = *vr;
|
|
||||||
newvr->lower = newvr->higher = NULL;
|
|
||||||
newvr->phys = phavl;
|
|
||||||
);
|
|
||||||
|
|
||||||
physr_init(newvr->phys);
|
|
||||||
|
|
||||||
physr_start_iter_least(vr->phys, &iter);
|
physr_start_iter_least(vr->phys, &iter);
|
||||||
while((ph = physr_get_iter(&iter))) {
|
while((ph = physr_get_iter(&iter))) {
|
||||||
struct phys_region *newph;
|
struct phys_region *newph = pb_reference(ph->ph, ph->offset, newvr);
|
||||||
if(!SLABALLOC(newph)) {
|
|
||||||
map_free(vmp, newvr);
|
if(!newph) { map_free(newvr); return NULL; }
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
USE(newph,
|
|
||||||
newph->ph = ph->ph;
|
|
||||||
newph->next_ph_list = NULL;
|
|
||||||
newph->parent = newvr;
|
|
||||||
newph->offset = ph->offset;);
|
|
||||||
#if SANITYCHECKS
|
#if SANITYCHECKS
|
||||||
USE(newph, newph->written = 0;);
|
USE(newph, newph->written = 0;);
|
||||||
#endif
|
|
||||||
physr_insert(newvr->phys, newph);
|
|
||||||
#if SANITYCHECKS
|
|
||||||
assert(count_phys_regions(vr) == cr);
|
assert(count_phys_regions(vr) == cr);
|
||||||
#endif
|
#endif
|
||||||
physr_incr_iter(&iter);
|
physr_incr_iter(&iter);
|
||||||
@ -1591,17 +1513,7 @@ struct vir_region *start_src_vr;
|
|||||||
assert(orig_ph);
|
assert(orig_ph);
|
||||||
assert(orig_ph != new_ph);
|
assert(orig_ph != new_ph);
|
||||||
pb = orig_ph->ph;
|
pb = orig_ph->ph;
|
||||||
assert(pb == new_ph->ph);
|
assert(orig_ph->ph == new_ph->ph);
|
||||||
|
|
||||||
/* Link in new physregion. */
|
|
||||||
assert(!new_ph->next_ph_list);
|
|
||||||
USE(new_ph, new_ph->next_ph_list = pb->firstregion;);
|
|
||||||
USE(pb, pb->firstregion = new_ph;);
|
|
||||||
|
|
||||||
/* Increase phys block refcount */
|
|
||||||
assert(pb->refcount > 0);
|
|
||||||
USE(pb, pb->refcount++;);
|
|
||||||
assert(pb->refcount > 1);
|
|
||||||
|
|
||||||
/* If the phys block has been shared as SMAP,
|
/* If the phys block has been shared as SMAP,
|
||||||
* do the regular copy. */
|
* do the regular copy. */
|
||||||
@ -1766,7 +1678,7 @@ int map_unmap_region(struct vmproc *vmp, struct vir_region *r,
|
|||||||
SANITYCHECK(SCL_DETAIL);
|
SANITYCHECK(SCL_DETAIL);
|
||||||
/* Whole region disappears. Unlink and free it. */
|
/* Whole region disappears. Unlink and free it. */
|
||||||
region_remove(&vmp->vm_regions_avl, r->vaddr);
|
region_remove(&vmp->vm_regions_avl, r->vaddr);
|
||||||
map_free(vmp, r);
|
map_free(r);
|
||||||
} else {
|
} else {
|
||||||
struct phys_region *pr;
|
struct phys_region *pr;
|
||||||
physr_iter iter;
|
physr_iter iter;
|
||||||
@ -1774,7 +1686,7 @@ int map_unmap_region(struct vmproc *vmp, struct vir_region *r,
|
|||||||
* and then shrink the region.
|
* and then shrink the region.
|
||||||
*/
|
*/
|
||||||
SANITYCHECK(SCL_DETAIL);
|
SANITYCHECK(SCL_DETAIL);
|
||||||
map_subfree(vmp, r, len);
|
map_subfree(r, len);
|
||||||
USE(r,
|
USE(r,
|
||||||
r->vaddr += len;
|
r->vaddr += len;
|
||||||
r->length -= len;);
|
r->length -= len;);
|
||||||
@ -1855,11 +1767,6 @@ int map_remap(struct vmproc *dvmp, vir_bytes da, size_t size,
|
|||||||
|
|
||||||
physr_start_iter_least(vr->phys, &iter);
|
physr_start_iter_least(vr->phys, &iter);
|
||||||
while((ph = physr_get_iter(&iter))) {
|
while((ph = physr_get_iter(&iter))) {
|
||||||
struct phys_block *pb = ph->ph;
|
|
||||||
assert(!ph->next_ph_list);
|
|
||||||
USE(ph, ph->next_ph_list = pb->firstregion;);
|
|
||||||
USE(pb, pb->firstregion = ph;);
|
|
||||||
USE(pb, pb->refcount++;);
|
|
||||||
if(map_ph_writept(dvmp, vr, ph) != OK) {
|
if(map_ph_writept(dvmp, vr, ph) != OK) {
|
||||||
panic("map_remap: map_ph_writept failed");
|
panic("map_remap: map_ph_writept failed");
|
||||||
}
|
}
|
||||||
@ -2096,18 +2003,9 @@ static int do_map_memory(struct vmproc *vms, struct vmproc *vmd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate a new phys region. */
|
/* Allocate a new phys region. */
|
||||||
if(!SLABALLOC(newphysr))
|
if(!(newphysr = pb_reference(pb, offset_d, vrd)))
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
|
|
||||||
/* Set and link the new phys region to the block. */
|
|
||||||
newphysr->ph = pb;
|
|
||||||
newphysr->offset = offset_d;
|
|
||||||
newphysr->parent = vrd;
|
|
||||||
newphysr->next_ph_list = pb->firstregion;
|
|
||||||
pb->firstregion = newphysr;
|
|
||||||
physr_insert(newphysr->parent->phys, newphysr);
|
|
||||||
pb->refcount++;
|
|
||||||
|
|
||||||
/* If a COW share was requested but the phys block has already
|
/* If a COW share was requested but the phys block has already
|
||||||
* been shared as SMAP, give up on COW and copy the block for
|
* been shared as SMAP, give up on COW and copy the block for
|
||||||
* the destination phys region now.
|
* the destination phys region now.
|
||||||
@ -2207,7 +2105,6 @@ static void rm_phys_regions(struct vir_region *region,
|
|||||||
physr_start_iter(region->phys, &iter, begin, AVL_GREATER_EQUAL);
|
physr_start_iter(region->phys, &iter, begin, AVL_GREATER_EQUAL);
|
||||||
while((pr = physr_get_iter(&iter)) && pr->offset < begin + length) {
|
while((pr = physr_get_iter(&iter)) && pr->offset < begin + length) {
|
||||||
pb_unreferenced(region, pr);
|
pb_unreferenced(region, pr);
|
||||||
physr_remove(region->phys, pr->offset);
|
|
||||||
physr_start_iter(region->phys, &iter, begin,
|
physr_start_iter(region->phys, &iter, begin,
|
||||||
AVL_GREATER_EQUAL);
|
AVL_GREATER_EQUAL);
|
||||||
SLABFREE(pr);
|
SLABFREE(pr);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user