Skip to content

Commit

Permalink
ALSA: pcm: Make PCM linked list consistent while re-grouping
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Takashi Iwai committed Jan 21, 2019
1 parent 73365cb commit a41c4cb
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 15 deletions.
1 change: 0 additions & 1 deletion include/sound/pcm.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
34 changes: 20 additions & 14 deletions sound/core/pcm_native.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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);
Expand Down

0 comments on commit a41c4cb

Please sign in to comment.