VM: full munmap
complete munmap implementation; single-page references made a general munmap() implementation possible to write cleanly. . memory: let the MIOCRAMSIZE ioctl set the imgrd device size (but only to 0) . let the ramdisk command set sizes to 0 . use this command to set /dev/imgrd to 0 after mounting /usr in /etc/rc, so the boot time ramdisk is freed (about 4MB currently)
This commit is contained in:
parent
16c3870b2e
commit
ed1af3c86c
15 changed files with 116 additions and 134 deletions
|
@ -28,8 +28,8 @@ main(int argc, char *argv[])
|
||||||
#define KFACTOR 1024
|
#define KFACTOR 1024
|
||||||
size = atol(argv[1])*KFACTOR;
|
size = atol(argv[1])*KFACTOR;
|
||||||
|
|
||||||
if(size <= 0) {
|
if(size < 0) {
|
||||||
fprintf(stderr, "size should be positive.\n");
|
fprintf(stderr, "size should be non-negative.\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
local defines and declarations
|
local defines and declarations
|
||||||
*/
|
*/
|
||||||
|
|
||||||
extern unsigned char _binary_imgrd_mfs_start[], *_binary_imgrd_mfs_end;
|
extern unsigned char _binary_imgrd_mfs_start, _binary_imgrd_mfs_end;
|
||||||
|
|
||||||
#define imgrd _binary_imgrd_mfs_start
|
#define imgrd &_binary_imgrd_mfs_start
|
||||||
#define imgrd_size \
|
#define imgrd_size \
|
||||||
((size_t)(_binary_imgrd_mfs_end - _binary_imgrd_mfs_start))
|
(((size_t) &_binary_imgrd_mfs_end - (size_t)&_binary_imgrd_mfs_start))
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
* Apr 20, 1992 device dependent/independent split (Kees J. Bot)
|
* Apr 20, 1992 device dependent/independent split (Kees J. Bot)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <minix/drivers.h>
|
#include <minix/drivers.h>
|
||||||
#include <minix/chardriver.h>
|
#include <minix/chardriver.h>
|
||||||
#include <minix/blockdriver.h>
|
#include <minix/blockdriver.h>
|
||||||
|
@ -100,6 +101,7 @@ static char dev_zero[ZERO_BUF_SIZE];
|
||||||
static void sef_local_startup(void);
|
static void sef_local_startup(void);
|
||||||
static int sef_cb_init_fresh(int type, sef_init_info_t *info);
|
static int sef_cb_init_fresh(int type, sef_init_info_t *info);
|
||||||
|
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* main *
|
* main *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
@ -528,30 +530,6 @@ static int m_block_close(dev_t minor)
|
||||||
}
|
}
|
||||||
openct[minor]--;
|
openct[minor]--;
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* Special case: free initial ramdisk after it's been unmounted once. */
|
|
||||||
if(minor == IMGRD_DEV && openct[minor] == 0 && m_vaddrs[IMGRD_DEV]) {
|
|
||||||
vir_bytes vaddr, vlen;
|
|
||||||
vaddr = m_vaddrs[IMGRD_DEV];
|
|
||||||
vlen = imgrd_size;
|
|
||||||
/* Align `inwards' so as to not unmap more than the initial
|
|
||||||
* ramdisk image.
|
|
||||||
*/
|
|
||||||
if(vaddr % PAGE_SIZE) {
|
|
||||||
vir_bytes o = PAGE_SIZE - (vaddr % PAGE_SIZE);
|
|
||||||
vlen -= o;
|
|
||||||
vaddr += o;
|
|
||||||
}
|
|
||||||
if(vlen % PAGE_SIZE) {
|
|
||||||
vlen -= vlen % PAGE_SIZE;
|
|
||||||
}
|
|
||||||
minix_munmap((void *) vaddr, vlen);
|
|
||||||
m_geom[IMGRD_DEV].dv_base= cvul64(0);
|
|
||||||
m_geom[IMGRD_DEV].dv_size= cvul64(0);
|
|
||||||
m_vaddrs[IMGRD_DEV] = 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return(OK);
|
return(OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -569,15 +547,20 @@ static int m_block_ioctl(dev_t minor, unsigned int request, endpoint_t endpt,
|
||||||
u32_t ramdev_size;
|
u32_t ramdev_size;
|
||||||
int s;
|
int s;
|
||||||
void *mem;
|
void *mem;
|
||||||
|
int is_imgrd = 0;
|
||||||
|
|
||||||
if (request != MIOCRAMSIZE)
|
if (request != MIOCRAMSIZE)
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
|
||||||
|
if(minor == IMGRD_DEV)
|
||||||
|
is_imgrd = 1;
|
||||||
|
|
||||||
/* Someone wants to create a new RAM disk with the given size.
|
/* Someone wants to create a new RAM disk with the given size.
|
||||||
* A ramdisk can be created only once, and only on RAM disk device.
|
* A ramdisk can be created only once, and only on RAM disk device.
|
||||||
*/
|
*/
|
||||||
if ((dv = m_block_part(minor)) == NULL) return ENXIO;
|
if ((dv = m_block_part(minor)) == NULL) return ENXIO;
|
||||||
if((minor < RAM_DEV_FIRST || minor > RAM_DEV_LAST) && minor != RAM_DEV_OLD) {
|
if((minor < RAM_DEV_FIRST || minor > RAM_DEV_LAST) &&
|
||||||
|
minor != RAM_DEV_OLD && !is_imgrd) {
|
||||||
printf("MEM: MIOCRAMSIZE: %d not a ramdisk\n", minor);
|
printf("MEM: MIOCRAMSIZE: %d not a ramdisk\n", minor);
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -587,6 +570,8 @@ static int m_block_ioctl(dev_t minor, unsigned int request, endpoint_t endpt,
|
||||||
sizeof(ramdev_size));
|
sizeof(ramdev_size));
|
||||||
if (s != OK)
|
if (s != OK)
|
||||||
return s;
|
return s;
|
||||||
|
if(is_imgrd)
|
||||||
|
ramdev_size = 0;
|
||||||
if(m_vaddrs[minor] && !cmp64(dv->dv_size, cvul64(ramdev_size))) {
|
if(m_vaddrs[minor] && !cmp64(dv->dv_size, cvul64(ramdev_size))) {
|
||||||
return(OK);
|
return(OK);
|
||||||
}
|
}
|
||||||
|
@ -597,21 +582,37 @@ static int m_block_ioctl(dev_t minor, unsigned int request, endpoint_t endpt,
|
||||||
return(EBUSY);
|
return(EBUSY);
|
||||||
}
|
}
|
||||||
if(m_vaddrs[minor]) {
|
if(m_vaddrs[minor]) {
|
||||||
u32_t size;
|
u32_t a, o;
|
||||||
|
u64_t size;
|
||||||
|
int r;
|
||||||
if(ex64hi(dv->dv_size)) {
|
if(ex64hi(dv->dv_size)) {
|
||||||
panic("huge old ramdisk");
|
panic("huge old ramdisk");
|
||||||
}
|
}
|
||||||
size = ex64lo(dv->dv_size);
|
size = dv->dv_size;
|
||||||
minix_munmap((void *) m_vaddrs[minor], size);
|
a = m_vaddrs[minor];
|
||||||
|
if((o = a % PAGE_SIZE)) {
|
||||||
|
vir_bytes l = PAGE_SIZE - o;
|
||||||
|
a += l;
|
||||||
|
size -= l;
|
||||||
|
}
|
||||||
|
size = rounddown(size, PAGE_SIZE);
|
||||||
|
r = minix_munmap((void *) a, size);
|
||||||
|
if(r != OK) {
|
||||||
|
printf("memory: WARNING: munmap failed: %d\n", r);
|
||||||
|
}
|
||||||
m_vaddrs[minor] = (vir_bytes) NULL;
|
m_vaddrs[minor] = (vir_bytes) NULL;
|
||||||
|
dv->dv_size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
printf("MEM:%d: allocating ramdisk of size 0x%x\n", minor, ramdev_size);
|
printf("MEM:%d: allocating ramdisk of size 0x%x\n", minor, ramdev_size);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
mem = NULL;
|
||||||
|
|
||||||
/* Try to allocate a piece of memory for the RAM disk. */
|
/* Try to allocate a piece of memory for the RAM disk. */
|
||||||
if((mem = minix_mmap(NULL, ramdev_size, PROT_READ|PROT_WRITE,
|
if(ramdev_size > 0 &&
|
||||||
|
(mem = minix_mmap(NULL, ramdev_size, PROT_READ|PROT_WRITE,
|
||||||
MAP_PREALLOC|MAP_ANON, -1, 0)) == MAP_FAILED) {
|
MAP_PREALLOC|MAP_ANON, -1, 0)) == MAP_FAILED) {
|
||||||
printf("MEM: failed to get memory for ramdisk\n");
|
printf("MEM: failed to get memory for ramdisk\n");
|
||||||
return(ENOMEM);
|
return(ENOMEM);
|
||||||
|
|
7
etc/rc
7
etc/rc
|
@ -121,9 +121,6 @@ start)
|
||||||
printroot >/etc/mtab # /etc/mtab keeps track of mounts
|
printroot >/etc/mtab # /etc/mtab keeps track of mounts
|
||||||
>/etc/utmp # /etc/utmp keeps track of logins
|
>/etc/utmp # /etc/utmp keeps track of logins
|
||||||
|
|
||||||
# Unmount now defunct ramdisk
|
|
||||||
umount /dev/imgrd > /dev/null || echo "Failed to unmount boot ramdisk"
|
|
||||||
|
|
||||||
# Use MFS binary only from kernel image?
|
# Use MFS binary only from kernel image?
|
||||||
if [ "`sysenv bin_img`" = 1 ]
|
if [ "`sysenv bin_img`" = 1 ]
|
||||||
then
|
then
|
||||||
|
@ -149,6 +146,10 @@ start)
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Unmount and free now defunct ramdisk
|
||||||
|
umount /dev/imgrd > /dev/null || echo "Failed to unmount boot ramdisk"
|
||||||
|
ramdisk 0 /dev/imgrd || echo "Failed to free boot ramdisk"
|
||||||
|
|
||||||
# Edit settings for boot system services
|
# Edit settings for boot system services
|
||||||
if [ "`sysenv skip_boot_config`" != 1 ]
|
if [ "`sysenv skip_boot_config`" != 1 ]
|
||||||
then
|
then
|
||||||
|
|
|
@ -984,8 +984,6 @@
|
||||||
# define VMUM_ADDR m1_p1
|
# define VMUM_ADDR m1_p1
|
||||||
# define VMUM_LEN m1_i1
|
# define VMUM_LEN m1_i1
|
||||||
|
|
||||||
#define VM_MUNMAP_TEXT (VM_RQ_BASE+19)
|
|
||||||
|
|
||||||
/* To VM: forget all my yielded blocks. */
|
/* To VM: forget all my yielded blocks. */
|
||||||
#define VM_FORGETBLOCKS (VM_RQ_BASE+22)
|
#define VM_FORGETBLOCKS (VM_RQ_BASE+22)
|
||||||
|
|
||||||
|
@ -1090,7 +1088,7 @@
|
||||||
|
|
||||||
/* Basic vm calls allowed to every process. */
|
/* Basic vm calls allowed to every process. */
|
||||||
#define VM_BASIC_CALLS \
|
#define VM_BASIC_CALLS \
|
||||||
VM_MMAP, VM_MUNMAP, VM_MUNMAP_TEXT, VM_MAP_PHYS, VM_UNMAP_PHYS, \
|
VM_MMAP, VM_MUNMAP, VM_MAP_PHYS, VM_UNMAP_PHYS, \
|
||||||
VM_FORGETBLOCKS, VM_FORGETBLOCK, VM_YIELDBLOCKGETBLOCK, VM_INFO
|
VM_FORGETBLOCKS, VM_FORGETBLOCK, VM_YIELDBLOCKGETBLOCK, VM_INFO
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
|
|
|
@ -76,7 +76,6 @@ int munmap(void *, size_t);
|
||||||
void * minix_mmap(void *, size_t, int, int, int, off_t);
|
void * minix_mmap(void *, size_t, int, int, int, off_t);
|
||||||
void * minix_mmap_for(endpoint_t, void *, size_t, int, int, int, off_t);
|
void * minix_mmap_for(endpoint_t, void *, size_t, int, int, int, off_t);
|
||||||
int minix_munmap(void *, size_t);
|
int minix_munmap(void *, size_t);
|
||||||
int minix_munmap_text(void *, size_t);
|
|
||||||
void * vm_remap(int d, int s, void *da, void *sa, size_t si);
|
void * vm_remap(int d, int s, void *da, void *sa, size_t si);
|
||||||
void * vm_remap_ro(int d, int s, void *da, void *sa, size_t si);
|
void * vm_remap_ro(int d, int s, void *da, void *sa, size_t si);
|
||||||
int vm_unmap(int endpt, void *addr);
|
int vm_unmap(int endpt, void *addr);
|
||||||
|
|
|
@ -923,7 +923,6 @@
|
||||||
#define writev _writev
|
#define writev _writev
|
||||||
#define minix_mmap _minix_mmap
|
#define minix_mmap _minix_mmap
|
||||||
#define minix_munmap _minix_munmap
|
#define minix_munmap _minix_munmap
|
||||||
#define minix_munmap_text _minix_munmap_text
|
|
||||||
#define vfork __vfork14
|
#define vfork __vfork14
|
||||||
#endif /* __minix */
|
#endif /* __minix */
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,6 @@ __weak_alias(vm_getphys, _vm_getphys)
|
||||||
__weak_alias(vm_getrefcount, _vm_getrefcount)
|
__weak_alias(vm_getrefcount, _vm_getrefcount)
|
||||||
__weak_alias(minix_mmap, _minix_mmap)
|
__weak_alias(minix_mmap, _minix_mmap)
|
||||||
__weak_alias(minix_munmap, _minix_munmap)
|
__weak_alias(minix_munmap, _minix_munmap)
|
||||||
__weak_alias(minix_munmap_text, _minix_munmap_text)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -65,16 +64,6 @@ int minix_munmap(void *addr, size_t len)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int minix_munmap_text(void *addr, size_t len)
|
|
||||||
{
|
|
||||||
message m;
|
|
||||||
|
|
||||||
m.VMUM_ADDR = addr;
|
|
||||||
m.VMUM_LEN = len;
|
|
||||||
|
|
||||||
return _syscall(VM_PROC_NR, VM_MUNMAP_TEXT, &m);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *vm_remap(endpoint_t d,
|
void *vm_remap(endpoint_t d,
|
||||||
endpoint_t s,
|
endpoint_t s,
|
||||||
void *da,
|
void *da,
|
||||||
|
|
|
@ -7,10 +7,8 @@
|
||||||
#include "inc.h"
|
#include "inc.h"
|
||||||
|
|
||||||
#define minix_munmap _minix_munmap
|
#define minix_munmap _minix_munmap
|
||||||
#define minix_munmap_text _minix_munmap_text
|
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#undef minix_munmap
|
#undef minix_munmap
|
||||||
#undef minix_munmap_text
|
|
||||||
|
|
||||||
int unmap_ok = 0;
|
int unmap_ok = 0;
|
||||||
|
|
||||||
|
@ -24,14 +22,3 @@ int minix_munmap(void *addrstart, vir_bytes len)
|
||||||
|
|
||||||
return _minix_munmap(addrstart, len);
|
return _minix_munmap(addrstart, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* minix_munmap_text *
|
|
||||||
*===========================================================================*/
|
|
||||||
int minix_munmap_text(void *addrstart, vir_bytes len)
|
|
||||||
{
|
|
||||||
if(!unmap_ok)
|
|
||||||
return ENOSYS;
|
|
||||||
|
|
||||||
return _minix_munmap_text(addrstart, len);
|
|
||||||
}
|
|
||||||
|
|
|
@ -381,7 +381,6 @@ void init_vm(void)
|
||||||
/* Basic VM calls. */
|
/* Basic VM calls. */
|
||||||
CALLMAP(VM_MMAP, do_mmap);
|
CALLMAP(VM_MMAP, do_mmap);
|
||||||
CALLMAP(VM_MUNMAP, do_munmap);
|
CALLMAP(VM_MUNMAP, do_munmap);
|
||||||
CALLMAP(VM_MUNMAP_TEXT, do_munmap);
|
|
||||||
CALLMAP(VM_MAP_PHYS, do_map_phys);
|
CALLMAP(VM_MAP_PHYS, do_map_phys);
|
||||||
CALLMAP(VM_UNMAP_PHYS, do_unmap_phys);
|
CALLMAP(VM_UNMAP_PHYS, do_unmap_phys);
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include <minix/debug.h>
|
#include <minix/debug.h>
|
||||||
|
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
@ -234,7 +235,7 @@ int do_unmap_phys(message *m)
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(map_unmap_region(vmp, region, region->length) != OK) {
|
if(map_unmap_region(vmp, region, 0, region->length) != OK) {
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -345,7 +346,7 @@ int do_shared_unmap(message *m)
|
||||||
return EFAULT;
|
return EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(map_unmap_region(vmp, vr, vr->length) != OK)
|
if(map_unmap_region(vmp, vr, 0, vr->length) != OK)
|
||||||
panic("do_shared_unmap: map_unmap_region failed");
|
panic("do_shared_unmap: map_unmap_region failed");
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
|
@ -408,38 +409,38 @@ int do_munmap(message *m)
|
||||||
{
|
{
|
||||||
int r, n;
|
int r, n;
|
||||||
struct vmproc *vmp;
|
struct vmproc *vmp;
|
||||||
vir_bytes addr, len;
|
vir_bytes addr, len, offset;
|
||||||
struct vir_region *vr;
|
struct vir_region *vr;
|
||||||
|
|
||||||
if((r=vm_isokendpt(m->m_source, &n)) != OK) {
|
if((r=vm_isokendpt(m->m_source, &n)) != OK) {
|
||||||
panic("do_mmap: message from strange source: %d", m->m_source);
|
panic("do_mmap: message from strange source: %d", m->m_source);
|
||||||
}
|
}
|
||||||
|
|
||||||
vmp = &vmproc[n];
|
vmp = &vmproc[n];
|
||||||
|
|
||||||
if(m->m_type == VM_MUNMAP) {
|
assert(m->m_type == VM_MUNMAP);
|
||||||
addr = (vir_bytes) (vir_bytes) m->VMUM_ADDR;
|
addr = (vir_bytes) (vir_bytes) m->VMUM_ADDR;
|
||||||
} else if(m->m_type == VM_MUNMAP_TEXT) {
|
|
||||||
addr = (vir_bytes) (vir_bytes) m->VMUM_ADDR;
|
|
||||||
} else {
|
|
||||||
panic("do_munmap: strange type");
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!(vr = map_lookup(vmp, addr))) {
|
if(!(vr = map_lookup(vmp, addr))) {
|
||||||
printf("VM: unmap: virtual address %p not found in %d\n",
|
printf("VM: unmap: virtual address %p not found in %d\n",
|
||||||
m->VMUM_ADDR, vmp->vm_endpoint);
|
m->VMUM_ADDR, vmp->vm_endpoint);
|
||||||
return EFAULT;
|
return EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(addr % VM_PAGE_SIZE)
|
||||||
|
return EFAULT;
|
||||||
|
|
||||||
len = m->VMUM_LEN;
|
len = roundup(m->VMUM_LEN, VM_PAGE_SIZE);
|
||||||
if (len % VM_PAGE_SIZE)
|
|
||||||
len += VM_PAGE_SIZE - (len % VM_PAGE_SIZE);
|
|
||||||
|
|
||||||
if(addr != vr->vaddr || len > vr->length || len < VM_PAGE_SIZE) {
|
offset = addr - vr->vaddr;
|
||||||
return EFAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(map_unmap_region(vmp, vr, len) != OK)
|
if(offset + len > vr->length) {
|
||||||
|
printf("munmap: addr 0x%lx len 0x%lx spills out of region\n",
|
||||||
|
addr, len);
|
||||||
|
return EFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(map_unmap_region(vmp, vr, offset, len) != OK)
|
||||||
panic("do_munmap: map_unmap_region failed");
|
panic("do_munmap: map_unmap_region failed");
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
|
@ -483,15 +484,3 @@ int minix_munmap(void *addr, size_t len)
|
||||||
return munmap_lin(laddr, len);
|
return munmap_lin(laddr, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* munmap_text (override for VM) *
|
|
||||||
*===========================================================================*/
|
|
||||||
int minix_munmap_text(void *addr, size_t len)
|
|
||||||
{
|
|
||||||
vir_bytes laddr;
|
|
||||||
if(!unmap_ok)
|
|
||||||
return ENOSYS;
|
|
||||||
laddr = (vir_bytes) addr;
|
|
||||||
return munmap_lin(laddr, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,7 @@ USE(newphysr,
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* pb_unreferenced *
|
* pb_unreferenced *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
void pb_unreferenced(struct vir_region *region, struct phys_region *pr)
|
void pb_unreferenced(struct vir_region *region, struct phys_region *pr, int rm)
|
||||||
{
|
{
|
||||||
struct phys_block *pb;
|
struct phys_block *pb;
|
||||||
|
|
||||||
|
@ -116,5 +116,5 @@ void pb_unreferenced(struct vir_region *region, struct phys_region *pr)
|
||||||
SLABFREE(pb);
|
SLABFREE(pb);
|
||||||
}
|
}
|
||||||
|
|
||||||
physr_remove(region->phys, pr->offset);
|
if(rm) physr_remove(region->phys, pr->offset);
|
||||||
}
|
}
|
||||||
|
|
|
@ -132,7 +132,7 @@ int map_region_extend(struct vmproc *vmp, struct vir_region *vr,
|
||||||
int map_region_extend_upto_v(struct vmproc *vmp, vir_bytes vir);
|
int map_region_extend_upto_v(struct vmproc *vmp, vir_bytes vir);
|
||||||
int map_region_shrink(struct vir_region *vr, vir_bytes delta);
|
int map_region_shrink(struct vir_region *vr, vir_bytes delta);
|
||||||
int map_unmap_region(struct vmproc *vmp, struct vir_region *vr,
|
int map_unmap_region(struct vmproc *vmp, struct vir_region *vr,
|
||||||
vir_bytes len);
|
vir_bytes offset, vir_bytes len);
|
||||||
int map_free_proc(struct vmproc *vmp);
|
int map_free_proc(struct vmproc *vmp);
|
||||||
int map_proc_copy(struct vmproc *dst, struct vmproc *src);
|
int map_proc_copy(struct vmproc *dst, struct vmproc *src);
|
||||||
int map_proc_copy_from(struct vmproc *dst, struct vmproc *src, struct
|
int map_proc_copy_from(struct vmproc *dst, struct vmproc *src, struct
|
||||||
|
@ -158,7 +158,6 @@ int map_remap(struct vmproc *dvmp, vir_bytes da, size_t size, struct
|
||||||
int map_get_phys(struct vmproc *vmp, vir_bytes addr, phys_bytes *r);
|
int map_get_phys(struct vmproc *vmp, vir_bytes addr, phys_bytes *r);
|
||||||
int map_get_ref(struct vmproc *vmp, vir_bytes addr, u8_t *cnt);
|
int map_get_ref(struct vmproc *vmp, vir_bytes addr, u8_t *cnt);
|
||||||
|
|
||||||
void pb_unreferenced(struct vir_region *region, struct phys_region *pr);
|
|
||||||
void get_stats_info(struct vm_stats_info *vsi);
|
void get_stats_info(struct vm_stats_info *vsi);
|
||||||
void get_usage_info(struct vmproc *vmp, struct vm_usage_info *vui);
|
void get_usage_info(struct vmproc *vmp, struct vm_usage_info *vui);
|
||||||
int get_region_info(struct vmproc *vmp, struct vm_region_info *vri, int
|
int get_region_info(struct vmproc *vmp, struct vm_region_info *vri, int
|
||||||
|
@ -189,4 +188,4 @@ void init_query_exit(void);
|
||||||
struct phys_block *pb_new(phys_bytes phys);
|
struct phys_block *pb_new(phys_bytes phys);
|
||||||
struct phys_region *pb_reference(struct phys_block *newpb,
|
struct phys_region *pb_reference(struct phys_block *newpb,
|
||||||
vir_bytes offset, struct vir_region *region);
|
vir_bytes offset, struct vir_region *region);
|
||||||
void pb_unreferenced(struct vir_region *region, struct phys_region *pr);
|
void pb_unreferenced(struct vir_region *region, struct phys_region *pr, int rm);
|
||||||
|
|
|
@ -429,8 +429,11 @@ static vir_bytes region_find_slot_range(struct vmproc *vmp,
|
||||||
printf("VM: 1 minv: 0x%lx maxv: 0x%lx length: 0x%lx\n",
|
printf("VM: 1 minv: 0x%lx maxv: 0x%lx length: 0x%lx\n",
|
||||||
minv, maxv, length);
|
minv, maxv, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(minv < maxv);
|
assert(minv < maxv);
|
||||||
assert(minv + length <= maxv);
|
|
||||||
|
if(minv + length > maxv)
|
||||||
|
return SLOT_FAIL;
|
||||||
|
|
||||||
#define FREEVRANGE_TRY(rangestart, rangeend) { \
|
#define FREEVRANGE_TRY(rangestart, rangeend) { \
|
||||||
vir_bytes frstart = (rangestart), frend = (rangeend); \
|
vir_bytes frstart = (rangestart), frend = (rangeend); \
|
||||||
|
@ -642,11 +645,14 @@ static struct phys_region *reset_physr_iter(struct vir_region *region,
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* map_subfree *
|
* map_subfree *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
static int map_subfree(struct vir_region *region, vir_bytes len)
|
static int map_subfree(struct vir_region *region,
|
||||||
|
vir_bytes start, vir_bytes len)
|
||||||
{
|
{
|
||||||
struct phys_region *pr;
|
struct phys_region *pr;
|
||||||
physr_iter iter;
|
physr_iter iter;
|
||||||
|
vir_bytes end = start+len;
|
||||||
|
|
||||||
|
int full = 0;
|
||||||
|
|
||||||
#if SANITYCHECKS
|
#if SANITYCHECKS
|
||||||
{
|
{
|
||||||
|
@ -668,18 +674,25 @@ static int map_subfree(struct vir_region *region, vir_bytes len)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
physr_start_iter_least(region->phys, &iter);
|
if(start == 0 && len == region->length)
|
||||||
|
full = 1;
|
||||||
|
|
||||||
|
physr_start_iter(region->phys, &iter, start, AVL_GREATER_EQUAL);
|
||||||
while((pr = physr_get_iter(&iter))) {
|
while((pr = physr_get_iter(&iter))) {
|
||||||
physr_incr_iter(&iter);
|
physr_incr_iter(&iter);
|
||||||
if(pr->offset >= len)
|
if(pr->offset >= end)
|
||||||
break;
|
break;
|
||||||
if(pr->offset + VM_PAGE_SIZE <= len) {
|
pb_unreferenced(region, pr, !full);
|
||||||
pb_unreferenced(region, pr);
|
if(!full) {
|
||||||
physr_start_iter_least(region->phys, &iter);
|
physr_start_iter(region->phys, &iter,
|
||||||
SLABFREE(pr);
|
pr->offset, AVL_GREATER_EQUAL);
|
||||||
}
|
}
|
||||||
|
SLABFREE(pr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(full)
|
||||||
|
physr_init(region->phys);
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -690,7 +703,7 @@ static int map_free(struct vir_region *region)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if((r=map_subfree(region, region->length)) != OK) {
|
if((r=map_subfree(region, 0, region->length)) != OK) {
|
||||||
printf("%d\n", __LINE__);
|
printf("%d\n", __LINE__);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -985,7 +998,7 @@ int written;
|
||||||
if((physr = physr_search(region->phys, offset,
|
if((physr = physr_search(region->phys, offset,
|
||||||
AVL_EQUAL))) {
|
AVL_EQUAL))) {
|
||||||
assert(physr->ph->refcount == 1);
|
assert(physr->ph->refcount == 1);
|
||||||
pb_unreferenced(region, physr);
|
pb_unreferenced(region, physr, 1);
|
||||||
SLABFREE(physr);
|
SLABFREE(physr);
|
||||||
}
|
}
|
||||||
offset += VM_PAGE_SIZE;
|
offset += VM_PAGE_SIZE;
|
||||||
|
@ -1052,7 +1065,7 @@ physr_iter *iter;
|
||||||
SLABSANE(ph);
|
SLABSANE(ph);
|
||||||
SLABSANE(ph->ph);
|
SLABSANE(ph->ph);
|
||||||
assert(ph->ph->refcount > 1);
|
assert(ph->ph->refcount > 1);
|
||||||
pb_unreferenced(region, ph);
|
pb_unreferenced(region, ph, 1);
|
||||||
assert(ph->ph->refcount >= 1);
|
assert(ph->ph->refcount >= 1);
|
||||||
SLABFREE(ph);
|
SLABFREE(ph);
|
||||||
|
|
||||||
|
@ -1653,7 +1666,7 @@ u32_t map_region_get_tag(struct vir_region *vr)
|
||||||
* map_unmap_region *
|
* map_unmap_region *
|
||||||
*========================================================================*/
|
*========================================================================*/
|
||||||
int map_unmap_region(struct vmproc *vmp, struct vir_region *r,
|
int map_unmap_region(struct vmproc *vmp, struct vir_region *r,
|
||||||
vir_bytes len)
|
vir_bytes offset, vir_bytes len)
|
||||||
{
|
{
|
||||||
/* Shrink the region by 'len' bytes, from the start. Unreference
|
/* Shrink the region by 'len' bytes, from the start. Unreference
|
||||||
* memory it used to reference if any.
|
* memory it used to reference if any.
|
||||||
|
@ -1662,7 +1675,7 @@ int map_unmap_region(struct vmproc *vmp, struct vir_region *r,
|
||||||
|
|
||||||
SANITYCHECK(SCL_FUNCTIONS);
|
SANITYCHECK(SCL_FUNCTIONS);
|
||||||
|
|
||||||
if(len > r->length || (len % VM_PAGE_SIZE)) {
|
if(offset+len > r->length || (len % VM_PAGE_SIZE)) {
|
||||||
printf("VM: bogus length 0x%lx\n", len);
|
printf("VM: bogus length 0x%lx\n", len);
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -1672,35 +1685,44 @@ int map_unmap_region(struct vmproc *vmp, struct vir_region *r,
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
regionstart = r->vaddr;
|
regionstart = r->vaddr + offset;
|
||||||
|
|
||||||
if(len == r->length) {
|
/* unreference its memory */
|
||||||
SANITYCHECK(SCL_DETAIL);
|
map_subfree(r, offset, len);
|
||||||
/* Whole region disappears. Unlink and free it. */
|
|
||||||
region_remove(&vmp->vm_regions_avl, r->vaddr);
|
/* if unmap was at start/end of this region, it actually shrinks */
|
||||||
map_free(r);
|
if(offset == 0) {
|
||||||
} else {
|
|
||||||
struct phys_region *pr;
|
struct phys_region *pr;
|
||||||
physr_iter iter;
|
physr_iter iter;
|
||||||
/* Region shrinks. First unreference its memory
|
|
||||||
* and then shrink the region.
|
region_remove(&vmp->vm_regions_avl, r->vaddr);
|
||||||
*/
|
|
||||||
SANITYCHECK(SCL_DETAIL);
|
|
||||||
map_subfree(r, len);
|
|
||||||
USE(r,
|
USE(r,
|
||||||
r->vaddr += len;
|
r->vaddr += len;
|
||||||
r->length -= len;);
|
r->length -= len;);
|
||||||
physr_start_iter_least(r->phys, &iter);
|
|
||||||
|
region_insert(&vmp->vm_regions_avl, r);
|
||||||
|
|
||||||
/* vaddr has increased; to make all the phys_regions
|
/* vaddr has increased; to make all the phys_regions
|
||||||
* point to the same addresses, make them shrink by the
|
* point to the same addresses, make them shrink by the
|
||||||
* same amount.
|
* same amount.
|
||||||
*/
|
*/
|
||||||
|
physr_start_iter(r->phys, &iter, offset, AVL_GREATER_EQUAL);
|
||||||
|
|
||||||
while((pr = physr_get_iter(&iter))) {
|
while((pr = physr_get_iter(&iter))) {
|
||||||
assert(pr->offset >= len);
|
assert(pr->offset >= offset);
|
||||||
USE(pr, pr->offset -= len;);
|
USE(pr, pr->offset -= len;);
|
||||||
physr_incr_iter(&iter);
|
physr_incr_iter(&iter);
|
||||||
}
|
}
|
||||||
|
} else if(offset + len == r->length) {
|
||||||
|
assert(len <= r->length);
|
||||||
|
r->length -= len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(r->length == 0) {
|
||||||
|
/* Whole region disappears. Unlink and free it. */
|
||||||
|
region_remove(&vmp->vm_regions_avl, r->vaddr);
|
||||||
|
map_free(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
SANITYCHECK(SCL_DETAIL);
|
SANITYCHECK(SCL_DETAIL);
|
||||||
|
@ -2104,7 +2126,7 @@ 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, 1);
|
||||||
physr_start_iter(region->phys, &iter, begin,
|
physr_start_iter(region->phys, &iter, begin,
|
||||||
AVL_GREATER_EQUAL);
|
AVL_GREATER_EQUAL);
|
||||||
SLABFREE(pr);
|
SLABFREE(pr);
|
||||||
|
|
|
@ -205,12 +205,11 @@ static int checklist(char *file, int line,
|
||||||
MYASSERT(n->sdh.magic1 == MAGIC1);
|
MYASSERT(n->sdh.magic1 == MAGIC1);
|
||||||
MYASSERT(n->sdh.magic2 == MAGIC2);
|
MYASSERT(n->sdh.magic2 == MAGIC2);
|
||||||
#endif
|
#endif
|
||||||
MYASSERT(n->sdh.list == l);
|
|
||||||
MYASSERT(usedpages_add(n->sdh.phys, VM_PAGE_SIZE) == OK);
|
MYASSERT(usedpages_add(n->sdh.phys, VM_PAGE_SIZE) == OK);
|
||||||
if(n->sdh.prev)
|
if(n->sdh.prev)
|
||||||
MYASSERT(n->sdh.prev->sdh.next == n);
|
MYASSERT(n->sdh.prev->sdh.next == n);
|
||||||
else
|
else
|
||||||
MYASSERT(s->list_head[l] == n);
|
MYASSERT(s->list_head == n);
|
||||||
if(n->sdh.next) MYASSERT(n->sdh.next->sdh.prev == n);
|
if(n->sdh.next) MYASSERT(n->sdh.next->sdh.prev == n);
|
||||||
for(i = 0; i < USEELEMENTS*8; i++)
|
for(i = 0; i < USEELEMENTS*8; i++)
|
||||||
if(i >= ITEMSPERPAGE(bytes))
|
if(i >= ITEMSPERPAGE(bytes))
|
||||||
|
@ -233,7 +232,6 @@ void slab_sanitycheck(char *file, int line)
|
||||||
{
|
{
|
||||||
int s;
|
int s;
|
||||||
for(s = 0; s < SLABSIZES; s++) {
|
for(s = 0; s < SLABSIZES; s++) {
|
||||||
int l;
|
|
||||||
checklist(file, line, &slabs[s], s + MINSIZE);
|
checklist(file, line, &slabs[s], s + MINSIZE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -247,6 +245,8 @@ int slabsane_f(char *file, int line, void *mem, int bytes)
|
||||||
struct slabdata *f;
|
struct slabdata *f;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
bytes = roundup(bytes, OBJALIGN);
|
||||||
|
|
||||||
return (objstats(mem, bytes, &s, &f, &i) == OK);
|
return (objstats(mem, bytes, &s, &f, &i) == OK);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -508,7 +508,6 @@ void slabstats(void)
|
||||||
n++;
|
n++;
|
||||||
if(n%1000) return;
|
if(n%1000) return;
|
||||||
for(s = 0; s < SLABSIZES; s++) {
|
for(s = 0; s < SLABSIZES; s++) {
|
||||||
int l;
|
|
||||||
int b, t;
|
int b, t;
|
||||||
b = s + MINSIZE;
|
b = s + MINSIZE;
|
||||||
t = checklist(__FILE__, __LINE__, &slabs[s], b);
|
t = checklist(__FILE__, __LINE__, &slabs[s], b);
|
||||||
|
|
Loading…
Reference in a new issue