vm_unix.c revision 189015
1139826Simp/*-
253541Sshin * Copyright (c) 1988 University of Utah.
353541Sshin * Copyright (c) 1991, 1993
453541Sshin *	The Regents of the University of California.  All rights reserved.
553541Sshin *
653541Sshin * This code is derived from software contributed to Berkeley by
753541Sshin * the Systems Programming Group of the University of Utah Computer
853541Sshin * Science Department.
953541Sshin *
1053541Sshin * Redistribution and use in source and binary forms, with or without
1153541Sshin * modification, are permitted provided that the following conditions
1253541Sshin * are met:
1353541Sshin * 1. Redistributions of source code must retain the above copyright
1453541Sshin *    notice, this list of conditions and the following disclaimer.
1553541Sshin * 2. Redistributions in binary form must reproduce the above copyright
1653541Sshin *    notice, this list of conditions and the following disclaimer in the
1753541Sshin *    documentation and/or other materials provided with the distribution.
1853541Sshin * 4. Neither the name of the University nor the names of its contributors
1953541Sshin *    may be used to endorse or promote products derived from this software
2053541Sshin *    without specific prior written permission.
2153541Sshin *
2253541Sshin * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2353541Sshin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2453541Sshin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2553541Sshin * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2653541Sshin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2753541Sshin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28174510Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29174510Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3053541Sshin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3153541Sshin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32174510Sobrien * SUCH DAMAGE.
33174510Sobrien *
34174510Sobrien * from: Utah $Hdr: vm_unix.c 1.1 89/11/07$
3562587Sitojun *
3662587Sitojun *	@(#)vm_unix.c	8.1 (Berkeley) 6/11/93
3762587Sitojun */
3853541Sshin
3953541Sshin/*
4053541Sshin * Traditional sbrk/grow interface to VM
4153541Sshin */
42303458Ssbruno
4353541Sshin#include <sys/cdefs.h>
4453541Sshin__FBSDID("$FreeBSD: head/sys/vm/vm_unix.c 189015 2009-02-24 20:57:43Z kib $");
4553541Sshin
4678064Sume#include <sys/param.h>
47185751Simp#include <sys/lock.h>
4853541Sshin#include <sys/mutex.h>
49185747Skmacy#include <sys/proc.h>
5053541Sshin#include <sys/resourcevar.h>
5178064Sume#include <sys/sysproto.h>
5253541Sshin#include <sys/systm.h>
5353541Sshin
5453541Sshin#include <vm/vm.h>
5553541Sshin#include <vm/vm_param.h>
5653541Sshin#include <vm/pmap.h>
5753541Sshin#include <vm/vm_map.h>
58185571Sbz
5953541Sshin#ifndef _SYS_SYSPROTO_H_
6053541Sshinstruct obreak_args {
61186119Sqingli	char *nsize;
6253541Sshin};
6378064Sume#endif
6462587Sitojun
6553541Sshin/*
6653541Sshin * MPSAFE
6762587Sitojun */
6862587Sitojun/* ARGSUSED */
6953541Sshinint
70175162Sobrienobreak(td, uap)
71175162Sobrien	struct thread *td;
72241916Sdelphij	struct obreak_args *uap;
73241916Sdelphij{
74241916Sdelphij	struct vmspace *vm = td->td_proc->p_vmspace;
75241916Sdelphij	vm_offset_t new, old, base;
76241916Sdelphij	rlim_t datalim, vmemlim;
77175162Sobrien	int rv;
78175162Sobrien	int error = 0;
7962587Sitojun	boolean_t do_map_wirefuture;
80175162Sobrien
81175162Sobrien	PROC_LOCK(td->td_proc);
82175162Sobrien	datalim = lim_cur(td->td_proc, RLIMIT_DATA);
8353541Sshin	vmemlim = lim_cur(td->td_proc, RLIMIT_VMEM);
84175162Sobrien	PROC_UNLOCK(td->td_proc);
85241916Sdelphij
86241916Sdelphij	do_map_wirefuture = FALSE;
8753541Sshin	new = round_page((vm_offset_t)uap->nsize);
88229547Sbz	vm_map_lock(&vm->vm_map);
89229547Sbz
90229547Sbz	base = round_page((vm_offset_t) vm->vm_daddr);
91175162Sobrien	old = base + ctob(vm->vm_dsize);
9253541Sshin	if (new > base) {
93195699Srwatson		/*
94195727Srwatson		 * Check the resource limit, but allow a process to reduce
9553541Sshin		 * its usage, even if it remains over the limit.
96215701Sdim		 */
97207369Sbz		if (new - base > datalim && new > old) {
98195727Srwatson			error = ENOMEM;
9962587Sitojun			goto done;
100207369Sbz		}
101207369Sbz		if (new > vm_map_max(&vm->vm_map)) {
102195699Srwatson			error = ENOMEM;
103207369Sbz			goto done;
104207369Sbz		}
10578064Sume	} else if (new < base) {
106207369Sbz		/*
107207369Sbz		 * This is simply an invalid value.  If someone wants to
108151539Ssuz		 * do fancy address space manipulations, mmap and munmap
109151539Ssuz		 * can do most of what the user would want.
110151539Ssuz		 */
111151539Ssuz		error = EINVAL;
112151539Ssuz		goto done;
113151539Ssuz	}
114151539Ssuz	if (new > old) {
11578064Sume		if (vm->vm_map.size + (new - old) > vmemlim) {
11653541Sshin			error = ENOMEM;
11753541Sshin			goto done;
11853541Sshin		}
11953541Sshin		rv = vm_map_insert(&vm->vm_map, NULL, 0, old, new,
12053541Sshin		    VM_PROT_ALL, VM_PROT_ALL, 0);
12153541Sshin		if (rv != KERN_SUCCESS) {
12253541Sshin			error = ENOMEM;
123171259Sdelphij			goto done;
12453541Sshin		}
12553541Sshin		vm->vm_dsize += btoc(new - old);
12653541Sshin		/*
12762587Sitojun		 * Handle the MAP_WIREFUTURE case for legacy applications,
12853541Sshin		 * by marking the newly mapped range of pages as wired.
12953541Sshin		 * We are not required to perform a corresponding
13053541Sshin		 * vm_map_unwire() before vm_map_delete() below, as
13153541Sshin		 * it will forcibly unwire the pages in the range.
132165118Sbz		 *
13353541Sshin		 * XXX If the pages cannot be wired, no error is returned.
134222728Shrs		 */
135222728Shrs		if ((vm->vm_map.flags & MAP_WIREFUTURE) == MAP_WIREFUTURE) {
136222728Shrs			if (bootverbose)
137222728Shrs				printf("obreak: MAP_WIREFUTURE set\n");
138222728Shrs			do_map_wirefuture = TRUE;
13962587Sitojun		}
14053541Sshin	} else if (new < old) {
14153541Sshin		rv = vm_map_delete(&vm->vm_map, new, old);
14253541Sshin		if (rv != KERN_SUCCESS) {
14378064Sume			error = ENOMEM;
14478064Sume			goto done;
145165118Sbz		}
146165118Sbz		vm->vm_dsize -= btoc(old - new);
14778064Sume	}
14853541Sshindone:
14953541Sshin	vm_map_unlock(&vm->vm_map);
15053541Sshin
15153541Sshin	if (do_map_wirefuture)
15253541Sshin		(void) vm_map_wire(&vm->vm_map, old, new,
15353541Sshin		    VM_MAP_WIRE_USER|VM_MAP_WIRE_NOHOLES);
15453541Sshin
15562587Sitojun	return (error);
15662587Sitojun}
15762587Sitojun
15862587Sitojun#ifndef _SYS_SYSPROTO_H_
15962587Sitojunstruct ovadvise_args {
16062587Sitojun	int anom;
16162587Sitojun};
16262587Sitojun#endif
163190964Srwatson
16453541Sshin/*
16562587Sitojun * MPSAFE
16662587Sitojun */
16753541Sshin/* ARGSUSED */
16853541Sshinint
16953541Sshinovadvise(td, uap)
17053541Sshin	struct thread *td;
17178064Sume	struct ovadvise_args *uap;
17278064Sume{
17378064Sume	/* START_GIANT_OPTIONAL */
17462587Sitojun	/* END_GIANT_OPTIONAL */
17553541Sshin	return (EINVAL);
17653541Sshin}
17753541Sshin