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;

Reply via email to