d343041caa
Introduce explicit abstractions for different mapping types, handling the instantiation, forking, pagefaults and freeing of anonymous memory, direct physical mappings, shared memory and physically contiguous anonymous memory as separate types, making region.c more generic. Also some other genericification like merging the 3 munmap cases into one. COW and SMAP safemap code is still implicit in region.c.
134 lines
2.7 KiB
C
134 lines
2.7 KiB
C
|
|
#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;
|
|
}
|
|
|
|
if(phys != MAP_NONE)
|
|
assert(!(phys % VM_PAGE_SIZE));
|
|
|
|
USE(newpb,
|
|
newpb->phys = phys;
|
|
newpb->refcount = 0;
|
|
newpb->firstregion = NULL;
|
|
);
|
|
|
|
return newpb;
|
|
}
|
|
|
|
void pb_free(struct phys_block *pb)
|
|
{
|
|
if(pb->phys != MAP_NONE)
|
|
free_mem(ABS2CLICK(pb->phys), 1);
|
|
SLABFREE(pb);
|
|
}
|
|
|
|
void pb_link(struct phys_region *newphysr, struct phys_block *newpb,
|
|
vir_bytes offset, struct vir_region *parent)
|
|
{
|
|
USE(newphysr,
|
|
newphysr->offset = offset;
|
|
newphysr->ph = newpb;
|
|
newphysr->parent = parent;
|
|
newphysr->next_ph_list = newpb->firstregion;
|
|
newphysr->memtype = parent->memtype;
|
|
newpb->firstregion = newphysr;);
|
|
newpb->refcount++;
|
|
}
|
|
|
|
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. */
|
|
pb_link(newphysr, newpb, offset, region);
|
|
|
|
physr_insert(region->phys, newphysr);
|
|
|
|
return newphysr;
|
|
}
|
|
|
|
/*===========================================================================*
|
|
* pb_unreferenced *
|
|
*===========================================================================*/
|
|
void pb_unreferenced(struct vir_region *region, struct phys_region *pr, int rm)
|
|
{
|
|
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);
|
|
int r;
|
|
if((r = region->memtype->ev_unreference(pr)) != OK)
|
|
panic("unref failed, %d", r);
|
|
|
|
SLABFREE(pb);
|
|
}
|
|
|
|
pr->ph = NULL;
|
|
|
|
if(rm) physr_remove(region->phys, pr->offset);
|
|
}
|