|
@@ -1370,6 +1370,7 @@ static ssize_t snd_pcm_oss_write1(struct snd_pcm_substream *substream, const cha
|
|
|
if (atomic_read(&substream->mmap_count))
|
|
|
return -ENXIO;
|
|
|
|
|
|
+ atomic_inc(&runtime->oss.rw_ref);
|
|
|
while (bytes > 0) {
|
|
|
if (mutex_lock_interruptible(&runtime->oss.params_lock)) {
|
|
|
tmp = -ERESTARTSYS;
|
|
@@ -1433,6 +1434,7 @@ static ssize_t snd_pcm_oss_write1(struct snd_pcm_substream *substream, const cha
|
|
|
}
|
|
|
tmp = 0;
|
|
|
}
|
|
|
+ atomic_dec(&runtime->oss.rw_ref);
|
|
|
return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
|
|
|
}
|
|
|
|
|
@@ -1478,6 +1480,7 @@ static ssize_t snd_pcm_oss_read1(struct snd_pcm_substream *substream, char __use
|
|
|
if (atomic_read(&substream->mmap_count))
|
|
|
return -ENXIO;
|
|
|
|
|
|
+ atomic_inc(&runtime->oss.rw_ref);
|
|
|
while (bytes > 0) {
|
|
|
if (mutex_lock_interruptible(&runtime->oss.params_lock)) {
|
|
|
tmp = -ERESTARTSYS;
|
|
@@ -1526,6 +1529,7 @@ static ssize_t snd_pcm_oss_read1(struct snd_pcm_substream *substream, char __use
|
|
|
}
|
|
|
tmp = 0;
|
|
|
}
|
|
|
+ atomic_dec(&runtime->oss.rw_ref);
|
|
|
return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
|
|
|
}
|
|
|
|
|
@@ -1632,8 +1636,11 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file)
|
|
|
goto __direct;
|
|
|
if ((err = snd_pcm_oss_make_ready(substream)) < 0)
|
|
|
return err;
|
|
|
- if (mutex_lock_interruptible(&runtime->oss.params_lock))
|
|
|
+ atomic_inc(&runtime->oss.rw_ref);
|
|
|
+ if (mutex_lock_interruptible(&runtime->oss.params_lock)) {
|
|
|
+ atomic_dec(&runtime->oss.rw_ref);
|
|
|
return -ERESTARTSYS;
|
|
|
+ }
|
|
|
format = snd_pcm_oss_format_from(runtime->oss.format);
|
|
|
width = snd_pcm_format_physical_width(format);
|
|
|
if (runtime->oss.buffer_used > 0) {
|
|
@@ -1645,10 +1652,8 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file)
|
|
|
runtime->oss.buffer + runtime->oss.buffer_used,
|
|
|
size);
|
|
|
err = snd_pcm_oss_sync1(substream, runtime->oss.period_bytes);
|
|
|
- if (err < 0) {
|
|
|
- mutex_unlock(&runtime->oss.params_lock);
|
|
|
- return err;
|
|
|
- }
|
|
|
+ if (err < 0)
|
|
|
+ goto unlock;
|
|
|
} else if (runtime->oss.period_ptr > 0) {
|
|
|
#ifdef OSS_DEBUG
|
|
|
pcm_dbg(substream->pcm, "sync: period_ptr\n");
|
|
@@ -1658,10 +1663,8 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file)
|
|
|
runtime->oss.buffer,
|
|
|
size * 8 / width);
|
|
|
err = snd_pcm_oss_sync1(substream, size);
|
|
|
- if (err < 0) {
|
|
|
- mutex_unlock(&runtime->oss.params_lock);
|
|
|
- return err;
|
|
|
- }
|
|
|
+ if (err < 0)
|
|
|
+ goto unlock;
|
|
|
}
|
|
|
/*
|
|
|
* The ALSA's period might be a bit large than OSS one.
|
|
@@ -1675,7 +1678,11 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file)
|
|
|
else if (runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
|
|
|
snd_pcm_lib_writev(substream, NULL, size);
|
|
|
}
|
|
|
+unlock:
|
|
|
mutex_unlock(&runtime->oss.params_lock);
|
|
|
+ atomic_dec(&runtime->oss.rw_ref);
|
|
|
+ if (err < 0)
|
|
|
+ return err;
|
|
|
/*
|
|
|
* finish sync: drain the buffer
|
|
|
*/
|
|
@@ -1723,6 +1730,8 @@ static int snd_pcm_oss_set_rate(struct snd_pcm_oss_file *pcm_oss_file, int rate)
|
|
|
rate = 192000;
|
|
|
if (mutex_lock_interruptible(&runtime->oss.params_lock))
|
|
|
return -ERESTARTSYS;
|
|
|
+ if (atomic_read(&runtime->oss.rw_ref))
|
|
|
+ return -EBUSY;
|
|
|
if (runtime->oss.rate != rate) {
|
|
|
runtime->oss.params = 1;
|
|
|
runtime->oss.rate = rate;
|
|
@@ -1757,6 +1766,8 @@ static int snd_pcm_oss_set_channels(struct snd_pcm_oss_file *pcm_oss_file, unsig
|
|
|
runtime = substream->runtime;
|
|
|
if (mutex_lock_interruptible(&runtime->oss.params_lock))
|
|
|
return -ERESTARTSYS;
|
|
|
+ if (atomic_read(&runtime->oss.rw_ref))
|
|
|
+ return -EBUSY;
|
|
|
if (runtime->oss.channels != channels) {
|
|
|
runtime->oss.params = 1;
|
|
|
runtime->oss.channels = channels;
|
|
@@ -1847,6 +1858,8 @@ static int snd_pcm_oss_set_format(struct snd_pcm_oss_file *pcm_oss_file, int for
|
|
|
if (substream == NULL)
|
|
|
continue;
|
|
|
runtime = substream->runtime;
|
|
|
+ if (atomic_read(&runtime->oss.rw_ref))
|
|
|
+ return -EBUSY;
|
|
|
if (mutex_lock_interruptible(&runtime->oss.params_lock))
|
|
|
return -ERESTARTSYS;
|
|
|
if (runtime->oss.format != format) {
|
|
@@ -1901,6 +1914,8 @@ static int snd_pcm_oss_set_subdivide(struct snd_pcm_oss_file *pcm_oss_file, int
|
|
|
if (substream == NULL)
|
|
|
continue;
|
|
|
runtime = substream->runtime;
|
|
|
+ if (atomic_read(&runtime->oss.rw_ref))
|
|
|
+ return -EBUSY;
|
|
|
if (mutex_lock_interruptible(&runtime->oss.params_lock))
|
|
|
return -ERESTARTSYS;
|
|
|
err = snd_pcm_oss_set_subdivide1(substream, subdivide);
|
|
@@ -1939,6 +1954,8 @@ static int snd_pcm_oss_set_fragment(struct snd_pcm_oss_file *pcm_oss_file, unsig
|
|
|
if (substream == NULL)
|
|
|
continue;
|
|
|
runtime = substream->runtime;
|
|
|
+ if (atomic_read(&runtime->oss.rw_ref))
|
|
|
+ return -EBUSY;
|
|
|
if (mutex_lock_interruptible(&runtime->oss.params_lock))
|
|
|
return -ERESTARTSYS;
|
|
|
err = snd_pcm_oss_set_fragment1(substream, val);
|
|
@@ -2333,6 +2350,7 @@ static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream,
|
|
|
runtime->oss.maxfrags = 0;
|
|
|
runtime->oss.subdivision = 0;
|
|
|
substream->pcm_release = snd_pcm_oss_release_substream;
|
|
|
+ atomic_set(&runtime->oss.rw_ref, 0);
|
|
|
}
|
|
|
|
|
|
static int snd_pcm_oss_release_file(struct snd_pcm_oss_file *pcm_oss_file)
|