summaryrefslogtreecommitdiff
path: root/sysdep/unix
diff options
context:
space:
mode:
authorMaria Matejka <mq@ucw.cz>2021-09-08 11:29:49 +0200
committerMaria Matejka <mq@ucw.cz>2021-10-13 19:01:22 +0200
commit6cd37713781a3092f8166b2178fae35cbfec1e28 (patch)
treed80aaadbbd0b39765f6284229420dea754618c45 /sysdep/unix
parent3a31c3aad6c53ea9673743f983e13728d8551149 (diff)
Multipage allocation
We can also quite simply allocate bigger blocks. Anyway, we need these blocks to be aligned to their size which needs one mmap() two times bigger and then two munmap()s returning the unaligned parts. The user can specify -B <N> on startup when <N> is the exponent of 2, setting the block size to 2^N. On most systems, N is 12, anyway if you know that your configuration is going to eat gigabytes of RAM, you are almost forced to raise your block size as you may easily get into memory fragmentation issues or you have to raise your maximum mapping count, e.g. "sysctl vm.max_map_count=(number)".
Diffstat (limited to 'sysdep/unix')
-rw-r--r--sysdep/unix/alloc.c23
-rw-r--r--sysdep/unix/main.c32
2 files changed, 54 insertions, 1 deletions
diff --git a/sysdep/unix/alloc.c b/sysdep/unix/alloc.c
index f6296afe..4c9d5eb5 100644
--- a/sysdep/unix/alloc.c
+++ b/sysdep/unix/alloc.c
@@ -17,6 +17,7 @@
#endif
long page_size = 0;
+_Bool alloc_multipage = 0;
#ifdef HAVE_MMAP
static _Bool use_fake = 0;
@@ -45,9 +46,31 @@ alloc_sys_page(void)
#ifdef HAVE_MMAP
if (!use_fake)
{
+ if (alloc_multipage)
+ {
+ void *big = mmap(NULL, page_size * 2, PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if (big == MAP_FAILED)
+ bug("mmap(%lu) failed: %m", page_size);
+
+ uintptr_t offset = ((uintptr_t) big) % page_size;
+ if (offset)
+ {
+ void *ret = big + page_size - offset;
+ munmap(big, page_size - offset);
+ munmap(ret + page_size, offset);
+ return ret;
+ }
+ else
+ {
+ munmap(big + page_size, page_size);
+ return big;
+ }
+ }
+
void *ret = mmap(NULL, page_size, PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (ret == MAP_FAILED)
bug("mmap(%lu) failed: %m", page_size);
+
return ret;
}
else
diff --git a/sysdep/unix/main.c b/sysdep/unix/main.c
index cdf0a310..7e8ea0dc 100644
--- a/sysdep/unix/main.c
+++ b/sysdep/unix/main.c
@@ -682,7 +682,7 @@ signal_init(void)
* Parsing of command-line arguments
*/
-static char *opt_list = "bc:dD:ps:P:u:g:flRh";
+static char *opt_list = "B:c:dD:ps:P:u:g:flRh";
int parse_and_exit;
char *bird_name;
static char *use_user;
@@ -703,6 +703,7 @@ display_help(void)
fprintf(stderr,
"\n"
"Options: \n"
+ " -B <block-size> Use 2^this number as memory allocation block size (default: 12)\n"
" -c <config-file> Use given configuration file instead of\n"
" " PATH_CONFIG_FILE "\n"
" -d Enable debug messages and run bird in foreground\n"
@@ -789,12 +790,15 @@ get_gid(const char *s)
return gr->gr_gid;
}
+extern _Bool alloc_multipage;
+
static void
parse_args(int argc, char **argv)
{
int config_changed = 0;
int socket_changed = 0;
int c;
+ int bp;
bird_name = get_bird_name(argv[0], "bird");
if (argc == 2)
@@ -807,6 +811,29 @@ parse_args(int argc, char **argv)
while ((c = getopt(argc, argv, opt_list)) >= 0)
switch (c)
{
+ case 'B':
+ bp = atoi(optarg);
+ if (bp < 1)
+ {
+ fprintf(stderr, "Strange block size power %d\n\n", bp);
+ display_usage();
+ exit(1);
+ }
+
+ if ((1 << bp) < page_size)
+ {
+ fprintf(stderr, "Requested block size %ld is lesser than page size %ld\n\n", (1L<<bp), page_size);
+ display_usage();
+ exit(1);
+ }
+
+ if ((1L << bp) > page_size)
+ {
+ alloc_multipage = 1;
+ page_size = (1L << bp);
+ }
+
+ break;
case 'c':
config_name = optarg;
config_changed = 1;
@@ -861,6 +888,8 @@ parse_args(int argc, char **argv)
}
}
+void resource_sys_init(void);
+
/*
* Hic Est main()
*/
@@ -873,6 +902,7 @@ main(int argc, char **argv)
dmalloc_debug(0x2f03d00);
#endif
+ resource_sys_init();
parse_args(argc, argv);
log_switch(1, NULL, NULL);