aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2018-01-08 08:03:53 -0500
committerTakashi Iwai <tiwai@suse.de>2018-01-08 10:40:26 -0500
commit900498a34a3ac9c611e9b425094c8106bdd7dc1c (patch)
tree844ccba051c0491b8e7d74879e6a8d20f11c6e53
parent29159a4ed7044c52e3e2cf1a9fb55cec4745c60b (diff)
ALSA: pcm: Allow aborting mutex lock at OSS read/write loops
PCM OSS read/write loops keep taking the mutex lock for the whole read/write, and this might take very long when the exceptionally high amount of data is given. Also, since it invokes with mutex_lock(), the concurrent read/write becomes unbreakable. This patch tries to address these issues by replacing mutex_lock() with mutex_lock_interruptible(), and also splits / re-takes the lock at each read/write period chunk, so that it can switch the context more finely if requested. Cc: <stable@vger.kernel.org> Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--sound/core/oss/pcm_oss.c36
1 files changed, 21 insertions, 15 deletions
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index e317964bd2ea..c2db7e905f7d 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -1334,8 +1334,11 @@ static ssize_t snd_pcm_oss_write1(struct snd_pcm_substream *substream, const cha
1334 1334
1335 if ((tmp = snd_pcm_oss_make_ready(substream)) < 0) 1335 if ((tmp = snd_pcm_oss_make_ready(substream)) < 0)
1336 return tmp; 1336 return tmp;
1337 mutex_lock(&runtime->oss.params_lock);
1338 while (bytes > 0) { 1337 while (bytes > 0) {
1338 if (mutex_lock_interruptible(&runtime->oss.params_lock)) {
1339 tmp = -ERESTARTSYS;
1340 break;
1341 }
1339 if (bytes < runtime->oss.period_bytes || runtime->oss.buffer_used > 0) { 1342 if (bytes < runtime->oss.period_bytes || runtime->oss.buffer_used > 0) {
1340 tmp = bytes; 1343 tmp = bytes;
1341 if (tmp + runtime->oss.buffer_used > runtime->oss.period_bytes) 1344 if (tmp + runtime->oss.buffer_used > runtime->oss.period_bytes)
@@ -1379,18 +1382,18 @@ static ssize_t snd_pcm_oss_write1(struct snd_pcm_substream *substream, const cha
1379 xfer += tmp; 1382 xfer += tmp;
1380 if ((substream->f_flags & O_NONBLOCK) != 0 && 1383 if ((substream->f_flags & O_NONBLOCK) != 0 &&
1381 tmp != runtime->oss.period_bytes) 1384 tmp != runtime->oss.period_bytes)
1382 break; 1385 tmp = -EAGAIN;
1383 } 1386 }
1387 err:
1388 mutex_unlock(&runtime->oss.params_lock);
1389 if (tmp < 0)
1390 break;
1384 if (signal_pending(current)) { 1391 if (signal_pending(current)) {
1385 tmp = -ERESTARTSYS; 1392 tmp = -ERESTARTSYS;
1386 goto err; 1393 break;
1387 } 1394 }
1395 tmp = 0;
1388 } 1396 }
1389 mutex_unlock(&runtime->oss.params_lock);
1390 return xfer;
1391
1392 err:
1393 mutex_unlock(&runtime->oss.params_lock);
1394 return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp; 1397 return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
1395} 1398}
1396 1399
@@ -1438,8 +1441,11 @@ static ssize_t snd_pcm_oss_read1(struct snd_pcm_substream *substream, char __use
1438 1441
1439 if ((tmp = snd_pcm_oss_make_ready(substream)) < 0) 1442 if ((tmp = snd_pcm_oss_make_ready(substream)) < 0)
1440 return tmp; 1443 return tmp;
1441 mutex_lock(&runtime->oss.params_lock);
1442 while (bytes > 0) { 1444 while (bytes > 0) {
1445 if (mutex_lock_interruptible(&runtime->oss.params_lock)) {
1446 tmp = -ERESTARTSYS;
1447 break;
1448 }
1443 if (bytes < runtime->oss.period_bytes || runtime->oss.buffer_used > 0) { 1449 if (bytes < runtime->oss.period_bytes || runtime->oss.buffer_used > 0) {
1444 if (runtime->oss.buffer_used == 0) { 1450 if (runtime->oss.buffer_used == 0) {
1445 tmp = snd_pcm_oss_read2(substream, runtime->oss.buffer, runtime->oss.period_bytes, 1); 1451 tmp = snd_pcm_oss_read2(substream, runtime->oss.buffer, runtime->oss.period_bytes, 1);
@@ -1470,16 +1476,16 @@ static ssize_t snd_pcm_oss_read1(struct snd_pcm_substream *substream, char __use
1470 bytes -= tmp; 1476 bytes -= tmp;
1471 xfer += tmp; 1477 xfer += tmp;
1472 } 1478 }
1479 err:
1480 mutex_unlock(&runtime->oss.params_lock);
1481 if (tmp < 0)
1482 break;
1473 if (signal_pending(current)) { 1483 if (signal_pending(current)) {
1474 tmp = -ERESTARTSYS; 1484 tmp = -ERESTARTSYS;
1475 goto err; 1485 break;
1476 } 1486 }
1487 tmp = 0;
1477 } 1488 }
1478 mutex_unlock(&runtime->oss.params_lock);
1479 return xfer;
1480
1481 err:
1482 mutex_unlock(&runtime->oss.params_lock);
1483 return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp; 1489 return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
1484} 1490}
1485 1491