Date: Sat, 19 Jul 2003 12:19:52 +0100 From: Bruce M Simpson <bms@spc.org> To: FreeBSD-gnats-submit@FreeBSD.org, freebsd-standards@FreeBSD.org Cc: alc@freebsd.org Subject: Re: standards/54223: [PATCH] Add mlockall(), munlockall() syscalls to -CURRENT Message-ID: <20030719111952.GB12995@spc.org> In-Reply-To: <200307081530.h68FUDlb025977@freefall.freebsd.org> References: <20030708152410.5E14036C@saboteur.dek.spc.org> <200307081530.h68FUDlb025977@freefall.freebsd.org>
next in thread | previous in thread | raw e-mail | index | archive | help
--OgqxwSJOaUobr8KG Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Here is an updated patch which fixes some issues. BMS --OgqxwSJOaUobr8KG Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="mlockall.patch" Revised patch to add mlockall()/munlockall() to FreeBSD 5.1-RELEASE. - Believed to back out of allocations and locks correctly (tested with WITNESS, MUTEX_PROFILING, INVARIANTS and DIAGNOSTIC). - Inspected at the vmstat, top and vm pager sysctl stats level. Paging-in activity is occurring correctly, using a test harness. - The RES size for a process may appear to be greater than its SIZE. This is believed to be due to mappings of the same shared library page being wired twice. Further exploration is needed. - All those diffs to syscalls.master for each architecture *are* necessary. This needed clarification; the stub code generation for mlockall() was disabled, which would prevent applications from linking to this API (suggested by mux@freebsd.org) - vm_map_*_all() may be eliminated and 0 no longer special (reviewed by alc@freebsd.org) - Giant has been quoshed. It is no longer held by the code, as the required locking has been pushed down within vm_map.c. Bruce M Simpson <bms@spc.org> Generated by diffcoll on Sat 19 Jul 2003 00:54:30 BST diff -uN src/lib/libc/alpha/sys/Makefile.inc.orig src/lib/libc/alpha/sys/Makefile.inc --- /usr/src/lib/libc/alpha/sys/Makefile.inc.orig Fri May 30 11:25:46 2003 +++ /usr/src/lib/libc/alpha/sys/Makefile.inc Sat Jul 19 00:52:04 2003 @@ -5,7 +5,7 @@ # Don't generate default code for these syscalls: NOASM= break.o exit.o ftruncate.o getdomainname.o getlogin.o \ - lseek.o mlockall.o mmap.o munlockall.o openbsd_poll.o pread.o \ + lseek.o mmap.o openbsd_poll.o pread.o \ pwrite.o setdomainname.o sstk.o truncate.o uname.o vfork.o yield.o PSEUDO= _getlogin.o _exit.o diff -uN src/lib/libc/amd64/sys/Makefile.inc.orig src/lib/libc/amd64/sys/Makefile.inc --- /usr/src/lib/libc/amd64/sys/Makefile.inc.orig Fri May 30 11:26:03 2003 +++ /usr/src/lib/libc/amd64/sys/Makefile.inc Sat Jul 19 00:52:04 2003 @@ -6,7 +6,7 @@ # Don't generate default code for these syscalls: NOASM= break.o exit.o ftruncate.o getdomainname.o getlogin.o \ - lseek.o mlockall.o mmap.o munlockall.o openbsd_poll.o pread.o \ + lseek.o mmap.o openbsd_poll.o pread.o \ pwrite.o setdomainname.o sstk.o truncate.o uname.o vfork.o yield.o PSEUDO= _getlogin.o _exit.o diff -uN src/lib/libc/i386/sys/Makefile.inc.orig src/lib/libc/i386/sys/Makefile.inc --- /usr/src/lib/libc/i386/sys/Makefile.inc.orig Fri May 30 04:44:28 2003 +++ /usr/src/lib/libc/i386/sys/Makefile.inc Sat Jul 19 00:52:04 2003 @@ -9,7 +9,7 @@ # Don't generate default code for these syscalls: NOASM= break.o exit.o ftruncate.o getdomainname.o getlogin.o \ - lseek.o mlockall.o mmap.o munlockall.o openbsd_poll.o pread.o \ + lseek.o mmap.o openbsd_poll.o pread.o \ pwrite.o setdomainname.o sstk.o truncate.o uname.o vfork.o yield.o PSEUDO= _getlogin.o _exit.o diff -uN src/lib/libc/ia64/sys/Makefile.inc.orig src/lib/libc/ia64/sys/Makefile.inc --- /usr/src/lib/libc/ia64/sys/Makefile.inc.orig Fri May 30 11:26:25 2003 +++ /usr/src/lib/libc/ia64/sys/Makefile.inc Sat Jul 19 00:52:04 2003 @@ -5,7 +5,7 @@ # Don't generate default code for these syscalls: NOASM= break.o exit.o ftruncate.o getdomainname.o getlogin.o \ - lseek.o mlockall.o mmap.o munlockall.o openbsd_poll.o pread.o \ + lseek.o mmap.o openbsd_poll.o pread.o \ pwrite.o setdomainname.o sstk.o truncate.o uname.o vfork.o yield.o PSEUDO= _getlogin.o _exit.o diff -uN src/lib/libc/powerpc/sys/Makefile.inc.orig src/lib/libc/powerpc/sys/Makefile.inc --- /usr/src/lib/libc/powerpc/sys/Makefile.inc.orig Fri May 30 11:26:40 2003 +++ /usr/src/lib/libc/powerpc/sys/Makefile.inc Sat Jul 19 00:52:04 2003 @@ -4,7 +4,7 @@ # Don't generate default code for these syscalls: NOASM= break.o exit.o ftruncate.o getdomainname.o getlogin.o \ - lseek.o mlockall.o mmap.o munlockall.o openbsd_poll.o pread.o \ + lseek.o mmap.o openbsd_poll.o pread.o \ pwrite.o setdomainname.o sstk.o truncate.o uname.o yield.o PSEUDO= _getlogin.o _exit.o diff -uN src/lib/libc/sparc64/sys/Makefile.inc.orig src/lib/libc/sparc64/sys/Makefile.inc --- /usr/src/lib/libc/sparc64/sys/Makefile.inc.orig Fri May 30 11:27:02 2003 +++ /usr/src/lib/libc/sparc64/sys/Makefile.inc Sat Jul 19 00:52:04 2003 @@ -16,7 +16,7 @@ # Don't generate default code for these syscalls: NOASM= break.o exit.o ftruncate.o getdomainname.o getlogin.o \ - lseek.o mlockall.o mmap.o munlockall.o openbsd_poll.o pread.o \ + lseek.o mmap.o openbsd_poll.o pread.o \ pwrite.o setdomainname.o sstk.o truncate.o uname.o yield.o PSEUDO= _getlogin.o _exit.o diff -uN src/lib/libc/sys/Makefile.inc.orig src/lib/libc/sys/Makefile.inc --- /usr/src/lib/libc/sys/Makefile.inc.orig Sat Jun 21 10:03:26 2003 +++ /usr/src/lib/libc/sys/Makefile.inc Sat Jul 19 00:52:04 2003 @@ -69,8 +69,8 @@ kldfind.2 kldfirstmod.2 kldload.2 kldnext.2 kldstat.2 kldsym.2 \ kldunload.2 kqueue.2 kse.2 ktrace.2 link.2 lio_listio.2 listen.2 \ lseek.2 \ - madvise.2 mincore.2 minherit.2 mkdir.2 mkfifo.2 mknod.2 mlock.2 mmap.2 \ - modfind.2 modnext.2 modstat.2 mount.2 \ + madvise.2 mincore.2 minherit.2 mkdir.2 mkfifo.2 mknod.2 mlock.2 \ + mlockall.2 mmap.2 modfind.2 modnext.2 modstat.2 mount.2 \ mprotect.2 msync.2 munmap.2 nanosleep.2 ntp_adjtime.2 ntp_gettime.2 \ nfssvc.2 open.2 pathconf.2 pipe.2 poll.2 profil.2 ptrace.2 quotactl.2 \ read.2 readlink.2 reboot.2 recv.2 rename.2 revoke.2 rfork.2 rmdir.2 \ diff -uN src/lib/libc/sys/mlockall.2.orig src/lib/libc/sys/mlockall.2 --- /usr/src/lib/libc/sys/mlockall.2.orig Fri May 30 07:01:26 2003 +++ /usr/src/lib/libc/sys/mlockall.2 Sat Jul 19 00:52:04 2003 @@ -0,0 +1,140 @@ +.\" $NetBSD: mlockall.2,v 1.11 2003/04/16 13:34:54 wiz Exp $ +.\" +.\" Copyright (c) 1999 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" This code is derived from software contributed to The NetBSD Foundation +.\" by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, +.\" NASA Ames Research Center. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the NetBSD +.\" Foundation, Inc. and its contributors. +.\" 4. Neither the name of The NetBSD Foundation nor the names of its +.\" contributors may be used to endorse or promote products derived +.\" from this software without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +.\" POSSIBILITY OF SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd June 12, 1999 +.Dt MLOCKALL 2 +.Os +.Sh NAME +.Nm mlockall , +.Nm munlockall +.Nd lock (unlock) the address space of a process +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In sys/mman.h +.Ft int +.Fn mlockall "int flags" +.Ft int +.Fn munlockall "void" +.Sh DESCRIPTION +The +.Nm mlockall +system call locks into memory the physical pages associated with the +address space of a process until the address space is unlocked, the +process exits, or execs another program image. +.Pp +The following flags affect the behavior of +.Nm mlockall : +.Bl -tag -width MCL_CURRENT +.It Dv MCL_CURRENT +Lock all pages currently mapped into the process's address space. +.It Dv MCL_FUTURE +Lock all pages mapped into the process's address space in the future, +at the time the mapping is established. +Note that this may cause future mappings to fail if those mappings +cause resource limits to be exceeded. +.El +.Pp +Since physical memory is a potentially scarce resource, processes are +limited in how much they can lock down. +A single process can lock the minimum of a system-wide +.Dq wired pages +limit and the per-process +.Li RLIMIT_MEMLOCK +resource limit. +.Pp +The +.Nm munlockall +call unlocks any locked memory regions in the process address space. +Any regions mapped after an +.Nm munlockall +call will not be locked. +.Sh RETURN VALUES +A return value of 0 indicates that the call +succeeded and all pages in the range have either been locked or unlocked. +A return value of -1 indicates an error occurred and the locked +status of all pages in the range remains unchanged. +In this case, the global location +.Va errno +is set to indicate the error. +.Sh ERRORS +.Fn mlockall +will fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +The +.Ar flags +argument is zero, or includes unimplemented flags. +.It Bq Er ENOMEM +Locking the indicated range would exceed either the system or per-process +limit for locked memory. +.It Bq Er EAGAIN +Some or all of the memory mapped into the process's address space +could not be locked when the call was made. +.It Bq Er EPERM +The calling process does not have the appropriate privilege to perform +the requested operation. +.El +.Sh SEE ALSO +.Xr mincore 2 , +.Xr mlock 2 , +.Xr mmap 2 , +.Xr munmap 2 , +.Xr setrlimit 2 +.Sh STANDARDS +The +.Fn mlockall +and +.Fn munlockall +functions are believed to conform to +.St -p1003.1-2001 . +.Sh HISTORY +The +.Fn mlockall +and +.Fn munlockall +functions first appeared in +.Fx 5.1 . +.Sh BUGS +The per-process resource limit is a limit on the amount of virtual +memory locked, while the system-wide limit is for the number of locked +physical pages. +Hence a process with two distinct locked mappings of the same physical page +counts as 2 pages against the per-process limit and as only a single page +in the system limit. diff -uN src/sys/kern/link_elf.c.orig src/sys/kern/link_elf.c --- /usr/src/sys/kern/link_elf.c.orig Fri Jun 27 07:47:39 2003 +++ /usr/src/sys/kern/link_elf.c Sat Jul 19 00:52:04 2003 @@ -744,7 +744,7 @@ vm_map_wire(kernel_map, (vm_offset_t) segbase, (vm_offset_t) segbase + segs[i]->p_memsz, - FALSE); + VM_MAP_WIRE_SYSTEM); #endif } diff -uN src/sys/sys/mman.h.orig src/sys/sys/mman.h --- /usr/src/sys/sys/mman.h.orig Sat Jul 19 00:54:26 2003 +++ /usr/src/sys/sys/mman.h Sat Jul 19 00:53:13 2003 @@ -178,6 +178,8 @@ int munlock(const void *, size_t); int munmap(void *, size_t); #if __POSIX_VISIBLE >= 199309 +int mlockall(int); +int munlockall(void); int shm_open(const char *, int, mode_t); int shm_unlink(const char *); #endif diff -uN src/sys/vm/vm_contig.c.orig src/sys/vm/vm_contig.c --- /usr/src/sys/vm/vm_contig.c.orig Fri Jun 27 07:48:49 2003 +++ /usr/src/sys/vm/vm_contig.c Sat Jul 19 00:52:04 2003 @@ -254,7 +254,7 @@ tmp_addr += PAGE_SIZE; } VM_OBJECT_UNLOCK(kernel_object); - vm_map_wire(map, addr, addr + size, FALSE); + vm_map_wire(map, addr, addr + size, VM_MAP_WIRE_SYSTEM); splx(s); return ((void *)addr); diff -uN src/sys/vm/vm_glue.c.orig src/sys/vm/vm_glue.c --- /usr/src/sys/vm/vm_glue.c.orig Fri Jun 27 07:49:23 2003 +++ /usr/src/sys/vm/vm_glue.c Sat Jul 19 00:52:04 2003 @@ -186,7 +186,7 @@ { vm_map_wire(&curproc->p_vmspace->vm_map, trunc_page((vm_offset_t)addr), - round_page((vm_offset_t)addr + len), FALSE); + round_page((vm_offset_t)addr + len), VM_MAP_WIRE_SYSTEM); } /* @@ -200,7 +200,7 @@ vm_map_unwire(&curproc->p_vmspace->vm_map, trunc_page((vm_offset_t)addr), - round_page((vm_offset_t)addr + len), FALSE); + round_page((vm_offset_t)addr + len), VM_MAP_WIRE_SYSTEM); } /* diff -uN src/sys/vm/vm_kern.c.orig src/sys/vm/vm_kern.c --- /usr/src/sys/vm/vm_kern.c.orig Fri Jun 27 07:50:53 2003 +++ /usr/src/sys/vm/vm_kern.c Sat Jul 19 00:52:04 2003 @@ -210,7 +210,7 @@ /* * And finally, mark the data as non-pageable. */ - (void) vm_map_wire(map, addr, addr + size, FALSE); + (void) vm_map_wire(map, addr, addr + size, VM_MAP_WIRE_SYSTEM); return (addr); } diff -uN src/sys/vm/vm_map.c.orig src/sys/vm/vm_map.c --- /usr/src/sys/vm/vm_map.c.orig Wed Jun 4 11:01:59 2003 +++ /usr/src/sys/vm/vm_map.c Sat Jul 19 00:52:04 2003 @@ -1559,19 +1559,32 @@ */ int vm_map_unwire(vm_map_t map, vm_offset_t start, vm_offset_t end, - boolean_t user_unwire) + int flags) { vm_map_entry_t entry, first_entry, tmp_entry; vm_offset_t saved_start; unsigned int last_timestamp; int rv; boolean_t need_wakeup, result; + boolean_t user_unwire; + + user_unwire = (flags & VM_MAP_WIRE_USER) ? TRUE : FALSE; vm_map_lock(map); VM_MAP_RANGE_CHECK(map, start, end); - if (!vm_map_lookup_entry(map, start, &first_entry)) { - vm_map_unlock(map); - return (KERN_INVALID_ADDRESS); + if (start != (vm_offset_t) 0) { + /* operating on arbitrary range */ + if (!vm_map_lookup_entry(map, start, &first_entry)) { + vm_map_unlock(map); + return (KERN_INVALID_ADDRESS); + } + } else { + /* operating on entire process space */ + if (map->header.next == NULL) { + vm_map_unlock(map); + return (KERN_INVALID_ADDRESS); + } + first_entry = map->header.next; } last_timestamp = map->timestamp; entry = first_entry; @@ -1627,9 +1640,11 @@ entry->eflags |= MAP_ENTRY_IN_TRANSITION; /* * Check the map for holes in the specified region. + * If VM_MAP_WIRE_NONCONTIG was specified, skip this check. */ - if (entry->end < end && (entry->next == &map->header || - entry->next->start > entry->end)) { + if (((flags & VM_MAP_WIRE_NONCONTIG) == 0) && + (entry->end < end && (entry->next == &map->header || + entry->next->start > entry->end))) { end = entry->end; rv = KERN_INVALID_ADDRESS; goto done; @@ -1688,19 +1703,25 @@ */ int vm_map_wire(vm_map_t map, vm_offset_t start, vm_offset_t end, - boolean_t user_wire) + int flags) { vm_map_entry_t entry, first_entry, tmp_entry; vm_offset_t saved_end, saved_start; unsigned int last_timestamp; int rv; boolean_t need_wakeup, result; + boolean_t user_wire; + + user_wire = (flags & VM_MAP_WIRE_USER) ? TRUE : FALSE; vm_map_lock(map); VM_MAP_RANGE_CHECK(map, start, end); if (!vm_map_lookup_entry(map, start, &first_entry)) { - vm_map_unlock(map); - return (KERN_INVALID_ADDRESS); + if ((flags & VM_MAP_WIRE_NONCONTIG) == 0) { + vm_map_unlock(map); + return (KERN_INVALID_ADDRESS); + } else + first_entry = map->header.next; } last_timestamp = map->timestamp; entry = first_entry; @@ -1811,9 +1832,11 @@ } /* * Check the map for holes in the specified region. + * If VM_MAP_WIRE_NONCONTIG was specified, skip this check. */ - if (entry->end < end && (entry->next == &map->header || - entry->next->start > entry->end)) { + if (((flags & VM_MAP_WIRE_NONCONTIG) == 0) && + (entry->end < end && (entry->next == &map->header || + entry->next->start > entry->end))) { end = entry->end; rv = KERN_INVALID_ADDRESS; goto done; @@ -2351,6 +2374,10 @@ new_map = &vm2->vm_map; /* XXX */ new_map->timestamp = 1; + /* Do not inherit the MAP_WIREFUTURE property. */ + if ((new_map->flags & MAP_WIREFUTURE) == MAP_WIREFUTURE) + new_map->flags &= ~MAP_WIREFUTURE; + old_entry = old_map->header.next; while (old_entry != &old_map->header) { @@ -2660,6 +2687,14 @@ } vm_map_unlock(map); + /* + * Heed the MAP_WIREFUTURE flag if it was set for this process. + */ + if (rv == KERN_SUCCESS && (map->flags & MAP_WIREFUTURE)) + vm_map_wire(map, addr, stack_entry->start, + (p->p_flag & P_SYSTEM ? VM_MAP_WIRE_SYSTEM : + VM_MAP_WIRE_USER)); + return (rv); } diff -uN src/sys/vm/vm_map.h.orig src/sys/vm/vm_map.h --- /usr/src/sys/vm/vm_map.h.orig Wed Jun 4 13:45:35 2003 +++ /usr/src/sys/vm/vm_map.h Sat Jul 19 00:52:04 2003 @@ -81,6 +81,7 @@ * vm_map_entry_t an entry in an address map. */ +typedef u_int vm_flags_t; typedef u_int vm_eflags_t; /* @@ -177,8 +178,11 @@ pmap_t pmap; /* (c) Physical map */ #define min_offset header.start /* (c) */ #define max_offset header.end /* (c) */ + vm_flags_t flags; /* flags for this vm_map */ }; +#define MAP_WIREFUTURE 0x0001 /* wire all future pages */ + #ifdef _KERNEL static __inline vm_offset_t vm_map_max(vm_map_t map) @@ -197,6 +201,12 @@ { return (map->pmap); } + +static __inline void +vm_map_modflags(vm_map_t map, vm_flags_t set, vm_flags_t clear) +{ + map->flags = (map->flags | set) & ~clear; +} #endif /* _KERNEL */ /* @@ -296,6 +306,13 @@ #define VM_FAULT_WIRE_MASK (VM_FAULT_CHANGE_WIRING|VM_FAULT_USER_WIRE) #define VM_FAULT_DIRTY 8 /* Dirty the page */ +/* + * vm_map_[un]wire option flags + */ +#define VM_MAP_WIRE_SYSTEM 0 /* wiring in a kernel map */ +#define VM_MAP_WIRE_USER 1 /* wiring in a user map */ +#define VM_MAP_WIRE_NONCONTIG 2 /* requested region has holes */ + #ifdef _KERNEL boolean_t vm_map_check_protection (vm_map_t, vm_offset_t, vm_offset_t, vm_prot_t); struct pmap; @@ -321,9 +338,9 @@ int vm_map_stack (vm_map_t, vm_offset_t, vm_size_t, vm_prot_t, vm_prot_t, int); int vm_map_growstack (struct proc *p, vm_offset_t addr); int vm_map_unwire(vm_map_t map, vm_offset_t start, vm_offset_t end, - boolean_t user_unwire); + int flags); int vm_map_wire(vm_map_t map, vm_offset_t start, vm_offset_t end, - boolean_t user_wire); + int flags); int vmspace_swap_count (struct vmspace *vmspace); #endif /* _KERNEL */ #endif /* _VM_MAP_ */ diff -uN src/sys/vm/vm_mmap.c.orig src/sys/vm/vm_mmap.c --- /usr/src/sys/vm/vm_mmap.c.orig Fri Jun 27 08:32:54 2003 +++ /usr/src/sys/vm/vm_mmap.c Sat Jul 19 00:52:04 2003 @@ -1039,7 +1039,7 @@ #endif error = vm_map_wire(&td->td_proc->p_vmspace->vm_map, addr, - addr + size, TRUE); + addr + size, VM_MAP_WIRE_USER); return (error == KERN_SUCCESS ? 0 : ENOMEM); } @@ -1057,14 +1057,55 @@ struct thread *td; struct mlockall_args *uap; { - /* mtx_lock(&Giant); */ - /* mtx_unlock(&Giant); */ - return 0; + int error; + vm_map_t map; + + error = 0; + map = &td->td_proc->p_vmspace->vm_map; + + if ((uap->how == 0) || ((uap->how & ~(MCL_CURRENT|MCL_FUTURE)) != 0)) + return (EINVAL); + +#ifdef pmap_wired_count + /* + * If wiring all pages in the process would cause it to exceed + * a hard resource limit, return ENOMEM. + */ + if (map->size - ptoa(pmap_wired_count(vm_map_pmap(map)) > + td->td_proc->p_rlimit[RLIMIT_MEMLOCK].rlim_cur)) + return (ENOMEM); +#else + error = suser(td); + if (error) + return (error); +#endif + + if (uap->how & MCL_FUTURE) { + vm_map_lock(map); + vm_map_modflags(map, MAP_WIREFUTURE, 0); + vm_map_unlock(map); + error = 0; + } + + if (uap->how & MCL_CURRENT) { + /* + * P1003.1-2001 actually mandates that all currently + * mapped pages will be memory resident and locked (wired). + * This implies that we need to prefault. However, the act + * of wiring the page will incur a call to vm_fault_wire(), + * which will fault in the newly wired page. + */ + error = vm_map_wire(map, vm_map_min(map), vm_map_max(map), + VM_MAP_WIRE_USER|VM_MAP_WIRE_NONCONTIG); + error = (error == KERN_SUCCESS ? 0 : EAGAIN); + } + + return (error); } #ifndef _SYS_SYSPROTO_H_ struct munlockall_args { - int how; + register_t dummy; }; #endif @@ -1076,9 +1117,27 @@ struct thread *td; struct munlockall_args *uap; { - /* mtx_lock(&Giant); */ - /* mtx_unlock(&Giant); */ - return 0; + int error; + vm_map_t map; + +#ifndef pmap_wired_count + error = suser(td); + if (error) + return (error); +#endif + error = 0; + map = &td->td_proc->p_vmspace->vm_map; + + /* Clear the MAP_WIREFUTURE flag from this vm_map. */ + vm_map_lock(map); + vm_map_modflags(map, 0, MAP_WIREFUTURE); + vm_map_unlock(map); + + /* Forcibly unwire all pages. */ + error = vm_map_unwire(map, vm_map_min(map), vm_map_max(map), + VM_MAP_WIRE_USER|VM_MAP_WIRE_NONCONTIG); + + return (error); } #ifndef _SYS_SYSPROTO_H_ @@ -1118,7 +1177,7 @@ #endif error = vm_map_unwire(&td->td_proc->p_vmspace->vm_map, addr, - addr + size, TRUE); + addr + size, VM_MAP_WIRE_USER); return (error == KERN_SUCCESS ? 0 : ENOMEM); } @@ -1275,6 +1334,14 @@ if (rv != KERN_SUCCESS) (void) vm_map_remove(map, *addr, *addr + size); } + + /* + * If the process has requested that all future mappings + * be wired, then heed this. + */ + if ((rv == KERN_SUCCESS) && (map->flags & MAP_WIREFUTURE)) + vm_map_wire(map, *addr, *addr + size, VM_MAP_WIRE_USER); + switch (rv) { case KERN_SUCCESS: return (0); diff -uN src/sys/vm/vm_unix.c.orig src/sys/vm/vm_unix.c --- /usr/src/sys/vm/vm_unix.c.orig Wed Jun 4 22:40:38 2003 +++ /usr/src/sys/vm/vm_unix.c Sat Jul 19 00:52:04 2003 @@ -77,6 +77,9 @@ vm_offset_t new, old, base; int rv; int error = 0; + boolean_t do_map_wirefuture; + + do_map_wirefuture = FALSE; new = round_page((vm_offset_t)uap->nsize); vm_map_lock(&vm->vm_map); @@ -119,6 +122,21 @@ goto done; } vm->vm_dsize += btoc(new - old); + /* + * Handle the MAP_WIREFUTURE case for legacy applications, + * by marking the newly mapped range of pages as wired. + * + * We are not required to perform a corresponding + * vm_map_unwire() before vm_map_delete() below, as + * it will forcibly unwire the pages in the range. + * + * XXX If the pages cannot be wired, no error is returned. + */ + if ((vm->vm_map.flags & MAP_WIREFUTURE) == MAP_WIREFUTURE) { + if (bootverbose) + printf("obreak: MAP_WIREFUTURE set\n"); + do_map_wirefuture = TRUE; + } } else if (new < old) { rv = vm_map_delete(&vm->vm_map, new, old); if (rv != KERN_SUCCESS) { @@ -129,6 +147,10 @@ } done: vm_map_unlock(&vm->vm_map); + + if (do_map_wirefuture) + (void) vm_map_wire(&vm->vm_map, old, new, VM_MAP_WIRE_USER); + return (error); } --OgqxwSJOaUobr8KG--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20030719111952.GB12995>