提交 a1477b27 创建 作者: Robert Morris's avatar Robert Morris

vma_overlap()

上级 eda2be67
...@@ -173,6 +173,7 @@ void vmn_free(struct vmnode *); ...@@ -173,6 +173,7 @@ void vmn_free(struct vmnode *);
int vmn_load(struct vmnode *, struct inode*, uint, uint); int vmn_load(struct vmnode *, struct inode*, uint, uint);
struct vmap * vmap_alloc(void); struct vmap * vmap_alloc(void);
void vmap_decref(struct vmap *); void vmap_decref(struct vmap *);
int vmap_overlap(struct vmap *m, uint start, uint end);
int vmap_insert(struct vmap *, struct vmnode *n, uint); int vmap_insert(struct vmap *, struct vmnode *n, uint);
int vmap_remove(struct vmap *, uint va_start, uint len); int vmap_remove(struct vmap *, uint va_start, uint len);
struct vma * vmap_lookup(struct vmap *, uint); struct vma * vmap_lookup(struct vmap *, uint);
......
...@@ -30,10 +30,9 @@ struct context { ...@@ -30,10 +30,9 @@ struct context {
}; };
enum procstate { UNUSED, EMBRYO, SLEEPING, RUNNABLE, RUNNING, ZOMBIE }; enum procstate { UNUSED, EMBRYO, SLEEPING, RUNNABLE, RUNNING, ZOMBIE };
enum vmatype { PRIVATE, COW};
enum vmntype { EAGER, ONDEMAND};
// Virtual memory // A memory object (physical pages or inode).
enum vmntype { EAGER, ONDEMAND};
struct vmnode { struct vmnode {
uint npages; uint npages;
char *page[32]; char *page[32];
...@@ -45,6 +44,9 @@ struct vmnode { ...@@ -45,6 +44,9 @@ struct vmnode {
uint sz; uint sz;
}; };
// A mapping of a chunk of an address space to
// a specific memory object.
enum vmatype { PRIVATE, COW};
struct vma { struct vma {
uint va_start; // start of mapping uint va_start; // start of mapping
uint va_end; // one past the last byte uint va_end; // one past the last byte
...@@ -53,6 +55,8 @@ struct vma { ...@@ -53,6 +55,8 @@ struct vma {
struct spinlock lock; // serialize fault/unmap struct spinlock lock; // serialize fault/unmap
}; };
// An address space: a set of vmas plus h/w page table.
// The elements of e[] are not ordered by address.
struct vmap { struct vmap {
struct vma e[16]; struct vma e[16];
struct spinlock lock; // serialize map/lookup/unmap struct spinlock lock; // serialize map/lookup/unmap
......
...@@ -384,25 +384,48 @@ vmap_decref(struct vmap *m) ...@@ -384,25 +384,48 @@ vmap_decref(struct vmap *m)
vmap_free(m); vmap_free(m);
} }
// Does any vma overlap start..start+len?
// If yes, return the m->e[] index.
// If no, return -1.
// This code can't handle regions at the very end
// of the address space, e.g. 0xffffffff..0x0
int
vmap_overlap(struct vmap *m, uint start, uint len)
{
if(holding(&m->lock) == 0)
panic("vmap_overlap no lock");
if(start + len < start)
panic("vmap_overlap bad len");
for(uint i = 0; i < sizeof(m->e) / sizeof(m->e[0]); i++){
if(m->e[i].n){
if(m->e[i].va_end <= m->e[i].va_start)
panic("vmap_overlap bad vma");
if(m->e[i].va_start < start+len && m->e[i].va_end > start)
return i;
}
}
return -1;
}
int int
vmap_insert(struct vmap *m, struct vmnode *n, uint va_start) vmap_insert(struct vmap *m, struct vmnode *n, uint va_start)
{ {
acquire(&m->lock); acquire(&m->lock);
uint va_end = va_start + n->npages * PGSIZE; uint len = n->npages * PGSIZE;
for(uint i = 0; i < sizeof(m->e) / sizeof(m->e[0]); i++) {
if(m->e[i].n && (m->e[i].va_start < va_end && m->e[i].va_end > va_start)) { if(vmap_overlap(m, va_start, len) != -1){
release(&m->lock); release(&m->lock);
cprintf("vmap_insert: overlap\n"); cprintf("vmap_insert: overlap\n");
return -1; return -1;
} }
}
for(uint i = 0; i < sizeof(m->e) / sizeof(m->e[0]); i++) { for(uint i = 0; i < sizeof(m->e) / sizeof(m->e[0]); i++) {
if(m->e[i].n) if(m->e[i].n)
continue; continue;
__sync_fetch_and_add(&n->ref, 1); __sync_fetch_and_add(&n->ref, 1);
m->e[i].va_start = va_start; m->e[i].va_start = va_start;
m->e[i].va_end = va_end; m->e[i].va_end = va_start + len;
m->e[i].n = n; m->e[i].n = n;
release(&m->lock); release(&m->lock);
return 0; return 0;
...@@ -438,14 +461,13 @@ struct vma * ...@@ -438,14 +461,13 @@ struct vma *
vmap_lookup(struct vmap *m, uint va) vmap_lookup(struct vmap *m, uint va)
{ {
acquire(&m->lock); acquire(&m->lock);
for(uint i = 0; i < sizeof(m->e) / sizeof(m->e[0]); i++) { int ind = vmap_overlap(m, va, 1);
struct vma *e = &m->e[i]; if(ind >= 0){
if (e->n && va >= e->va_start && va < e->va_end) { struct vma *e = &m->e[ind];
acquire(&e->lock); acquire(&e->lock);
release(&m->lock); release(&m->lock);
return e; return e;
} }
}
release(&m->lock); release(&m->lock);
return 0; return 0;
} }
......
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论