tinyalsa: pcm: open pcm driver in non blocking mode
- in current implementation pcm open call is blocking hence if pcm_open
is done on same driver twice second pcm open will get blocked till
first instance of the PCM driver is not released.
In times this will result in deadlock.
- fix this issue by making PCM open in non-blocking mode.
- after pcm open is successful, in non-blocking mode, change the device
mode to blocking again to make sure rest of the operation on the
driver, like read / write calls, are always called in blocking mode.
Also fix jump to wrong label in case of failure before mmap().
Bug: 29865791
Bug: 30388410
Change-Id: I95c0ad8456e6c2bb3bfb48813e1db75cdef387f8
diff --git a/pcm.c b/pcm.c
index 394faba..78e1cea 100644
--- a/pcm.c
+++ b/pcm.c
@@ -855,12 +855,18 @@
flags & PCM_IN ? 'c' : 'p');
pcm->flags = flags;
- pcm->fd = open(fn, O_RDWR);
+ pcm->fd = open(fn, O_RDWR|O_NONBLOCK);
if (pcm->fd < 0) {
oops(pcm, errno, "cannot open device '%s'", fn);
return pcm;
}
+ if (fcntl(pcm->fd, F_SETFL, fcntl(pcm->fd, F_GETFL) &
+ ~O_NONBLOCK) < 0) {
+ oops(pcm, errno, "failed to reset blocking mode '%s'", fn);
+ goto fail_close;
+ }
+
if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_INFO, &info)) {
oops(pcm, errno, "cannot get info");
goto fail_close;
@@ -884,7 +890,7 @@
if (flags & PCM_NOIRQ) {
if (!(flags & PCM_MMAP)) {
oops(pcm, -EINVAL, "noirq only currently supported with mmap().");
- goto fail;
+ goto fail_close;
}
params.flags |= SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP;