changed vma_list order

This commit is contained in:
Steffen Vogel 2014-01-09 13:45:20 +01:00
parent ab67350783
commit 6699886358
3 changed files with 73 additions and 78 deletions

View file

@ -29,9 +29,9 @@ extern "C" {
/// Binary exponent of maximal size for kmalloc() /// Binary exponent of maximal size for kmalloc()
#define BUDDY_MAX 32 // 4 GB #define BUDDY_MAX 32 // 4 GB
/// Binary exponent of minimal buddy size /// Binary exponent of minimal buddy size
#define BUDDY_MIN 4 // 16 Byte >= sizeof(buddy_prefix_t) #define BUDDY_MIN 3 // 8 Byte >= sizeof(buddy_t)
/// Binary exponent of the size which we allocate at least in one call to buddy_fill(); /// Binary exponent of the size which we allocate with buddy_fill()
#define BUDDY_ALLOC 17 // 128 KByte >= PAGE_SHIFT, TODO: add Huge Page support? #define BUDDY_ALLOC 15 // 32 KByte >= PAGE_SIZE
#define BUDDY_LISTS (BUDDY_MAX-BUDDY_MIN+1) #define BUDDY_LISTS (BUDDY_MAX-BUDDY_MIN+1)
#define BUDDY_MAGIC 0xBABE #define BUDDY_MAGIC 0xBABE

View file

@ -49,10 +49,9 @@ extern "C" {
#define VMA_HEAP (VMA_READ|VMA_WRITE|VMA_CACHEABLE) #define VMA_HEAP (VMA_READ|VMA_WRITE|VMA_CACHEABLE)
// boundaries for VAS allocation // boundaries for VAS allocation
extern const void kernel_end; #define VMA_KERN_MIN PAGE_SIZE // we skip the first page
//#define VMA_KERN_MIN (((size_t) &kernel_end + PAGE_SIZE) & PAGE_MASK)
#define VMA_KERN_MAX KERNEL_SPACE #define VMA_KERN_MAX KERNEL_SPACE
#define VMA_USER_MAX (1UL << 47) // TODO #define VMA_USER_MAX PAGE_MAP_PGT
struct vma; struct vma;

140
mm/vma.c
View file

@ -30,7 +30,7 @@
* For bootstrapping we initialize the VMA list with one empty VMA * For bootstrapping we initialize the VMA list with one empty VMA
* (start == end) and expand this VMA by calls to vma_alloc() * (start == end) and expand this VMA by calls to vma_alloc()
*/ */
static vma_t vma_boot = { VMA_KERN_MAX, VMA_KERN_MAX, VMA_HEAP }; static vma_t vma_boot = { VMA_KERN_MIN, VMA_KERN_MIN, VMA_HEAP };
static vma_t* vma_list = &vma_boot; static vma_t* vma_list = &vma_boot;
static spinlock_t vma_lock = SPINLOCK_INIT; static spinlock_t vma_lock = SPINLOCK_INIT;
@ -39,7 +39,6 @@ size_t vma_alloc(size_t size, uint32_t flags)
task_t* task = per_core(current_task); task_t* task = per_core(current_task);
spinlock_t* lock; spinlock_t* lock;
vma_t** list; vma_t** list;
size_t ret = 0;
kprintf("vma_alloc(0x%lx, 0x%x)\n", size, flags); kprintf("vma_alloc(0x%lx, 0x%x)\n", size, flags);
@ -56,7 +55,7 @@ size_t vma_alloc(size_t size, uint32_t flags)
lock = &task->vma_lock; lock = &task->vma_lock;
} }
else { else {
base = 0; base = VMA_KERN_MIN;
limit = VMA_KERN_MAX; limit = VMA_KERN_MAX;
list = &vma_list; list = &vma_list;
lock = &vma_lock; lock = &vma_lock;
@ -64,9 +63,9 @@ size_t vma_alloc(size_t size, uint32_t flags)
spinlock_lock(lock); spinlock_lock(lock);
// "last" fit search for free memory area // first fit search for free memory area
vma_t* pred = *list; // vma before current gap vma_t* pred = NULL; // vma before current gap
vma_t* succ = NULL; // vma after current gap vma_t* succ = *list; // vma after current gap
do { do {
start = (pred) ? pred->end : base; start = (pred) ? pred->end : base;
end = (succ) ? succ->start : limit; end = (succ) ? succ->start : limit;
@ -74,8 +73,8 @@ size_t vma_alloc(size_t size, uint32_t flags)
if (end > start && end - start > size) if (end > start && end - start > size)
break; // we found a gap break; // we found a gap
succ = pred; pred = succ;
pred = (pred) ? pred->prev : NULL; succ = (succ) ? succ->next : NULL;
} while (pred || succ); } while (pred || succ);
if (BUILTIN_EXPECT(end > limit || end < start || end - start < size, 0)) { if (BUILTIN_EXPECT(end > limit || end < start || end - start < size, 0)) {
@ -83,35 +82,35 @@ size_t vma_alloc(size_t size, uint32_t flags)
return 0; return 0;
} }
// resize existing vma
if (succ && succ->flags == flags) {
succ->start -= size;
ret = succ->start;
}
// insert new vma
else {
vma_t* new = kmalloc(sizeof(vma_t));
if (BUILTIN_EXPECT(!new, 0))
return 0;
new->start = end-size; if (pred && pred->flags == flags) {
new->end = end; pred->end = start+size;
}
else {
// insert new VMA
vma_t* new = kmalloc(sizeof(vma_t));
if (BUILTIN_EXPECT(!new, 0)) {
spinlock_unlock(lock);
return 0;
}
new->start = start;
new->end = start+size;
new->flags = flags; new->flags = flags;
new->next = succ; new->next = succ;
new->prev = pred; new->prev = pred;
if (pred)
pred->next = new;
if (succ) if (succ)
succ->prev = new; succ->prev = new;
if (pred)
pred->next = new;
else else
*list = new; *list = new;
ret = new->start;
} }
spinlock_unlock(lock); spinlock_unlock(lock);
return ret;
return start;
} }
int vma_free(size_t start, size_t end) int vma_free(size_t start, size_t end)
@ -124,7 +123,7 @@ int vma_free(size_t start, size_t end)
if (BUILTIN_EXPECT(start >= end, 0)) if (BUILTIN_EXPECT(start >= end, 0))
return -EINVAL; return -EINVAL;
if (end <= VMA_KERN_MAX) { if (end < VMA_KERN_MAX) {
lock = &vma_lock; lock = &vma_lock;
list = &vma_list; list = &vma_list;
} }
@ -132,8 +131,6 @@ int vma_free(size_t start, size_t end)
lock = &task->vma_lock; lock = &task->vma_lock;
list = &task->vma_list; list = &task->vma_list;
} }
else
return -EINVAL;
if (BUILTIN_EXPECT(!*list, 0)) if (BUILTIN_EXPECT(!*list, 0))
return -EINVAL; return -EINVAL;
@ -144,7 +141,7 @@ int vma_free(size_t start, size_t end)
vma = *list; vma = *list;
while (vma) { while (vma) {
if (start >= vma->start && end <= vma->end) break; if (start >= vma->start && end <= vma->end) break;
vma = vma->prev; vma = vma->next;
} }
if (BUILTIN_EXPECT(!vma, 0)) { if (BUILTIN_EXPECT(!vma, 0)) {
@ -173,13 +170,13 @@ int vma_free(size_t start, size_t end)
return -ENOMEM; return -ENOMEM;
} }
new->start = end;
vma->end = start;
new->end = vma->end; new->end = vma->end;
vma->end = start;
new->start = end;
new->next = vma->next; new->next = vma->next;
new->prev = vma;
vma->next = new; vma->next = new;
new->prev = vma;
} }
spinlock_unlock(lock); spinlock_unlock(lock);
@ -211,48 +208,45 @@ int vma_add(size_t start, size_t end, uint32_t flags)
lock = &vma_lock; lock = &vma_lock;
// check if address is in kernelspace // check if address is in kernelspace
if (BUILTIN_EXPECT(end > VMA_KERN_MAX, 0)) if (BUILTIN_EXPECT(end >= VMA_KERN_MAX, 0))
return -EINVAL; return -EINVAL;
} }
spinlock_lock(lock); spinlock_lock(lock);
// search gap // search gap
vma_t* pred = *list; vma_t* pred = NULL;
vma_t* succ = NULL; vma_t* succ = *list;
while (pred) { do {
if ((!pred || pred->end <= start) && if ((!pred || pred->end <= start) &&
(!succ || succ->start >= end)) (!succ || succ->start >= end))
break; break;
succ = pred; pred = succ;
pred = pred->prev; succ = succ->next;
} while (pred || succ);
// TODO: check bounds
// insert new VMA
vma_t* new = kmalloc(sizeof(vma_t));
if (BUILTIN_EXPECT(!new, 0)) {
spinlock_unlock(lock);
return -ENOMEM;
} }
// resize existing vma new->start = start;
if (pred && pred->end == start && pred->flags == flags) new->end = end;
pred->end = end; new->flags = flags;
else if (succ && succ->start == end && succ->flags == flags) new->next = succ;
succ->start = start; new->prev = pred;
// insert new vma
else {
vma_t* new = kmalloc(sizeof(vma_t));
if (BUILTIN_EXPECT(!new, 0))
return 0;
new->start = start; if (succ)
new->end = end; succ->prev = new;
new->flags = flags; if (pred)
new->next = succ; pred->next = new;
new->prev = pred; else
*list = new;
if (pred)
pred->next = new;
if (succ)
succ->prev = new;
else
*list = new;
}
spinlock_unlock(lock); spinlock_unlock(lock);
@ -267,15 +261,15 @@ int copy_vma_list(task_t* task)
spinlock_lock(&parent_task->vma_lock); spinlock_lock(&parent_task->vma_lock);
spinlock_lock(&task->vma_lock); spinlock_lock(&task->vma_lock);
int ret = 0;
vma_t* last = NULL; vma_t* last = NULL;
vma_t* parent = parent_task->vma_list; vma_t* parent = parent_task->vma_list;
while (parent) { while (parent) {
vma_t *new = kmalloc(sizeof(vma_t)); vma_t *new = kmalloc(sizeof(vma_t));
if (BUILTIN_EXPECT(!new, 0)) { if (BUILTIN_EXPECT(!new, 0)) {
ret = -ENOMEM; spinlock_unlock(&task->vma_lock);
goto out; spinlock_unlock(&parent_task->vma_lock);
return -ENOMEM;
} }
new->start = parent->start; new->start = parent->start;
@ -292,20 +286,22 @@ int copy_vma_list(task_t* task)
parent = parent->next; parent = parent->next;
} }
out: return 0;
spinlock_unlock(&task->vma_lock);
spinlock_unlock(&parent_task->vma_lock);
return ret;
} }
int drop_vma_list() int drop_vma_list()
{ {
task_t* task = per_core(current_task); task_t* task = per_core(current_task);
vma_t* vma;
kprintf("drop_vma_list: task = %u\n", task->id); // TODO: remove
spinlock_lock(&task->vma_lock); spinlock_lock(&task->vma_lock);
while(task->vma_list) while (vma = task->vma_list) {
pfree((void*) task->vma_list->start, task->vma_list->end - task->vma_list->start); task->vma_list = vma->next;
kfree(vma);
}
spinlock_unlock(&task->vma_lock); spinlock_unlock(&task->vma_lock);
@ -320,7 +316,7 @@ void vma_dump()
(vma->flags & VMA_READ) ? 'r' : '-', (vma->flags & VMA_READ) ? 'r' : '-',
(vma->flags & VMA_WRITE) ? 'w' : '-', (vma->flags & VMA_WRITE) ? 'w' : '-',
(vma->flags & VMA_EXECUTE) ? 'x' : '-'); (vma->flags & VMA_EXECUTE) ? 'x' : '-');
vma = vma->prev; vma = vma->next;
} }
} }