[alsa-devel] [PATCH 10/15] ALSA: line6: Add proper locks for hwdep open/release/read
Andrej Krutak
dev at andree.sk
Thu Aug 11 21:02:22 CEST 2016
Signed-off-by: Andrej Krutak <dev at andree.sk>
---
sound/usb/line6/driver.c | 16 +++++++++++-----
sound/usb/line6/driver.h | 3 ++-
2 files changed, 13 insertions(+), 6 deletions(-)
diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c
index 0a0e324..344465f 100644
--- a/sound/usb/line6/driver.c
+++ b/sound/usb/line6/driver.c
@@ -541,8 +541,7 @@ static int line6_hwdep_open(struct snd_hwdep *hw, struct file *file)
line6->buffer_circular.head = 0;
line6->buffer_circular.tail = 0;
sema_init(&line6->buffer_circular.sem, 0);
-
- line6->buffer_circular.active = 1;
+ spin_lock_init(&line6->buffer_circular.read_lock);
line6->buffer_circular.data =
kmalloc(LINE6_MESSAGE_MAXLEN * LINE6_MESSAGE_MAXCOUNT, GFP_KERNEL);
@@ -567,7 +566,7 @@ static int line6_hwdep_release(struct snd_hwdep *hw, struct file *file)
/* By this time, no readers are waiting, we can safely recreate the
* semaphore at next open. */
- line6->buffer_circular.active = 0;
+ clear_bit(0, &line6->buffer_circular.active);
kfree(line6->buffer_circular.data);
kfree(line6->buffer_circular.data_len);
@@ -581,18 +580,23 @@ line6_hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count,
{
struct usb_line6 *line6 = hwdep->private_data;
unsigned long tail;
+ long rv = 0;
if (down_interruptible(&line6->buffer_circular.sem)) {
return -ERESTARTSYS;
}
/* There must an item now in the buffer... */
+ spin_lock(&line6->buffer_circular.read_lock);
+
tail = line6->buffer_circular.tail;
if (line6->buffer_circular.data_len[tail] > count) {
/* Buffer too small; allow re-read of the current item... */
up(&line6->buffer_circular.sem);
- return -EINVAL;
+
+ rv = -EINVAL;
+ goto end;
}
if (copy_to_user(buf,
@@ -608,7 +612,9 @@ line6_hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count,
smp_store_release(&line6->buffer_circular.tail,
(tail + 1) & (LINE6_MESSAGE_MAXCOUNT - 1));
- return 0;
+end:
+ spin_unlock(&line6->buffer_circular.read_lock);
+ return rv;
}
/* Write directly (no buffering) to device by user*/
diff --git a/sound/usb/line6/driver.h b/sound/usb/line6/driver.h
index f4ab6cd..05e155c 100644
--- a/sound/usb/line6/driver.h
+++ b/sound/usb/line6/driver.h
@@ -159,12 +159,13 @@ struct usb_line6 {
/* Circular buffer for non-MIDI control messages */
struct {
- int active;
+ unsigned long active;
char *data;
int *data_len;
unsigned long head, tail;
/* Actually is up'd # of items in the buffer - times */
struct semaphore sem;
+ spinlock_t read_lock;
} buffer_circular;
/* If MIDI is supported, buffer_message contains the pre-processed data;
--
1.9.1
More information about the Alsa-devel
mailing list