We compile out kernel with -Wframe-larger-than=2047 to make sure we
don't write stupid code that blows the kernel stack. Now clang thinks
it is clever and considers it a good idea to inline functions when the
function and the caller live in the same source file. A particular
case where this happens is in audio.c, where wskbd_initmute() gets
inlined into wskbd_initvol(). And this inlining pushes things over
the stack limit, since struct mixer_devinfo is quite large and it now
needs three copies of that structure.
Diff below is a possible way to fix this. But in a way we're cheating
here since we'll still consume more than 2047 bytes of stack space
when we descend into wskbd_initmute(). So perhaps we should rewrite
this code to dynamically allocate the mixer_devinfo structs?
Index: sys/cdefs.h
===================================================================
RCS file: /cvs/src/sys/sys/cdefs.h,v
retrieving revision 1.39
diff -u -p -r1.39 cdefs.h
--- sys/cdefs.h 18 Apr 2014 11:51:17 -0000 1.39
+++ sys/cdefs.h 30 Sep 2016 14:22:28 -0000
@@ -160,6 +160,12 @@
#define __only_inline static __inline
#endif
+#if __GNUC_PREREQ__(3, 0)
+#define __noinline __attribute__((__noinline__))
+#else
+#define __noinline
+#endif
+
/*
* GNU C version 2.96 adds explicit branch prediction so that
* the CPU back-end can hint the processor and also so that
Index: dev/audio.c
===================================================================
RCS file: /cvs/src/sys/dev/audio.c,v
retrieving revision 1.153
diff -u -p -r1.153 audio.c
--- dev/audio.c 19 Sep 2016 06:46:43 -0000 1.153
+++ dev/audio.c 30 Sep 2016 14:22:28 -0000
@@ -1783,7 +1783,7 @@ audiopoll(dev_t dev, int events, struct
}
#if NWSKBD > 0
-int
+__noinline int
wskbd_initmute(struct audio_softc *sc, struct mixer_devinfo *vol)
{
struct mixer_devinfo mi;