diff options
Diffstat (limited to 'firmware/target/hosted')
-rw-r--r-- | firmware/target/hosted/pcm-alsa.c | 31 |
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 |
77 | static snd_async_handler_t *ahandler; | 82 | static snd_async_handler_t *ahandler; |
78 | static pthread_mutex_t pcm_mtx; | 83 | static pthread_mutex_t pcm_mtx; |
84 | static char signal_stack[SIGSTKSZ]; | ||
79 | #else | 85 | #else |
80 | static int recursion; | 86 | static 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 */ |