More pipe changes:

From alc:
Move pageable pipe memory to a seperate kernel submap to avoid awkward
vm map interlocking issues.  (Bad explanation provided by me.)

From me:
Rework pipespace accounting code to handle this new layout, and adjust
our default values to account for the fact that we now have a solid
limit on allocations.

Also, remove the "maxpipes" limit, as it no longer has a purpose.
(The limit on kva usage solves the problem of having two many pipes.)
This commit is contained in:
Mike Silbersack 2003-08-11 05:51:51 +00:00
parent 5bff585104
commit cebde06978
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=118764
6 changed files with 39 additions and 49 deletions

View File

@ -77,7 +77,6 @@ int nbuf;
int nswbuf;
int maxswzone; /* max swmeta KVA storage */
int maxbcache; /* max buffer cache KVA storage */
int maxpipes; /* Limit on # of pipes */
int maxpipekva; /* Limit on pipe KVA */
int maxpipekvawired; /* Limit on wired pipe KVA */
u_quad_t maxtsiz; /* max text size */
@ -180,19 +179,18 @@ void
init_param3(long kmempages)
{
/*
* Limit number of pipes to a reasonable fraction of kmap entries,
* pageable pipe memory usage to 2.5% of the kernel map, and wired
* pipe memory usage to 1% of the same. Ensure that all have
* reasonable floors. (See sys_pipe.c for more info.)
* Limit pageable pipe memory usage to 5% of the kernel map
* (via pipe_map), and nonpageable pipe memory usage to 2.5%
* of the same. Ensure that all have reasonable floors.
* (See sys_pipe.c for more info.)
*/
maxpipes = kmempages / 5;
maxpipekva = (kmempages / 40) * PAGE_SIZE;
maxpipekvawired = (kmempages / 100) * PAGE_SIZE;
maxpipekva = (kmempages / 20) * PAGE_SIZE;
maxpipekvawired = (kmempages / 40) * PAGE_SIZE;
if (maxpipes < 128)
maxpipes = 128;
if (maxpipekva < 512 * 1024)
maxpipekva = 512 * 1024;
if (maxpipekvawired < 512 * 1024)
maxpipekvawired = 512 * 1024;
TUNABLE_INT_FETCH("kern.ipc.maxpipekva", &maxpipekva);
}

View File

@ -43,24 +43,20 @@
*
* The constant PIPE_MINDIRECT is chosen to make sure that buffering will
* happen for small transfers so that the system will not spend all of
* its time context switching. PIPE_SIZE is constrained by the
* amount of kernel virtual memory.
* its time context switching.
*
* In order to limit the resource use of pipes, three sysctls exist:
* In order to limit the resource use of pipes, two sysctls exist:
*
* kern.ipc.maxpipes - A limit on the total number of pipes in the system.
* Note that since pipes are bidirectional, the effective value is this
* number divided by two.
*
* kern.ipc.maxpipekva - This value limits the amount of pageable memory that
* can be used by pipes. Whenever the amount in use exceeds this value,
* all new pipes will be SMALL_PIPE_SIZE in size, rather than PIPE_SIZE.
* Big pipe creation will be limited as well.
* kern.ipc.maxpipekva - This is a hard limit on the amount of pageable
* address space available to us in pipe_map. Whenever the amount in use
* exceeds half of this value, all new pipes will be created with size
* SMALL_PIPE_SIZE, rather than PIPE_SIZE. Big pipe creation will be limited
* as well. This value is loader tunable only.
*
* kern.ipc.maxpipekvawired - This value limits the amount of memory that may
* be wired in order to facilitate direct copies using page flipping.
* Whenever this value is exceeded, pipes will fall back to using regular
* copies.
* copies. This value is sysctl controllable at all times.
*
* These values are autotuned in subr_param.c.
*
@ -182,9 +178,7 @@ static int amountpipekvawired;
SYSCTL_DECL(_kern_ipc);
SYSCTL_INT(_kern_ipc, OID_AUTO, maxpipes, CTLFLAG_RW,
&maxpipes, 0, "Max # of pipes");
SYSCTL_INT(_kern_ipc, OID_AUTO, maxpipekva, CTLFLAG_RW,
SYSCTL_INT(_kern_ipc, OID_AUTO, maxpipekva, CTLFLAG_RD,
&maxpipekva, 0, "Pipe KVA limit");
SYSCTL_INT(_kern_ipc, OID_AUTO, maxpipekvawired, CTLFLAG_RW,
&maxpipekvawired, 0, "Pipe KVA wired limit");
@ -339,32 +333,29 @@ pipespace(cpipe, size)
KASSERT(cpipe->pipe_mtxp == NULL || !mtx_owned(PIPE_MTX(cpipe)),
("pipespace: pipe mutex locked"));
if (amountpipes > maxpipes) {
if (ppsratecheck(&lastfail, &curfail, 1))
printf("kern.maxpipes exceeded, please see tuning(7).\n");
return (ENOMEM);
}
npages = round_page(size)/PAGE_SIZE;
size = round_page(size);
npages = size / PAGE_SIZE;
/*
* Create an object, I don't like the idea of paging to/from
* kernel_object.
* XXX -- minor change needed here for NetBSD/OpenBSD VM systems.
*/
object = vm_object_allocate(OBJT_DEFAULT, npages);
buffer = (caddr_t) vm_map_min(kernel_map);
buffer = (caddr_t) vm_map_min(pipe_map);
/*
* Insert the object into the kernel map, and allocate kva for it.
* The map entry is, by default, pageable.
* XXX -- minor change needed here for NetBSD/OpenBSD VM systems.
*/
error = vm_map_find(kernel_map, object, 0,
error = vm_map_find(pipe_map, object, 0,
(vm_offset_t *) &buffer, size, 1,
VM_PROT_ALL, VM_PROT_ALL, 0);
if (error != KERN_SUCCESS) {
vm_object_deallocate(object);
if (ppsratecheck(&lastfail, &curfail, 1))
printf("kern.maxpipekva exceeded, please see tuning(7).\n");
return (ENOMEM);
}
@ -423,7 +414,7 @@ pipe_create(cpipep)
/*
* Reduce to 1/4th pipe size if we're over our global max.
*/
if (amountpipekva > maxpipekva)
if (amountpipekva > maxpipekva / 2)
error = pipespace(cpipe, SMALL_PIPE_SIZE);
else
error = pipespace(cpipe, PIPE_SIZE);
@ -697,8 +688,6 @@ pipe_build_write_buffer(wpipe, uio)
vm_page_lock_queues();
for (j = 0; j < i; j++) {
vm_page_unhold(wpipe->pipe_map.ms[j]);
atomic_subtract_int(&amountpipekvawired,
PAGE_SIZE);
}
vm_page_unlock_queues();
return (EFAULT);
@ -707,7 +696,6 @@ pipe_build_write_buffer(wpipe, uio)
m = PHYS_TO_VM_PAGE(paddr);
vm_page_lock_queues();
vm_page_hold(m);
atomic_add_int(&amountpipekvawired, PAGE_SIZE);
vm_page_unlock_queues();
wpipe->pipe_map.ms[i] = m;
}
@ -730,7 +718,7 @@ pipe_build_write_buffer(wpipe, uio)
*/
wpipe->pipe_map.kva = kmem_alloc_nofault(kernel_map,
wpipe->pipe_buffer.size + PAGE_SIZE);
atomic_add_int(&amountpipekva,
atomic_add_int(&amountpipekvawired,
wpipe->pipe_buffer.size + PAGE_SIZE);
}
pmap_qenter(wpipe->pipe_map.kva, wpipe->pipe_map.ms,
@ -764,19 +752,19 @@ pipe_destroy_write_buffer(wpipe)
if (wpipe->pipe_map.kva) {
pmap_qremove(wpipe->pipe_map.kva, wpipe->pipe_map.npages);
if (amountpipekva > maxpipekva) {
if (amountpipekvawired > maxpipekvawired / 2) {
/* Conserve address space */
vm_offset_t kva = wpipe->pipe_map.kva;
wpipe->pipe_map.kva = 0;
kmem_free(kernel_map, kva,
wpipe->pipe_buffer.size + PAGE_SIZE);
atomic_subtract_int(&amountpipekva,
atomic_subtract_int(&amountpipekvawired,
wpipe->pipe_buffer.size + PAGE_SIZE);
}
}
vm_page_lock_queues();
for (i = 0; i < wpipe->pipe_map.npages; i++) {
vm_page_unhold(wpipe->pipe_map.ms[i]);
atomic_subtract_int(&amountpipekvawired, PAGE_SIZE);
}
vm_page_unlock_queues();
wpipe->pipe_map.npages = 0;
@ -951,7 +939,7 @@ pipe_write(fp, uio, active_cred, flags, td)
* so.
*/
if ((uio->uio_resid > PIPE_SIZE) &&
(amountpipekva < maxpipekva) &&
(amountpipekva < maxpipekva / 2) &&
(nbigpipe < LIMITBIGPIPES) &&
(wpipe->pipe_state & PIPE_DIRECTW) == 0 &&
(wpipe->pipe_buffer.size <= PIPE_SIZE) &&
@ -998,7 +986,7 @@ pipe_write(fp, uio, active_cred, flags, td)
*/
if ((uio->uio_iov->iov_len >= PIPE_MINDIRECT) &&
(fp->f_flag & FNONBLOCK) == 0 &&
amountpipekvawired < maxpipekvawired) {
amountpipekvawired + uio->uio_resid < maxpipekvawired) {
error = pipe_direct_write(wpipe, uio);
if (error)
break;
@ -1404,14 +1392,14 @@ pipe_free_kmem(cpipe)
atomic_subtract_int(&nbigpipe, 1);
atomic_subtract_int(&amountpipekva, cpipe->pipe_buffer.size);
atomic_subtract_int(&amountpipes, 1);
kmem_free(kernel_map,
(vm_offset_t)cpipe->pipe_buffer.buffer,
cpipe->pipe_buffer.size);
vm_map_remove(pipe_map,
(vm_offset_t)cpipe->pipe_buffer.buffer,
(vm_offset_t)cpipe->pipe_buffer.buffer + cpipe->pipe_buffer.size);
cpipe->pipe_buffer.buffer = NULL;
}
#ifndef PIPE_NODIRECT
if (cpipe->pipe_map.kva != 0) {
atomic_subtract_int(&amountpipekva,
atomic_subtract_int(&amountpipekvawired,
cpipe->pipe_buffer.size + PAGE_SIZE);
kmem_free(kernel_map,
cpipe->pipe_map.kva,

View File

@ -60,7 +60,6 @@
/*
* See sys_pipe.c for info on what these limits mean.
*/
extern int maxpipes;
extern int maxpipekva;
extern int maxpipekvawired;

View File

@ -75,6 +75,8 @@ __FBSDID("$FreeBSD$");
#include <sys/mutex.h>
#include <sys/proc.h>
#include <sys/systm.h>
#include <sys/selinfo.h>
#include <sys/pipe.h>
#include <sys/bio.h>
#include <sys/buf.h>
@ -195,6 +197,7 @@ vm_ksubmap_init(struct kva_md_info *kmi)
pager_map->system_map = 1;
exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
(16*(ARG_MAX+(PAGE_SIZE*3))));
pipe_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr, maxpipekva);
/*
* XXX: Mbuf system machine-specific initializations should

View File

@ -89,6 +89,7 @@ __FBSDID("$FreeBSD$");
vm_map_t kernel_map=0;
vm_map_t kmem_map=0;
vm_map_t exec_map=0;
vm_map_t pipe_map;
vm_map_t clean_map=0;
vm_map_t buffer_map=0;

View File

@ -73,6 +73,7 @@ extern vm_map_t kernel_map;
extern vm_map_t kmem_map;
extern vm_map_t clean_map;
extern vm_map_t exec_map;
extern vm_map_t pipe_map;
extern u_int vm_kmem_size;
#endif /* _VM_VM_KERN_H_ */