summaryrefslogtreecommitdiff
path: root/lib/resource.c
diff options
context:
space:
mode:
authorMaria Matejka <mq@ucw.cz>2021-11-11 16:25:59 +0100
committerMaria Matejka <mq@ucw.cz>2021-11-22 19:05:44 +0100
commit794a4eefa11f3166404d91edddd0f4f19458f652 (patch)
tree915c139b02ab72ce79622c3c855e6c72af872c4d /lib/resource.c
parent4f3fa1623f66acd24c227cf0cc5a4af2f5133b6c (diff)
Keeping un-unmmappable pages until they can be reused
On Linux, munmap() may fail with ENOMEM when virtual memory is too fragmented. Working this around by just keeping such blocks for future use.
Diffstat (limited to 'lib/resource.c')
-rw-r--r--lib/resource.c23
1 files changed, 17 insertions, 6 deletions
diff --git a/lib/resource.c b/lib/resource.c
index e80b315b..2d041ad5 100644
--- a/lib/resource.c
+++ b/lib/resource.c
@@ -60,7 +60,7 @@ static struct resclass pool_class = {
pool root_pool;
void *alloc_sys_page(void);
-void free_sys_page(void *);
+int free_sys_page(void *);
static int indent;
@@ -98,8 +98,10 @@ pool_free(resource *P)
if (p->pages)
{
ASSERT_DIE(!p->pages->used);
- for (uint i=0; i<p->pages->free; i++)
+
+ for (uint i = 0; i < p->pages->free; i++)
free_sys_page(p->pages->ptr[i]);
+
free_sys_page(p->pages);
}
}
@@ -476,10 +478,19 @@ free_page(pool *p, void *ptr)
ASSERT_DIE(p->pages);
p->pages->used--;
- if (p->pages->free >= POOL_PAGES_MAX)
- return free_sys_page(ptr);
- else
- p->pages->ptr[p->pages->free++] = ptr;
+ ASSERT_DIE(p->pages->free <= POOL_PAGES_MAX);
+
+ if (p->pages->free == POOL_PAGES_MAX)
+ {
+ const unsigned long keep = POOL_PAGES_MAX / 4;
+
+ for (uint i = keep; i < p->pages->free; i++)
+ free_sys_page(p->pages->ptr[i]);
+
+ p->pages->free = keep;
+ }
+
+ p->pages->ptr[p->pages->free++] = ptr;
}