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>