Make it possible to define an upper limit for memory consumed by

the rump kernel by specifying RUMP_MEMLIMIT.  In case allocation
over that limit is attempted, essentially pool reclaim and uvm_wait()
is done.  The default is to allow to allocate as much as the host
will give.

XXX: uvm_km_alloc and malloc(9) do not currently conform.  the
former is easy, the latter requires kern_malloc.c (rump malloc is
currently directly relegated to host malloc).
This commit is contained in:
pooka 2010-06-14 21:04:56 +00:00
parent 90f3d84c58
commit 771f2275a6
4 changed files with 58 additions and 12 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: locks_up.c,v 1.3 2010/06/03 10:56:20 pooka Exp $ */
/* $NetBSD: locks_up.c,v 1.4 2010/06/14 21:04:56 pooka Exp $ */
/*
* Copyright (c) 2010 Antti Kantee. All Rights Reserved.
@ -35,7 +35,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: locks_up.c,v 1.3 2010/06/03 10:56:20 pooka Exp $");
__KERNEL_RCSID(0, "$NetBSD: locks_up.c,v 1.4 2010/06/14 21:04:56 pooka Exp $");
#include <sys/param.h>
#include <sys/kernel.h>
@ -88,7 +88,7 @@ mutex_destroy(kmutex_t *mtx)
KASSERT(upm->upm_owner == NULL);
KASSERT(upm->upm_wanted == 0);
rumpuser_cv_destroy(upm->upm_rucv);
rumpuser_free(upm);
rump_hyperfree(upm, sizeof(*upm));
}
void
@ -192,7 +192,7 @@ rw_destroy(krwlock_t *rw)
rumpuser_cv_destroy(uprw->uprw_rucv_reader);
rumpuser_cv_destroy(uprw->uprw_rucv_writer);
rumpuser_free(uprw);
rump_hyperfree(uprw, sizeof(*uprw));
}
/* take rwlock. prefer writers over readers (see rw_tryenter and rw_exit) */

View File

@ -1,4 +1,4 @@
/* $NetBSD: memalloc.c,v 1.8 2010/06/03 19:36:21 pooka Exp $ */
/* $NetBSD: memalloc.c,v 1.9 2010/06/14 21:04:56 pooka Exp $ */
/*
* Copyright (c) 2009 Antti Kantee. All Rights Reserved.
@ -26,7 +26,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: memalloc.c,v 1.8 2010/06/03 19:36:21 pooka Exp $");
__KERNEL_RCSID(0, "$NetBSD: memalloc.c,v 1.9 2010/06/14 21:04:56 pooka Exp $");
#include <sys/param.h>
#include <sys/kmem.h>
@ -73,7 +73,7 @@ kern_malloc(unsigned long size, struct malloc_type *type, int flags)
{
void *rv;
rv = rump_hypermalloc(size, 0, (flags & M_WAITOK) != 0, "malloc");
rv = rumpuser_malloc(size, 0);
if (rv && flags & M_ZERO)
memset(rv, 0, size);

View File

@ -1,4 +1,4 @@
/* $NetBSD: rump_private.h,v 1.53 2010/06/13 16:49:01 pooka Exp $ */
/* $NetBSD: rump_private.h,v 1.54 2010/06/14 21:04:56 pooka Exp $ */
/*
* Copyright (c) 2007 Antti Kantee. All Rights Reserved.
@ -139,5 +139,6 @@ void rump_intr_init(void);
void rump_softint_run(struct cpu_info *);
void *rump_hypermalloc(size_t, int, bool, const char *);
void rump_hyperfree(void *, size_t);
#endif /* _SYS_RUMP_PRIVATE_H_ */

View File

@ -1,4 +1,4 @@
/* $NetBSD: vm.c,v 1.83 2010/06/10 21:40:42 pooka Exp $ */
/* $NetBSD: vm.c,v 1.84 2010/06/14 21:04:56 pooka Exp $ */
/*
* Copyright (c) 2007-2010 Antti Kantee. All Rights Reserved.
@ -43,7 +43,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: vm.c,v 1.83 2010/06/10 21:40:42 pooka Exp $");
__KERNEL_RCSID(0, "$NetBSD: vm.c,v 1.84 2010/06/14 21:04:56 pooka Exp $");
#include <sys/param.h>
#include <sys/atomic.h>
@ -91,6 +91,10 @@ static unsigned int pdaemon_waiters;
static kmutex_t pdaemonmtx;
static kcondvar_t pdaemoncv, oomwait;
#define RUMPMEM_UNLIMITED ((unsigned long)-1)
static unsigned long physmemlimit = RUMPMEM_UNLIMITED;
static unsigned long curphysmem;
/*
* vm pages
*/
@ -235,8 +239,24 @@ static kmutex_t pagermtx;
void
uvm_init(void)
{
char buf[64];
int error;
uvmexp.free = 1024*1024; /* XXX */
if (rumpuser_getenv("RUMP_MEMLIMIT", buf, sizeof(buf), &error) == 0) {
physmemlimit = strtoll(buf, NULL, 10);
/* it's not like we'd get far with, say, 1 byte, but ... */
if (physmemlimit == 0)
panic("uvm_init: no memory available");
#define HUMANIZE_BYTES 9
CTASSERT(sizeof(buf) >= HUMANIZE_BYTES);
format_bytes(buf, HUMANIZE_BYTES, physmemlimit);
#undef HUMANIZE_BYTES
} else {
strlcpy(buf, "unlimited (host limit)", sizeof(buf));
}
aprint_verbose("total memory = %s\n", buf);
uvmexp.free = 1024*1024; /* XXX: arbitrary & not updated */
mutex_init(&pagermtx, MUTEX_DEFAULT, 0);
mutex_init(&uvm_pageqlock, MUTEX_DEFAULT, 0);
@ -622,7 +642,7 @@ void
uvm_km_free_poolpage(struct vm_map *map, vaddr_t addr)
{
rumpuser_free((void *)addr);
rump_hyperfree((void *)addr, PAGE_SIZE);
}
vaddr_t
@ -854,8 +874,23 @@ uvm_kick_pdaemon()
void *
rump_hypermalloc(size_t howmuch, int alignment, bool waitok, const char *wmsg)
{
unsigned long newmem;
void *rv;
/* first we must be within the limit */
limitagain:
if (physmemlimit != RUMPMEM_UNLIMITED) {
newmem = atomic_add_long_nv(&curphysmem, howmuch);
if (newmem > physmemlimit) {
newmem = atomic_add_long_nv(&curphysmem, -howmuch);
if (!waitok)
return NULL;
uvm_wait(wmsg);
goto limitagain;
}
}
/* second, we must get something from the backend */
again:
rv = rumpuser_malloc(howmuch, alignment);
if (__predict_false(rv == NULL && waitok)) {
@ -865,3 +900,13 @@ rump_hypermalloc(size_t howmuch, int alignment, bool waitok, const char *wmsg)
return rv;
}
void
rump_hyperfree(void *what, size_t size)
{
if (physmemlimit != RUMPMEM_UNLIMITED) {
atomic_add_long(&curphysmem, -size);
}
rumpuser_free(what);
}