ALSA: pcm: Make PCM linked list consistent while re-grouping
Make a common helper to re-assign the PCM link using list_move() instead of open code with manual list_del() and list_add_tail(). This assures the consistency and we can get rid of snd_pcm_group.count field -- its purpose is only to check whether the list is singular, and we can know it by list_is_singular() call now. Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
73365cb10b
commit
a41c4cb913
|
@ -439,7 +439,6 @@ struct snd_pcm_group { /* keep linked substreams */
|
|||
spinlock_t lock;
|
||||
struct mutex mutex;
|
||||
struct list_head substreams;
|
||||
int count;
|
||||
};
|
||||
|
||||
struct pid;
|
||||
|
|
|
@ -1131,6 +1131,13 @@ static int snd_pcm_action_single(const struct action_ops *ops,
|
|||
return res;
|
||||
}
|
||||
|
||||
static void snd_pcm_group_assign(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_group *new_group)
|
||||
{
|
||||
substream->group = new_group;
|
||||
list_move(&substream->link_list, &new_group->substreams);
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: call with stream lock
|
||||
*/
|
||||
|
@ -1995,14 +2002,10 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
|
|||
goto _end;
|
||||
}
|
||||
if (!snd_pcm_stream_linked(substream)) {
|
||||
substream->group = group;
|
||||
snd_pcm_group_assign(substream, group);
|
||||
group = NULL;
|
||||
list_add_tail(&substream->link_list, &substream->group->substreams);
|
||||
substream->group->count = 1;
|
||||
}
|
||||
list_add_tail(&substream1->link_list, &substream->group->substreams);
|
||||
substream->group->count++;
|
||||
substream1->group = substream->group;
|
||||
snd_pcm_group_assign(substream1, substream->group);
|
||||
_end:
|
||||
write_unlock_irq(&snd_pcm_link_rwlock);
|
||||
up_write(&snd_pcm_link_rwsem);
|
||||
|
@ -2015,14 +2018,13 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
|
|||
|
||||
static void relink_to_local(struct snd_pcm_substream *substream)
|
||||
{
|
||||
substream->group = &substream->self_group;
|
||||
INIT_LIST_HEAD(&substream->self_group.substreams);
|
||||
list_add_tail(&substream->link_list, &substream->self_group.substreams);
|
||||
snd_pcm_group_assign(substream, &substream->self_group);
|
||||
}
|
||||
|
||||
static int snd_pcm_unlink(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_pcm_substream *s;
|
||||
struct snd_pcm_group *group;
|
||||
int res = 0;
|
||||
|
||||
down_write_nonfifo(&snd_pcm_link_rwsem);
|
||||
|
@ -2031,16 +2033,20 @@ static int snd_pcm_unlink(struct snd_pcm_substream *substream)
|
|||
res = -EALREADY;
|
||||
goto _end;
|
||||
}
|
||||
list_del(&substream->link_list);
|
||||
substream->group->count--;
|
||||
if (substream->group->count == 1) { /* detach the last stream, too */
|
||||
|
||||
group = substream->group;
|
||||
|
||||
relink_to_local(substream);
|
||||
|
||||
/* detach the last stream, too */
|
||||
if (list_is_singular(&group->substreams)) {
|
||||
snd_pcm_group_for_each_entry(s, substream) {
|
||||
relink_to_local(s);
|
||||
break;
|
||||
}
|
||||
kfree(substream->group);
|
||||
kfree(group);
|
||||
}
|
||||
relink_to_local(substream);
|
||||
|
||||
_end:
|
||||
write_unlock_irq(&snd_pcm_link_rwlock);
|
||||
up_write(&snd_pcm_link_rwsem);
|
||||
|
|
Loading…
Reference in New Issue