Recently, it was reported to me that you could provoke a double fault

panic with the NDISulator if you did "ifconfig ndis0 10.0.0.1/24,"
whereas "ifconfig ndis0 10.0.0.1/24 up" worked fine. The double fault
was caused by the ifconfig thread running out of kernel stack space.
(This was partly due to the NDIsulator using a couple of big buffers on
the stack, but even after fixing that the double fault persisted.)

It turns out that ndis_init() is called in both cases, but in the first
case the code path passes through ieee80211_ioctl(), and it turns out
ieee80211_ioctl() consumes a whopping 2400 bytes of stack space.
Apparently, gcc -O2 causes the ieee80211_ioctl_get80211() routine to
be inlined into ieee80211_ioctl(), and for some reason which I do not
fully understand, this causes ieee80211_ioctl() to consume an extra 2K
of stack space.

To prevent this overly agressive optimization, ieee80211_ioctl_get80211()
is now declared with __attribute__ ((noinline)). With this change,
ieee80211_ioctl() now only reserves about 200 bytes of stack instead of 2400.
This commit is contained in:
Bill Paul 2005-03-03 17:35:05 +00:00
parent 9c6519b0a2
commit c788ca3e3c

View File

@ -1224,6 +1224,25 @@ ieee80211_ioctl_getwmeparam(struct ieee80211com *ic, struct ieee80211req *ireq)
return 0;
}
/*
* When building the kernel with -O2 on the i386 architecture, gcc
* seems to want to inline this function into ieee80211_ioctl()
* (which is the only routine that calls it). When this happens,
* ieee80211_ioctl() ends up consuming an additional 2K of stack
* space. (Exactly why it needs so much is unclear.) The problem
* is that it's possible for ieee80211_ioctl() to invoke other
* routines (including driver init functions) which could then find
* themselves perilously close to exhausting the stack.
*
* To avoid this, we deliberately prevent gcc from inlining this
* routine. Another way to avoid this is to use less agressive
* optimization when compiling this file (i.e. -O instead of -O2)
* but special-casing the compilation of this one module in the
* build system would be awkward.
*/
#ifdef __GNUC__
__attribute__ ((noinline))
#endif
static int
ieee80211_ioctl_get80211(struct ieee80211com *ic, u_long cmd, struct ieee80211req *ireq)
{