summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Martitz <kugel@rockbox.org>2012-01-13 09:47:01 +0100
committerThomas Martitz <kugel@rockbox.org>2012-01-21 18:39:19 +0100
commit34b0311d0eb906bd801cc1e9a329ed211b81496f (patch)
treeb76d82b8ecb94aab048c58d2b6f3c23b57e15b7a
parent109084d5cbaeee26373ecf1b765d9507ccbbe63e (diff)
downloadrockbox-34b0311d0eb906bd801cc1e9a329ed211b81496f.tar.gz
rockbox-34b0311d0eb906bd801cc1e9a329ed211b81496f.zip
hosted/pcm/alsa: Use alternate signal stack for the async callback.
Signals are by default executed on the user stack, i.e. the stack of the currently active thread. This has two problems: 1) The stack size of the current stack is likely insufficient (unless using sigaltstack threads) because our stack sizes are normally below MINSIGSTKSIZE which is needed to deliver a signal. 2) Some of our asm code does nasty tricks with the stack pointer. When a signal comes in during this bad things can happen, e.g. random memory being overwritten or simply a crash. Using a well defined stack fixes this. This is comparable with the separate irq stack on native targets.
-rw-r--r--firmware/target/hosted/pcm-alsa.c31
1 files changed, 31 insertions, 0 deletions
diff --git a/firmware/target/hosted/pcm-alsa.c b/firmware/target/hosted/pcm-alsa.c
index 7daf485f18..02cb34ea5b 100644
--- a/firmware/target/hosted/pcm-alsa.c
+++ b/firmware/target/hosted/pcm-alsa.c
@@ -27,6 +27,11 @@
27 * This driver uses the so-called unsafe async callback method and hardcoded device 27 * This driver uses the so-called unsafe async callback method and hardcoded device
28 * names. It fails when the audio device is busy by other apps. 28 * names. It fails when the audio device is busy by other apps.
29 * 29 *
30 * To make the async callback safer, an alternative stack is installed, since
31 * it's run from a signal hanlder (which otherwise uses the user stack). If
32 * tick tasks are run from a signal handler too, please install
33 * an alternative stack for it too.
34 *
30 * TODO: Rewrite this to do it properly with multithreading 35 * TODO: Rewrite this to do it properly with multithreading
31 * 36 *
32 * Alternatively, a version using polling in a tick task is provided. While 37 * Alternatively, a version using polling in a tick task is provided. While
@@ -76,6 +81,7 @@ static size_t pcm_size = 0;
76#ifdef USE_ASYNC_CALLBACK 81#ifdef USE_ASYNC_CALLBACK
77static snd_async_handler_t *ahandler; 82static snd_async_handler_t *ahandler;
78static pthread_mutex_t pcm_mtx; 83static pthread_mutex_t pcm_mtx;
84static char signal_stack[SIGSTKSZ];
79#else 85#else
80static int recursion; 86static int recursion;
81#endif 87#endif
@@ -271,12 +277,37 @@ static int async_rw(snd_pcm_t *handle)
271 short *samples; 277 short *samples;
272 278
273#ifdef USE_ASYNC_CALLBACK 279#ifdef USE_ASYNC_CALLBACK
280 /* assign alternative stack for the signal handlers */
281 stack_t ss = {
282 .ss_sp = signal_stack,
283 .ss_size = sizeof(signal_stack),
284 .ss_flags = 0
285 };
286 struct sigaction sa;
287
288 err = sigaltstack(&ss, NULL);
289 if (err < 0)
290 {
291 DEBUGF("Unable to install alternative signal stack: %s", strerror(err));
292 return err;
293 }
294
274 err = snd_async_add_pcm_handler(&ahandler, handle, async_callback, NULL); 295 err = snd_async_add_pcm_handler(&ahandler, handle, async_callback, NULL);
275 if (err < 0) 296 if (err < 0)
276 { 297 {
277 DEBUGF("Unable to register async handler: %s\n", snd_strerror(err)); 298 DEBUGF("Unable to register async handler: %s\n", snd_strerror(err));
278 return err; 299 return err;
279 } 300 }
301
302 /* only modify the stack the handler runs on */
303 sigaction(SIGIO, NULL, &sa);
304 sa.sa_flags |= SA_ONSTACK;
305 err = sigaction(SIGIO, &sa, NULL);
306 if (err < 0)
307 {
308 DEBUGF("Unable to install alternative signal stack: %s", strerror(err));
309 return err;
310 }
280#endif 311#endif
281 312
282 /* fill buffer with silence to initiate playback without noisy click */ 313 /* fill buffer with silence to initiate playback without noisy click */