Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 28 Feb 1999 15:23:00 -0600
From:      "Richard Seaman, Jr." <dick@tar.com>
To:        Bruce Evans <bde@zeta.org.au>
Cc:        current@FreeBSD.ORG, pangolin@home.com, Julian Elischer <julian@whistle.com>
Subject:   Re: lockmgr panic with mmap()
Message-ID:  <19990228152300.A467@tar.com>
In-Reply-To: <199902281252.XAA24877@godzilla.zeta.org.au>; from Bruce Evans on Sun, Feb 28, 1999 at 11:52:57PM %2B1100
References:  <199902281252.XAA24877@godzilla.zeta.org.au>

next in thread | previous in thread | raw e-mail | index | archive | help

--sm4nu43k4a2Rpi4c
Content-Type: text/plain; charset=us-ascii

On Sun, Feb 28, 1999 at 11:52:57PM +1100, Bruce Evans wrote:

[snip]

> Here is a simpler example.
> 
> ---
> #include <sys/param.h>
> #include <sys/mman.h>
> 
> #include <err.h>
> #include <stdlib.h>
> 
> #define	SIZE		(32 * 1024 * 1024)
> 
> int
> main(void)
> {
> 	void *p;
> 	char vec[SIZE / PAGE_SIZE];
> 
> 	p = malloc(SIZE);
> 	if (mincore(p, SIZE, vec) != 0)
> 		err(1, "mincore");
> 	return (0);
> }
> ---
> 
> mincore() locks the vmspace map, and initialises vec[] a byte at a time
> using subyte().  When vec[] is sufficiently large, it is not all in core
> initially and a page fault occurs in subyte().  The new stack growing
> code locks the vmspace map early and panics.

It appears to me the potential for deadlock exists in the old grow code
too, but is less likely.  

I've attached a patch that addresses the issue, though there is a
question if this is the best solution.

With the old grow code, if the map lock is already held, one of the
following will be true
a) the grow code doesn't get executed because the va is not
   in the stack region, which is equivalent to grow returning
   success
b) the grow code returns success because there's no need to
   grow the region because the va is aready in the mapped region.
c) the grow code returns false if the va is within the stack
   region and there's no room left, which normally will result
   in a SIGSEGV
d) the grow code attempts to grow the stack via vm_map_find and
   will then deadlock at the vm_map_lock call

With this patch, if the map lock is already held, by always returning
success, cases a) and b) will be the same as before.  For case c)
the code will attempt to continue to execute, generally calling
vm_fault, which should, I think, generate a SIGSEGV, essentially
the same result as the old code, but via a different path.  Case d)
will now continue executing in a manner equivalent to the new case c).

The question is whether there is a way to do the autogrow function if
the map lock is already held.




-- 
Richard Seaman, Jr.           email: dick@tar.com
5182 N. Maple Lane            phone: 414-367-5450
Chenequa WI 53058             fax:   414-367-5850
--sm4nu43k4a2Rpi4c
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=vmfix

Index: vm_map.c
===================================================================
RCS file: /home/ncvs/src/sys/vm/vm_map.c,v
retrieving revision 1.152
diff -c -r1.152 vm_map.c
*** vm_map.c	1999/02/24 21:26:25	1.152
--- vm_map.c	1999/02/28 20:41:25
***************
*** 663,668 ****
--- 663,674 ----
  	int      rv;
  	int      is_procstack = 0;
  
+ 
+ #define	vm_map_locked(map) lockstatus(&(map)->lock)
+ 
+ 	if (vm_map_locked(map))
+ 		return (KERN_SUCCESS);
+ 
  	vm_map_lock(map);
  
  	/* If addr is already in the entry range, no need to grow.*/

--sm4nu43k4a2Rpi4c--


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?19990228152300.A467>