Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 19 Jul 2003 04:30:16 -0700 (PDT)
From:      Bruce M Simpson <bms@spc.org>
To:        freebsd-standards@FreeBSD.org
Subject:   Re: standards/54223: [PATCH] Add mlockall(), munlockall() syscalls to -CURRENT
Message-ID:  <200307191130.h6JBUGMp098758@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
The following reply was made to PR standards/54223; it has been noted by GNATS.

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
Date: Sat, 19 Jul 2003 12:19:52 +0100

 --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?200307191130.h6JBUGMp098758>