summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/bird.sgml7
-rw-r--r--lib/resource.c2
-rw-r--r--lib/slab.c2
-rw-r--r--sysdep/unix/alloc.c23
-rw-r--r--sysdep/unix/main.c32
5 files changed, 62 insertions, 4 deletions
diff --git a/doc/bird.sgml b/doc/bird.sgml
index 39dadaf2..ddad4d98 100644
--- a/doc/bird.sgml
+++ b/doc/bird.sgml
@@ -145,6 +145,13 @@ BIRD executable by configuring out routing protocols you don't use, and
<p>You can pass several command-line options to bird:
<descrip>
+ <tag><label id="argv-block">-B <m/exp/</tag>
+ allocate memory using 2^<cf/exp/ byte sized blocks;
+ if you're expecting high memory load, raise this to
+ reduce number of allocated memory pages. For a million routes
+ in one table, the recommended setting is 18.
+ Default is your system page size, typically 12 for 4096 bytes.
+
<tag><label id="argv-config">-c <m/config name/</tag>
use given configuration file instead of <it/prefix/<file>/etc/bird.conf</file>.
diff --git a/lib/resource.c b/lib/resource.c
index 0ad886d9..e80b315b 100644
--- a/lib/resource.c
+++ b/lib/resource.c
@@ -61,7 +61,6 @@ pool root_pool;
void *alloc_sys_page(void);
void free_sys_page(void *);
-void resource_sys_init(void);
static int indent;
@@ -283,7 +282,6 @@ rlookup(unsigned long a)
void
resource_init(void)
{
- resource_sys_init();
root_pool.r.class = &pool_class;
root_pool.name = "Root";
init_list(&root_pool.inside);
diff --git a/lib/slab.c b/lib/slab.c
index 2fc88ee0..6348e29b 100644
--- a/lib/slab.c
+++ b/lib/slab.c
@@ -178,7 +178,7 @@ struct sl_alignment { /* Magic structure for testing of alignment */
int x[0];
};
-#define SL_GET_HEAD(x) ((struct sl_head *) (((uintptr_t) (x)) & ~(page_size-1)))
+#define SL_GET_HEAD(x) ((struct sl_head *) PAGE_HEAD(x))
/**
* sl_new - create a new Slab
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);