aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/debug.c4
-rw-r--r--src/dmem.c4
-rw-r--r--src/regions.c45
-rw-r--r--src/vmem.c21
4 files changed, 49 insertions, 25 deletions
diff --git a/src/debug.c b/src/debug.c
index 950f73b..d87588d 100644
--- a/src/debug.c
+++ b/src/debug.c
@@ -455,7 +455,7 @@ static size_t __print_sign(ssize_t value, size_t flags)
* @return \see __integral_val().
*/
#define __integral_len(value, base, flags) __integral_val((value), (base), \
- (flags), false)
+ (flags), false)
/**
* Print integral value as string.
@@ -466,7 +466,7 @@ static size_t __print_sign(ssize_t value, size_t flags)
* @return \see __integral_val().
*/
#define __integral_print(value, base, flags) __integral_val((value), (base), \
- (flags), true)
+ (flags), true)
/**
* Print integral value.
diff --git a/src/dmem.c b/src/dmem.c
index 91ddb02..d21a9c5 100644
--- a/src/dmem.c
+++ b/src/dmem.c
@@ -24,8 +24,8 @@ stat_t init_devmem(pm_t ram_base, pm_t ram_top)
/* -1 being the effective highest address possible */
size_t post_pages = __pages(-1) - ram_pages - pre_pages;
- init_region(&pre_ram, 0, pre_pages);
- init_region(&post_ram, ram_top, post_pages);
+ init_region(&pre_ram, 0, pre_pages, 0);
+ init_region(&post_ram, ram_top, post_pages, 0);
return OK;
}
diff --git a/src/regions.c b/src/regions.c
index ca99971..1aa318d 100644
--- a/src/regions.c
+++ b/src/regions.c
@@ -113,6 +113,8 @@ static struct mem_region *__insert_free_region(struct mem_region_root *r,
}
else if (start < t->start) {
+ /* note that blocks with smaller addresses go to the
+ * left */
n = sp_left(n);
d = SP_LEFT;
}
@@ -165,7 +167,8 @@ static struct mem_region *__insert_used_region(struct mem_region_root *r,
return m;
}
-stat_t init_region(struct mem_region_root *r, vm_t start, size_t arena_size)
+stat_t init_region(struct mem_region_root *r, vm_t start, size_t arena_size,
+ size_t reserved)
{
/* convert bytes to pages */
start = __page(start);
@@ -173,8 +176,11 @@ stat_t init_region(struct mem_region_root *r, vm_t start, size_t arena_size)
struct mem_region *m = get_mem_node();
m->start = start;
m->end = start + arena_size;
- __insert_free_region(r, m);
+ r->reserved = __page(reserved);
+ r->start = m->start;
+ r->end = m->end;
+ __insert_free_region(r, m);
return OK;
}
@@ -311,16 +317,45 @@ struct mem_region *find_free_region(struct mem_region_root *r, size_t size,
size_t offset = __page(po_align(__addr(size)));
struct mem_region *quick_best = 0;
struct sp_node *n = sp_root(&r->free_regions);
- while (n) {
+
+ /* always go right, both to find a larger block and a higher
+ * address (generally avoid going towards the NULL page) */
+ for (; n; n = sp_right(n)) {
struct mem_region *t = mem_container(n);
vm_t start = align_up(t->start, offset);
-
size_t qsize = t->end - t->start;
size_t bsize = 0;
if (t->end >= start)
bsize = t->end - start;
+ /* handle reserved region first */
+ if (start < r->start + r->reserved) {
+ /* we would have to map reserved pages, go to next node
+ * if one exists */
+ if (sp_right(n))
+ continue;
+
+ /* we're the only free region left to check,
+ * are we large enough to carve a chunk out of? */
+ size_t offset = r->reserved - t->start;
+ if (size < qsize - offset)
+ return quick_best;
+
+ /* we are, so let's set the alignment to match that at
+ * least some parts of this block should be skipped */
+
+ /* try to use page order alignment if possible */
+ if (size <= bsize - offset) {
+ *align = start - t->start;
+ return t;
+ }
+
+ /* otherwise, carve out a block at the top of this node. */
+ *align = t->end - size;
+ return t;
+ }
+
if (!quick_best && size <= qsize)
quick_best = t;
@@ -328,8 +363,6 @@ struct mem_region *find_free_region(struct mem_region_root *r, size_t size,
*align = start - t->start;
return t;
}
-
- n = sp_right(n);
}
return quick_best;
diff --git a/src/vmem.c b/src/vmem.c
index 52e7bd2..6fb5474 100644
--- a/src/vmem.c
+++ b/src/vmem.c
@@ -18,19 +18,10 @@ stat_t init_uvmem(struct tcb *t)
{
t->uvmem.owner = t->tid;
t->uvmem.vmem = t->proc.vmem;
-
- stat_t ret = OK;
- if ((ret = init_region(&t->uvmem.region, UVMEM_START, UVMEM_END)))
- return ret;
-
- /* if a user really wants to use the first page for something, they'll
- * have to free it first, 'accepting' that no null-page is dangerous. */
- size_t size = 0;
- vm_t v = alloc_fixed_region(&t->uvmem.region,
- UVMEM_START, BASE_PAGE_SIZE, &size,
- MR_NONBACKED);
- assert(v == UVMEM_START && size == BASE_PAGE_SIZE);
- return OK;
+ /* reserve 64KiB (arbitrary number but should be large enough that
+ * nobody accidentally indexes above NULL enough to find real memory) */
+ return init_region(&t->uvmem.region, UVMEM_START,
+ UVMEM_END - UVMEM_START, SZ_64K);
}
/**
@@ -132,8 +123,8 @@ static vm_t __clone_shared_region(struct tcb *d, struct tcb *s,
if (ERR_CODE(v))
return v;
- stat_t res = clone_region(d->uvmem.vmem, s->uvmem.vmem, start, v, size,
- flags);
+ stat_t res = clone_region(d->uvmem.vmem, s->uvmem.vmem,
+ start, v, size, flags);
if (res == OK)
return v;