Subject: RE: NetBSD1.6 UVM problem?
To: 'Chuck Silvers' <chuq@chuq.com>
From: Sylvain Fontaine <sfontaine@hyperchip.com>
List: tech-kern
Date: 12/09/2002 15:41:08
This message is in MIME format. Since your mail reader does not understand
this format, some or all of this message may not be legible.

------_=_NextPart_001_01C29FC3.4D8535D0
Content-Type: text/plain;
	charset="iso-8859-1"

Thanks Chuq,
This fix does solve part of the problem, but now 
I run out of anon memory...

void
uvm_anon_init()
{
	int nanon = uvmexp.free - (uvmexp.free / 16); /* XXXCDC ??? */
...
}

Is this 1/16 necessary... ????  If I anon_init all uvmesp.free,
will I encounter some problems?  What's the drawback ??

Sylvain

-----Original Message-----
From: Chuck Silvers [mailto:chuq@chuq.com]
Sent: Sunday, December 08, 2002 2:03 PM
To: Sylvain Fontaine
Cc: 'tech-kern@netbsd.org'
Subject: Re: NetBSD1.6 UVM problem?


hi,

yes, the heuristic for determining when to start killing processes
when no swap is available doesn't work so well when there's no swap
configured.  in this case, it would be useful to count RAM that isn't
reserved for other usage types as potentially available for swap-backed
allocation.   all the places in uvm_fault() that return ENOMEM currently
use "uvmexp.swpgonly == uvmexp.swpages" as the indicator that sleeping
won't free up any more memory that could be used for anons, but when
there's no swap then both sides of that comparison are always zero.

we could replace that with something more like

	int t;

	t = uvmexp.active + uvmexp.inactive + uvmexp.free;
	if (uvmexp.swpgonly == uvmexp.swpages &&
            uvmexp.filepages <= ((t * uvmexp.filemin) >> 8) &&
	    uvmexp.execpages <= ((t * uvmexp.execmin) >> 8)) {
		return ENOMEM;
	}

(and yea, I should make some macros for doing the fixed-point math.)
this means that we will only start killing processes when swap is full
and the file and exec pages have been reduced to their minimum levels.

does that do anything useful for you?

-Chuck


On Fri, Dec 06, 2002 at 11:35:13AM -0500, Sylvain Fontaine wrote:
> 
> I found a behavior with the UVM that seems to be wrong.
> My system has no swap space. 1G of RAM.
> 
> Here's what I see:
> - Create a file of 100M on a MFS of 100M.  Then 200M are removed from
free,
> 100M active, 100M file.
>   I'm left with about 730M of free mem now, but with 100M file memory
> available when needed.
> - I start a program that calloc (not malloc) 800M.  I expect file memory
to
> be returned to me.
>   The test program does callocation by 100M slices.
> - The page deamon does not react until its free_target is not under.
About
> ~~500k.
> - When the page deamon finds the free_target not to be met, it starts
> recovering pages, 
>   but there's a race condition freeing/allocating and my test app wins...
> resulting in faulting
>   and being killed by the UVM when uvm_fault returns ENOMEM.  
> 
> 
> I found two solutions:
> 1) In this condition, when I know there is still memory I can retrieve
from
> file memory,
>     I call uvm_wait, and tell the pagedeamon to overlook the free_target
and
> to free 
>     some pages because I need some, even if the free_target is met.
> 2) Increraese the free target to 1/20 of my memory ~50M... This way the
race
> begins sooner
>     And the pagedeamon wins.
> 
> Sylvain

------_=_NextPart_001_01C29FC3.4D8535D0
Content-Type: text/html;
	charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV=3D"Content-Type" CONTENT=3D"text/html; =
charset=3Diso-8859-1">
<META NAME=3D"Generator" CONTENT=3D"MS Exchange Server version =
5.5.2653.12">
<TITLE>RE: NetBSD1.6 UVM problem?</TITLE>
</HEAD>
<BODY>

<P><FONT SIZE=3D2>Thanks Chuq,</FONT>
<BR><FONT SIZE=3D2>This fix does solve part of the problem, but now =
</FONT>
<BR><FONT SIZE=3D2>I run out of anon memory...</FONT>
</P>

<P><FONT SIZE=3D2>void</FONT>
<BR><FONT SIZE=3D2>uvm_anon_init()</FONT>
<BR><FONT SIZE=3D2>{</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT SIZE=3D2>int nanon =
=3D uvmexp.free - (uvmexp.free / 16); /* XXXCDC ??? */</FONT>
<BR><FONT SIZE=3D2>...</FONT>
<BR><FONT SIZE=3D2>}</FONT>
</P>

<P><FONT SIZE=3D2>Is this 1/16 necessary... ????&nbsp; If I anon_init =
all uvmesp.free,</FONT>
<BR><FONT SIZE=3D2>will I encounter some problems?&nbsp; What's the =
drawback ??</FONT>
</P>

<P><FONT SIZE=3D2>Sylvain</FONT>
</P>

<P><FONT SIZE=3D2>-----Original Message-----</FONT>
<BR><FONT SIZE=3D2>From: Chuck Silvers [<A =
HREF=3D"mailto:chuq@chuq.com">mailto:chuq@chuq.com</A>]</FONT>
<BR><FONT SIZE=3D2>Sent: Sunday, December 08, 2002 2:03 PM</FONT>
<BR><FONT SIZE=3D2>To: Sylvain Fontaine</FONT>
<BR><FONT SIZE=3D2>Cc: 'tech-kern@netbsd.org'</FONT>
<BR><FONT SIZE=3D2>Subject: Re: NetBSD1.6 UVM problem?</FONT>
</P>
<BR>

<P><FONT SIZE=3D2>hi,</FONT>
</P>

<P><FONT SIZE=3D2>yes, the heuristic for determining when to start =
killing processes</FONT>
<BR><FONT SIZE=3D2>when no swap is available doesn't work so well when =
there's no swap</FONT>
<BR><FONT SIZE=3D2>configured.&nbsp; in this case, it would be useful =
to count RAM that isn't</FONT>
<BR><FONT SIZE=3D2>reserved for other usage types as potentially =
available for swap-backed</FONT>
<BR><FONT SIZE=3D2>allocation.&nbsp;&nbsp; all the places in =
uvm_fault() that return ENOMEM currently</FONT>
<BR><FONT SIZE=3D2>use &quot;uvmexp.swpgonly =3D=3D =
uvmexp.swpages&quot; as the indicator that sleeping</FONT>
<BR><FONT SIZE=3D2>won't free up any more memory that could be used for =
anons, but when</FONT>
<BR><FONT SIZE=3D2>there's no swap then both sides of that comparison =
are always zero.</FONT>
</P>

<P><FONT SIZE=3D2>we could replace that with something more like</FONT>
</P>

<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT SIZE=3D2>int =
t;</FONT>
</P>

<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT SIZE=3D2>t =3D =
uvmexp.active + uvmexp.inactive + uvmexp.free;</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT SIZE=3D2>if =
(uvmexp.swpgonly =3D=3D uvmexp.swpages &amp;&amp;</FONT>
<BR><FONT =
SIZE=3D2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nb=
sp; uvmexp.filepages &lt;=3D ((t * uvmexp.filemin) &gt;&gt; 8) =
&amp;&amp;</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT =
SIZE=3D2>&nbsp;&nbsp;&nbsp; uvmexp.execpages &lt;=3D ((t * =
uvmexp.execmin) &gt;&gt; 8)) {</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT SIZE=3D2>return =
ENOMEM;</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT SIZE=3D2>}</FONT>
</P>

<P><FONT SIZE=3D2>(and yea, I should make some macros for doing the =
fixed-point math.)</FONT>
<BR><FONT SIZE=3D2>this means that we will only start killing processes =
when swap is full</FONT>
<BR><FONT SIZE=3D2>and the file and exec pages have been reduced to =
their minimum levels.</FONT>
</P>

<P><FONT SIZE=3D2>does that do anything useful for you?</FONT>
</P>

<P><FONT SIZE=3D2>-Chuck</FONT>
</P>
<BR>

<P><FONT SIZE=3D2>On Fri, Dec 06, 2002 at 11:35:13AM -0500, Sylvain =
Fontaine wrote:</FONT>
<BR><FONT SIZE=3D2>&gt; </FONT>
<BR><FONT SIZE=3D2>&gt; I found a behavior with the UVM that seems to =
be wrong.</FONT>
<BR><FONT SIZE=3D2>&gt; My system has no swap space. 1G of RAM.</FONT>
<BR><FONT SIZE=3D2>&gt; </FONT>
<BR><FONT SIZE=3D2>&gt; Here's what I see:</FONT>
<BR><FONT SIZE=3D2>&gt; - Create a file of 100M on a MFS of 100M.&nbsp; =
Then 200M are removed from free,</FONT>
<BR><FONT SIZE=3D2>&gt; 100M active, 100M file.</FONT>
<BR><FONT SIZE=3D2>&gt;&nbsp;&nbsp; I'm left with about 730M of free =
mem now, but with 100M file memory</FONT>
<BR><FONT SIZE=3D2>&gt; available when needed.</FONT>
<BR><FONT SIZE=3D2>&gt; - I start a program that calloc (not malloc) =
800M.&nbsp; I expect file memory to</FONT>
<BR><FONT SIZE=3D2>&gt; be returned to me.</FONT>
<BR><FONT SIZE=3D2>&gt;&nbsp;&nbsp; The test program does callocation =
by 100M slices.</FONT>
<BR><FONT SIZE=3D2>&gt; - The page deamon does not react until its =
free_target is not under.&nbsp; About</FONT>
<BR><FONT SIZE=3D2>&gt; ~~500k.</FONT>
<BR><FONT SIZE=3D2>&gt; - When the page deamon finds the free_target =
not to be met, it starts</FONT>
<BR><FONT SIZE=3D2>&gt; recovering pages, </FONT>
<BR><FONT SIZE=3D2>&gt;&nbsp;&nbsp; but there's a race condition =
freeing/allocating and my test app wins...</FONT>
<BR><FONT SIZE=3D2>&gt; resulting in faulting</FONT>
<BR><FONT SIZE=3D2>&gt;&nbsp;&nbsp; and being killed by the UVM when =
uvm_fault returns ENOMEM.&nbsp; </FONT>
<BR><FONT SIZE=3D2>&gt; </FONT>
<BR><FONT SIZE=3D2>&gt; </FONT>
<BR><FONT SIZE=3D2>&gt; I found two solutions:</FONT>
<BR><FONT SIZE=3D2>&gt; 1) In this condition, when I know there is =
still memory I can retrieve from</FONT>
<BR><FONT SIZE=3D2>&gt; file memory,</FONT>
<BR><FONT SIZE=3D2>&gt;&nbsp;&nbsp;&nbsp;&nbsp; I call uvm_wait, and =
tell the pagedeamon to overlook the free_target and</FONT>
<BR><FONT SIZE=3D2>&gt; to free </FONT>
<BR><FONT SIZE=3D2>&gt;&nbsp;&nbsp;&nbsp;&nbsp; some pages because I =
need some, even if the free_target is met.</FONT>
<BR><FONT SIZE=3D2>&gt; 2) Increraese the free target to 1/20 of my =
memory ~50M... This way the race</FONT>
<BR><FONT SIZE=3D2>&gt; begins sooner</FONT>
<BR><FONT SIZE=3D2>&gt;&nbsp;&nbsp;&nbsp;&nbsp; And the pagedeamon =
wins.</FONT>
<BR><FONT SIZE=3D2>&gt; </FONT>
<BR><FONT SIZE=3D2>&gt; Sylvain</FONT>
</P>

</BODY>
</HTML>
------_=_NextPart_001_01C29FC3.4D8535D0--