* Re: 2.5.50: sleeping function called from illegal context
2002-12-03 5:57 ` Duncan Sands
@ 2002-12-03 14:56 ` Takashi Iwai
2002-12-03 6:39 ` Duncan Sands
2002-12-06 13:13 ` Duncan Sands
2002-12-03 18:34 ` Paul Davis
1 sibling, 2 replies; 11+ messages in thread
From: Takashi Iwai @ 2002-12-03 14:56 UTC (permalink / raw)
To: Duncan Sands; +Cc: alsa-devel
[-- Attachment #1: Type: text/plain, Size: 2620 bytes --]
At Tue, 3 Dec 2002 06:57:45 +0100,
Duncan Sands wrote:
>
> On Tuesday 03 December 2002 14:56, Takashi Iwai wrote:
> > At Tue, 3 Dec 2002 04:55:15 +0100,
> >
> > Duncan Sands wrote:
> > > On Tuesday 03 December 2002 13:01, Takashi Iwai wrote:
> > > > At Tue, 3 Dec 2002 04:07:52 +0100,
> > > >
> > > > Duncan Sands wrote:
> > > > > Got this with today 2.5 BK tree:
> > > > >
> > > > > Debug: sleeping function called from illegal context at
> > > > > include/asm/semaphore.h:119 Call Trace:
> > > > > [<c0113f1a>] __might_sleep+0x52/0x58
> > > > > [<c024291a>] snd_cs46xx_iec958_put+0x36/0xf8
> > > > > [<c0217f28>] snd_ctl_elem_write+0xe0/0x1a4
> > > > > [<c0218360>] snd_ctl_ioctl+0x184/0x2c8
> > > > > [<c01462e6>] sys_ioctl+0x1fa/0x244
> > > > > [<c01088f7>] syscall_call+0x7/0xb
> > > >
> > > > ouch, we are using rwlock in the control ioctls.
> > > >
> > > > mutex is necessary for many controls, so we cannot suppress the use of
> > > > mutex in control callbacks.
> > > > but temporary unlocking looks ad-hoc, too...
> > >
> > > If I understand right, the problem is that snd_ctl_elem_write
> > > acquires control_rwlock, which is a rw spinlock. It then calls
> > > snd_cs46xx_iec958_put which acquires chip->spos_mutex,
> > > which is a semaphore. Thus the message. Now I deduce
> > > from the fact that you don't use read_lock_irqsave that the
> > > data structure is not read from interrupt context. That means
> > > you are only protecting against other CPUs. So why not use
> > > a semaphore instead of a spinlock?
> >
> > hmm, there are some places calling with irq lock.
> > for example, snd_ctl_notify() can be called from the interrupt handler
> > for some interrupts like h/w volume change.
>
> Uh oh!
>
> > however, it seems that a single rwlock is used for the management of
> > two different lists. and snd_ctl_elem_write() uses card->controls
> > only, whereas snd_ctl_notify() uses card->ctl_files only.
> > hence, we can merge two locks, rwsem for card->controls and rwlock for
> > card->ctl_files. i'll give a try.
>
> I guess another way of dealing with this kind of problem is to use a
> semaphore rather than a spinlock, and a workqueue: when the interrupt
> comes in, the call to snd_ctl_notify is put on the queue, where it will later
> be run in process context, and can safely take the semaphore.
yes, basically what snd_ctl_notify() does is the same.
it queues an event and wakes up the sleepers.
thus, it's ok to separate the stuff from the semaphore.
the attached is a patch to rewrite the locks with rwsem.
please check whether it works for you.
thanks,
Takashi
[-- Attachment #2: control-lock-fix.dif --]
[-- Type: application/octet-stream, Size: 20990 bytes --]
Index: alsa-kernel/include/core.h
===================================================================
RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/include/core.h,v
retrieving revision 1.26
diff -u -r1.26 core.h
--- alsa-kernel/include/core.h 2 Dec 2002 09:25:18 -0000 1.26
+++ alsa-kernel/include/core.h 3 Dec 2002 14:29:58 -0000
@@ -24,6 +24,7 @@
#include <linux/sched.h> /* wake_up() */
#include <asm/semaphore.h> /* struct semaphore */
+#include <linux/rwsem.h> /* struct rw_semaphore */
/* Typedef's */
typedef struct timeval snd_timestamp_t;
@@ -141,8 +142,8 @@
struct list_head devices; /* devices */
unsigned int last_numid; /* last used numeric ID */
- rwlock_t control_rwlock; /* control list lock */
- rwlock_t control_owner_lock; /* control list lock */
+ struct rw_semaphore controls_rwsem; /* controls list lock */
+ rwlock_t ctl_files_rwlock; /* ctl_files list lock */
int controls_count; /* count of all controls */
struct list_head controls; /* all controls for this card */
struct list_head ctl_files; /* active control files */
Index: alsa-kernel/core/control.c
===================================================================
RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/core/control.c,v
retrieving revision 1.17
diff -u -r1.17 control.c
--- alsa-kernel/core/control.c 2 Dec 2002 09:25:17 -0000 1.17
+++ alsa-kernel/core/control.c 3 Dec 2002 14:45:15 -0000
@@ -37,7 +37,7 @@
#define snd_kctl_ioctl(n) list_entry(n, snd_kctl_ioctl_t, list)
-static rwlock_t snd_ioctl_rwlock = RW_LOCK_UNLOCKED;
+static DECLARE_RWSEM(snd_ioctl_rwsem);
static LIST_HEAD(snd_control_ioctls);
static inline void dec_mod_count(struct module *module)
@@ -82,9 +82,9 @@
ctl->card = card;
ctl->pid = current->pid;
file->private_data = ctl;
- write_lock_irqsave(&card->control_rwlock, flags);
+ write_lock_irqsave(&card->ctl_files_rwlock, flags);
list_add_tail(&ctl->list, &card->ctl_files);
- write_unlock_irqrestore(&card->control_rwlock, flags);
+ write_unlock_irqrestore(&card->ctl_files_rwlock, flags);
return 0;
__error:
@@ -123,16 +123,16 @@
fasync_helper(-1, file, 0, &ctl->fasync);
file->private_data = NULL;
card = ctl->card;
- write_lock_irqsave(&card->control_rwlock, flags);
+ write_lock_irqsave(&card->ctl_files_rwlock, flags);
list_del(&ctl->list);
- write_lock(&card->control_owner_lock);
+ write_unlock_irqrestore(&card->ctl_files_rwlock, flags);
+ down_write(&card->controls_rwsem);
list_for_each(list, &card->controls) {
control = snd_kcontrol(list);
if (control->owner == ctl)
control->owner = NULL;
}
- write_unlock(&card->control_owner_lock);
- write_unlock_irqrestore(&card->control_rwlock, flags);
+ up_write(&card->controls_rwsem);
snd_ctl_empty_read_queue(ctl);
snd_magic_kfree(ctl);
dec_mod_count(card->module);
@@ -151,7 +151,7 @@
snd_kctl_event_t *ev;
snd_runtime_check(card != NULL && id != NULL, return);
- read_lock_irqsave(&card->control_rwlock, flags);
+ read_lock(&card->ctl_files_rwlock);
#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
card->mixer_oss_change_count++;
#endif
@@ -160,7 +160,7 @@
ctl = snd_ctl_file(flist);
if (!ctl->subscribed)
continue;
- spin_lock(&ctl->read_lock);
+ spin_lock_irqsave(&ctl->read_lock, flags);
list_for_each(elist, &ctl->events) {
ev = snd_kctl_event(elist);
if (ev->id.numid == id->numid) {
@@ -179,9 +179,9 @@
_found:
wake_up(&ctl->change_sleep);
kill_fasync(&ctl->fasync, SIGIO, POLL_IN);
- spin_unlock(&ctl->read_lock);
+ spin_unlock_irqrestore(&ctl->read_lock, flags);
}
- read_unlock_irqrestore(&card->control_rwlock, flags);
+ read_unlock(&card->ctl_files_rwlock);
}
snd_kcontrol_t *snd_ctl_new(snd_kcontrol_t * control)
@@ -233,11 +233,11 @@
snd_assert(kcontrol->info != NULL, return -EINVAL);
snd_assert(!(kcontrol->access & SNDRV_CTL_ELEM_ACCESS_READ) || kcontrol->get != NULL, return -EINVAL);
snd_assert(!(kcontrol->access & SNDRV_CTL_ELEM_ACCESS_WRITE) || kcontrol->put != NULL, return -EINVAL);
- write_lock(&card->control_rwlock);
+ down_write(&card->controls_rwsem);
list_add_tail(&kcontrol->list, &card->controls);
card->controls_count++;
kcontrol->id.numid = ++card->last_numid;
- write_unlock(&card->control_rwlock);
+ up_write(&card->controls_rwsem);
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_ADD, &kcontrol->id);
return 0;
}
@@ -245,10 +245,10 @@
int snd_ctl_remove(snd_card_t * card, snd_kcontrol_t * kcontrol)
{
snd_runtime_check(card != NULL && kcontrol != NULL, return -EINVAL);
- write_lock(&card->control_rwlock);
+ down_write(&card->controls_rwsem);
list_del(&kcontrol->list);
card->controls_count--;
- write_unlock(&card->control_rwlock);
+ up_write(&card->controls_rwsem);
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_REMOVE, &kcontrol->id);
snd_ctl_free_one(kcontrol);
return 0;
@@ -264,47 +264,46 @@
return snd_ctl_remove(card, kctl);
}
+static snd_kcontrol_t *_ctl_find_id(snd_card_t * card, snd_ctl_elem_id_t *id); /* w/o lock */
+
int snd_ctl_rename_id(snd_card_t * card, snd_ctl_elem_id_t *src_id, snd_ctl_elem_id_t *dst_id)
{
snd_kcontrol_t *kctl;
- kctl = snd_ctl_find_id(card, src_id);
- if (kctl == NULL)
+ down_write(&card->controls_rwsem);
+ kctl = _ctl_find_id(card, src_id);
+ if (kctl == NULL) {
+ up_write(&card->controls_rwsem);
return -ENOENT;
- write_lock(&card->control_rwlock);
+ }
kctl->id = *dst_id;
kctl->id.numid = ++card->last_numid;
- write_unlock(&card->control_rwlock);
+ up_write(&card->controls_rwsem);
return 0;
}
-snd_kcontrol_t *snd_ctl_find_numid(snd_card_t * card, unsigned int numid)
+static snd_kcontrol_t *_ctl_find_numid(snd_card_t * card, unsigned int numid)
{
struct list_head *list;
snd_kcontrol_t *kctl;
snd_runtime_check(card != NULL && numid != 0, return NULL);
- read_lock(&card->control_rwlock);
list_for_each(list, &card->controls) {
kctl = snd_kcontrol(list);
- if (kctl->id.numid == numid) {
- read_unlock(&card->control_rwlock);
+ if (kctl->id.numid == numid)
return kctl;
- }
}
- read_unlock(&card->control_rwlock);
return NULL;
}
-snd_kcontrol_t *snd_ctl_find_id(snd_card_t * card, snd_ctl_elem_id_t *id)
+static snd_kcontrol_t *_ctl_find_id(snd_card_t * card, snd_ctl_elem_id_t *id)
{
struct list_head *list;
snd_kcontrol_t *kctl;
snd_runtime_check(card != NULL && id != NULL, return NULL);
if (id->numid != 0)
- return snd_ctl_find_numid(card, id->numid);
- read_lock(&card->control_rwlock);
+ return _ctl_find_numid(card, id->numid);
list_for_each(list, &card->controls) {
kctl = snd_kcontrol(list);
if (kctl->id.iface != id->iface)
@@ -317,20 +316,38 @@
continue;
if (kctl->id.index != id->index)
continue;
- read_unlock(&card->control_rwlock);
return kctl;
}
- read_unlock(&card->control_rwlock);
return NULL;
}
+/* exported: with read lock */
+snd_kcontrol_t *snd_ctl_find_id(snd_card_t * card, snd_ctl_elem_id_t *id)
+{
+ snd_kcontrol_t *kctl;
+ down_read(&card->controls_rwsem);
+ kctl = _ctl_find_id(card, id);
+ up_read(&card->controls_rwsem);
+ return kctl;
+}
+
+/* exported: with read lock */
+snd_kcontrol_t *snd_ctl_find_numid(snd_card_t * card, unsigned int numid)
+{
+ snd_kcontrol_t *kctl;
+ down_read(&card->controls_rwsem);
+ kctl = _ctl_find_numid(card, numid);
+ up_read(&card->controls_rwsem);
+ return kctl;
+}
+
static int snd_ctl_card_info(snd_card_t * card, snd_ctl_file_t * ctl,
unsigned int cmd, unsigned long arg)
{
snd_ctl_card_info_t info;
memset(&info, 0, sizeof(info));
- read_lock(&snd_ioctl_rwlock);
+ down_read(&snd_ioctl_rwsem);
info.card = card->number;
strncpy(info.id, card->id, sizeof(info.id) - 1);
strncpy(info.driver, card->driver, sizeof(info.driver) - 1);
@@ -338,7 +355,7 @@
strncpy(info.longname, card->longname, sizeof(info.longname) - 1);
strncpy(info.mixername, card->mixername, sizeof(info.mixername) - 1);
strncpy(info.components, card->components, sizeof(info.components) - 1);
- read_unlock(&snd_ioctl_rwlock);
+ up_read(&snd_ioctl_rwsem);
if (copy_to_user((void *) arg, &info, sizeof(snd_ctl_card_info_t)))
return -EFAULT;
return 0;
@@ -364,7 +381,7 @@
dst = vmalloc(space * sizeof(snd_ctl_elem_id_t));
if (dst == NULL)
return -ENOMEM;
- read_lock(&card->control_rwlock);
+ down_read(&card->controls_rwsem);
list.count = card->controls_count;
plist = card->controls.next;
while (offset-- > 0 && plist != &card->controls)
@@ -379,14 +396,14 @@
space--;
list.used++;
}
- read_unlock(&card->control_rwlock);
+ up_read(&card->controls_rwsem);
if (list.used > 0 && copy_to_user(list.pids, dst, list.used * sizeof(snd_ctl_elem_id_t)))
return -EFAULT;
vfree(dst);
} else {
- read_lock(&card->control_rwlock);
+ down_read(&card->controls_rwsem);
list.count = card->controls_count;
- read_unlock(&card->control_rwlock);
+ up_read(&card->controls_rwsem);
}
if (copy_to_user(_list, &list, sizeof(list)))
return -EFAULT;
@@ -402,10 +419,10 @@
if (copy_from_user(&info, _info, sizeof(info)))
return -EFAULT;
- read_lock(&card->control_rwlock);
- kctl = snd_ctl_find_id(card, &info.id);
+ down_read(&card->controls_rwsem);
+ kctl = _ctl_find_id(card, &info.id);
if (kctl == NULL) {
- read_unlock(&card->control_rwlock);
+ up_read(&card->controls_rwsem);
return -ENOENT;
}
#ifdef CONFIG_SND_DEBUG
@@ -425,7 +442,7 @@
info.owner = -1;
}
}
- read_unlock(&card->control_rwlock);
+ up_read(&card->controls_rwsem);
if (result >= 0)
if (copy_to_user(_info, &info, sizeof(info)))
return -EFAULT;
@@ -443,8 +460,8 @@
return -ENOMEM;
if (copy_from_user(control, _control, sizeof(*control)))
return -EFAULT;
- read_lock(&card->control_rwlock);
- kctl = snd_ctl_find_id(card, &control->id);
+ down_read(&card->controls_rwsem);
+ kctl = _ctl_find_id(card, &control->id);
if (kctl == NULL) {
result = -ENOENT;
} else {
@@ -460,7 +477,7 @@
result = -EPERM;
}
}
- read_unlock(&card->control_rwlock);
+ up_read(&card->controls_rwsem);
if (result >= 0)
if (copy_to_user(_control, control, sizeof(*control)))
return -EFAULT;
@@ -480,8 +497,8 @@
return -ENOMEM;
if (copy_from_user(control, _control, sizeof(*control)))
return -EFAULT;
- read_lock(&card->control_rwlock);
- kctl = snd_ctl_find_id(card, &control->id);
+ down_read(&card->controls_rwsem);
+ kctl = _ctl_find_id(card, &control->id);
if (kctl == NULL) {
result = -ENOENT;
} else {
@@ -489,7 +506,6 @@
if (control->indirect != indirect) {
result = -EACCES;
} else {
- read_lock(&card->control_owner_lock);
if (!(kctl->access & SNDRV_CTL_ELEM_ACCESS_WRITE) ||
kctl->put == NULL ||
(kctl->owner != NULL && kctl->owner != file)) {
@@ -499,16 +515,15 @@
if (result >= 0)
control->id = kctl->id;
}
- read_unlock(&card->control_owner_lock);
if (result > 0) {
- read_unlock(&card->control_rwlock);
+ up_read(&card->controls_rwsem);
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id);
result = 0;
goto __unlocked;
}
}
}
- read_unlock(&card->control_rwlock);
+ up_read(&card->controls_rwsem);
__unlocked:
if (result >= 0)
if (copy_to_user(_control, control, sizeof(*control)))
@@ -526,12 +541,11 @@
if (copy_from_user(&id, _id, sizeof(id)))
return -EFAULT;
- read_lock(&card->control_rwlock);
- kctl = snd_ctl_find_id(card, &id);
+ down_write(&card->controls_rwsem);
+ kctl = _ctl_find_id(card, &id);
if (kctl == NULL) {
result = -ENOENT;
} else {
- write_lock(&card->control_owner_lock);
if (kctl->owner != NULL)
result = -EBUSY;
else {
@@ -539,9 +553,8 @@
kctl->owner_pid = current->pid;
result = 0;
}
- write_unlock(&card->control_owner_lock);
}
- read_unlock(&card->control_rwlock);
+ up_write(&card->controls_rwsem);
return result;
}
@@ -554,12 +567,11 @@
if (copy_from_user(&id, _id, sizeof(id)))
return -EFAULT;
- read_lock(&card->control_rwlock);
- kctl = snd_ctl_find_id(card, &id);
+ down_write(&card->controls_rwsem);
+ kctl = _ctl_find_id(card, &id);
if (kctl == NULL) {
result = -ENOENT;
} else {
- write_lock(&card->control_owner_lock);
if (kctl->owner == NULL)
result = -EINVAL;
else if (kctl->owner != file)
@@ -569,9 +581,8 @@
kctl->owner_pid = 0;
result = 0;
}
- write_unlock(&card->control_owner_lock);
}
- read_unlock(&card->control_rwlock);
+ up_write(&card->controls_rwsem);
return result;
}
@@ -646,16 +657,16 @@
return put_user(SNDRV_CTL_POWER_D0, (int *)arg) ? -EFAULT : 0;
#endif
}
- read_lock(&snd_ioctl_rwlock);
+ down_read(&snd_ioctl_rwsem);
list_for_each(list, &snd_control_ioctls) {
p = list_entry(list, snd_kctl_ioctl_t, list);
err = p->fioctl(card, ctl, cmd, arg);
if (err != -ENOIOCTLCMD) {
- read_unlock(&snd_ioctl_rwlock);
+ up_read(&snd_ioctl_rwsem);
return err;
}
}
- read_unlock(&snd_ioctl_rwlock);
+ up_read(&snd_ioctl_rwsem);
snd_printd("unknown ioctl = 0x%x\n", cmd);
return -ENOTTY;
}
@@ -740,9 +751,9 @@
if (pn == NULL)
return -ENOMEM;
pn->fioctl = fcn;
- write_lock(&snd_ioctl_rwlock);
+ down_write(&snd_ioctl_rwsem);
list_add_tail(&pn->list, &snd_control_ioctls);
- write_unlock(&snd_ioctl_rwlock);
+ up_write(&snd_ioctl_rwsem);
return 0;
}
@@ -752,17 +763,17 @@
snd_kctl_ioctl_t *p;
snd_runtime_check(fcn != NULL, return -EINVAL);
- write_lock(&snd_ioctl_rwlock);
+ down_write(&snd_ioctl_rwsem);
list_for_each(list, &snd_control_ioctls) {
p = list_entry(list, snd_kctl_ioctl_t, list);
if (p->fioctl == fcn) {
list_del(&p->list);
- write_unlock(&snd_ioctl_rwlock);
+ up_write(&snd_ioctl_rwsem);
kfree(p);
return 0;
}
}
- write_unlock(&snd_ioctl_rwlock);
+ up_write(&snd_ioctl_rwsem);
snd_BUG();
return -EINVAL;
}
@@ -821,13 +832,13 @@
struct list_head *flist;
snd_ctl_file_t *ctl;
- read_lock_irq(&card->control_rwlock);
+ down_read(&card->controls_rwsem);
list_for_each(flist, &card->ctl_files) {
ctl = snd_ctl_file(flist);
wake_up(&ctl->change_sleep);
kill_fasync(&ctl->fasync, SIGIO, POLL_ERR);
}
- read_unlock_irq(&card->control_rwlock);
+ up_read(&card->controls_rwsem);
return 0;
}
Index: alsa-kernel/core/init.c
===================================================================
RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/core/init.c,v
retrieving revision 1.17
diff -u -r1.17 init.c
--- alsa-kernel/core/init.c 3 Dec 2002 11:02:36 -0000 1.17
+++ alsa-kernel/core/init.c 3 Dec 2002 14:30:16 -0000
@@ -99,8 +99,8 @@
card->number = idx;
card->module = module;
INIT_LIST_HEAD(&card->devices);
- rwlock_init(&card->control_rwlock);
- rwlock_init(&card->control_owner_lock);
+ init_rwsem(&card->controls_rwsem);
+ rwlock_init(&card->ctl_files_rwlock);
INIT_LIST_HEAD(&card->controls);
INIT_LIST_HEAD(&card->ctl_files);
spin_lock_init(&card->files_lock);
Index: alsa-kernel/core/pcm.c
===================================================================
RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/core/pcm.c,v
retrieving revision 1.19
diff -u -r1.19 pcm.c
--- alsa-kernel/core/pcm.c 2 Dec 2002 09:25:17 -0000 1.19
+++ alsa-kernel/core/pcm.c 3 Dec 2002 14:28:54 -0000
@@ -698,7 +698,7 @@
return -ENODEV;
card = pcm->card;
- read_lock(&card->control_rwlock);
+ down_read(&card->controls_rwsem);
list_for_each(list, &card->ctl_files) {
kctl = snd_ctl_file(list);
if (kctl->pid == current->pid) {
@@ -706,7 +706,7 @@
break;
}
}
- read_unlock(&card->control_rwlock);
+ up_read(&card->controls_rwsem);
if (pstr->substream_count == 0)
return -ENODEV;
Index: alsa-kernel/core/rawmidi.c
===================================================================
RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/core/rawmidi.c,v
retrieving revision 1.22
diff -u -r1.22 rawmidi.c
--- alsa-kernel/core/rawmidi.c 2 Dec 2002 09:25:18 -0000 1.22
+++ alsa-kernel/core/rawmidi.c 3 Dec 2002 14:31:09 -0000
@@ -412,7 +412,7 @@
add_wait_queue(&rmidi->open_wait, &wait);
while (1) {
subdevice = -1;
- read_lock(&card->control_rwlock);
+ down_read(&card->controls_rwsem);
list_for_each(list, &card->ctl_files) {
kctl = snd_ctl_file(list);
if (kctl->pid == current->pid) {
@@ -420,7 +420,7 @@
break;
}
}
- read_unlock(&card->control_rwlock);
+ up_read(&card->controls_rwsem);
err = snd_rawmidi_kernel_open(cardnum, device, subdevice, fflags, rawmidi_file);
if (err >= 0)
break;
Index: alsa-kernel/core/oss/mixer_oss.c
===================================================================
RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/core/oss/mixer_oss.c,v
retrieving revision 1.14
diff -u -r1.14 mixer_oss.c
--- alsa-kernel/core/oss/mixer_oss.c 2 Dec 2002 09:25:18 -0000 1.14
+++ alsa-kernel/core/oss/mixer_oss.c 3 Dec 2002 14:36:03 -0000
@@ -562,7 +562,7 @@
struct slot *slot = (struct slot *)pslot->private_data;
*left = *right = 100;
- read_lock(&card->control_rwlock);
+ down_read(&card->controls_rwsem);
if (slot->present & SNDRV_MIXER_OSS_PRESENT_PVOLUME) {
snd_mixer_oss_get_volume1_vol(fmixer, pslot, slot->kcontrol[SNDRV_MIXER_OSS_ITEM_PVOLUME], left, right);
} else if (slot->present & SNDRV_MIXER_OSS_PRESENT_GVOLUME) {
@@ -579,7 +579,7 @@
} else if (slot->present & SNDRV_MIXER_OSS_PRESENT_GROUTE) {
snd_mixer_oss_get_volume1_sw(fmixer, pslot, slot->kcontrol[SNDRV_MIXER_OSS_ITEM_GROUTE], left, right, 1);
}
- read_unlock(&card->control_rwlock);
+ up_read(&card->controls_rwsem);
return 0;
}
@@ -655,7 +655,7 @@
snd_card_t *card = fmixer->card;
struct slot *slot = (struct slot *)pslot->private_data;
- read_lock(&card->control_rwlock);
+ down_read(&card->controls_rwsem);
if (slot->present & SNDRV_MIXER_OSS_PRESENT_PVOLUME) {
snd_mixer_oss_put_volume1_vol(fmixer, pslot, slot->kcontrol[SNDRV_MIXER_OSS_ITEM_PVOLUME], left, right);
if (slot->present & SNDRV_MIXER_OSS_PRESENT_CVOLUME)
@@ -685,7 +685,7 @@
snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->kcontrol[SNDRV_MIXER_OSS_ITEM_GROUTE], left, right, 1);
}
}
- read_unlock(&card->control_rwlock);
+ up_read(&card->controls_rwsem);
return 0;
}
@@ -698,9 +698,9 @@
int left, right;
left = right = 1;
- read_lock(&card->control_rwlock);
+ down_read(&card->controls_rwsem);
snd_mixer_oss_get_volume1_sw(fmixer, pslot, slot->kcontrol[SNDRV_MIXER_OSS_ITEM_CSWITCH], &left, &right, 0);
- read_unlock(&card->control_rwlock);
+ up_read(&card->controls_rwsem);
*active = (left || right) ? 1 : 0;
return 0;
}
@@ -714,9 +714,9 @@
int left, right;
left = right = 1;
- read_lock(&card->control_rwlock);
+ down_read(&card->controls_rwsem);
snd_mixer_oss_get_volume1_sw(fmixer, pslot, slot->kcontrol[SNDRV_MIXER_OSS_ITEM_CROUTE], &left, &right, 1);
- read_unlock(&card->control_rwlock);
+ up_read(&card->controls_rwsem);
*active = (left || right) ? 1 : 0;
return 0;
}
@@ -728,9 +728,9 @@
snd_card_t *card = fmixer->card;
struct slot *slot = (struct slot *)pslot->private_data;
- read_lock(&card->control_rwlock);
+ down_read(&card->controls_rwsem);
snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->kcontrol[SNDRV_MIXER_OSS_ITEM_CSWITCH], active, active, 0);
- read_unlock(&card->control_rwlock);
+ up_read(&card->controls_rwsem);
return 0;
}
@@ -741,9 +741,9 @@
snd_card_t *card = fmixer->card;
struct slot *slot = (struct slot *)pslot->private_data;
- read_lock(&card->control_rwlock);
+ down_read(&card->controls_rwsem);
snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->kcontrol[SNDRV_MIXER_OSS_ITEM_CROUTE], active, active, 1);
- read_unlock(&card->control_rwlock);
+ up_read(&card->controls_rwsem);
return 0;
}
@@ -764,12 +764,11 @@
err = -ENOMEM;
goto __unlock;
}
- read_lock(&card->control_rwlock);
+ down_read(&card->controls_rwsem);
kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0);
snd_runtime_check(kctl != NULL, err = -ENOENT; goto __unlock);
snd_runtime_check(!(err = kctl->info(kctl, uinfo)), goto __unlock);
snd_runtime_check(!(err = kctl->get(kctl, uctl)), goto __unlock);
- read_unlock(&card->control_rwlock);
for (idx = 0; idx < 32; idx++) {
if (!(mixer->mask_recsrc & (1 << idx)))
continue;
@@ -785,10 +784,8 @@
}
}
err = 0;
- goto __unalloc;
__unlock:
- read_unlock(&card->control_rwlock);
- __unalloc:
+ up_read(&card->controls_rwsem);
if (uctl)
kfree(uctl);
if (uinfo)
@@ -813,7 +810,7 @@
err = -ENOMEM;
goto __unlock;
}
- read_lock(&card->control_rwlock);
+ down_read(&card->controls_rwsem);
kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0);
snd_runtime_check(kctl != NULL, err = -ENOENT; goto __unlock);
snd_runtime_check(!(err = kctl->info(kctl, uinfo)), goto __unlock);
@@ -838,7 +835,7 @@
snd_ctl_notify(fmixer->card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id);
err = 0;
__unlock:
- read_unlock(&card->control_rwlock);
+ up_read(&card->controls_rwsem);
if (uctl)
kfree(uctl);
if (uinfo)
^ permalink raw reply [flat|nested] 11+ messages in thread