Hello Takashi Thanks for your comments, Please find my answers below Regards Arnaud On 03/23/2017 08:02 PM, Takashi Iwai wrote: > On Thu, 23 Mar 2017 19:39:55 +0100, > Arnaud Pouliquen wrote: >> >> With RTlinux a race condition has been found that leads to NULL ptr crash: >> - On CPU 0: uni_player_irq_handler is called to treat XRUN >> "(player->state == UNIPERIF_STATE_STOPPED)" is FALSE so status is checked, >> dev_err(player->dev, "FIFO underflow error detected") is printed >> and then snd_pcm_stream_lock should be called to lock stream for stopping. >> - On CPU 1: application stop and close the stream. >> Issue is that the stop and shutdown functions are executed while >> "FIFO underflow error detected" is printed. >> So when CPU 0 calls snd_pcm_stream_lock, player->substream is already null. >> >> Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@xxxxxx> >> >> --- >> V2: Add spinlock to protect player/reader->substream >> --- >> sound/soc/sti/uniperif.h | 1 + >> sound/soc/sti/uniperif_player.c | 34 +++++++++++++++++++++++----------- >> sound/soc/sti/uniperif_reader.c | 24 ++++++++++++++++++++---- >> 3 files changed, 44 insertions(+), 15 deletions(-) >> >> diff --git a/sound/soc/sti/uniperif.h b/sound/soc/sti/uniperif.h >> index d487dd2..cfcb0ea 100644 >> --- a/sound/soc/sti/uniperif.h >> +++ b/sound/soc/sti/uniperif.h >> @@ -1299,6 +1299,7 @@ struct uniperif { >> int ver; /* IP version, used by register access macros */ >> struct regmap_field *clk_sel; >> struct regmap_field *valid_sel; >> + spinlock_t irq_lock; /* used to prevent race condition with IRQ */ >> >> /* capabilities */ >> const struct snd_pcm_hardware *hw; >> diff --git a/sound/soc/sti/uniperif_player.c b/sound/soc/sti/uniperif_player.c >> index 60ae31a..8f3a582 100644 >> --- a/sound/soc/sti/uniperif_player.c >> +++ b/sound/soc/sti/uniperif_player.c >> @@ -65,10 +65,13 @@ static irqreturn_t uni_player_irq_handler(int irq, void *dev_id) >> unsigned int status; >> unsigned int tmp; >> >> - if (player->state == UNIPERIF_STATE_STOPPED) { >> - /* Unexpected IRQ: do nothing */ >> - return IRQ_NONE; >> - } >> + spin_lock(&player->irq_lock); >> + if (!player->substream) >> + goto IRQ_END; > > This will be NULL-dereference, as it calls snd_pcm_stream_unlock() there. > Also, use lower letters for labels. Beginner's fault... > > >> + >> + snd_pcm_stream_lock(player->substream); > > Actually we don't need to take this lock here any longer since we have > irq_lock. Better to keep the stream lock only around the stop. Needed to protect "player->state". The irq_lock does not ensure that application calls a PCM stop in parallel on another CPU. That means that i need also to protect uni_player_stop and uni_player_start to protect layer->state. But in this case i will have a double lock when call snd_pcm_stop in IRQ handler. > > >> + if (player->state == UNIPERIF_STATE_STOPPED) >> + goto IRQ_END; >> >> /* Get interrupt status & clear them immediately */ >> status = GET_UNIPERIF_ITS(player); >> @@ -88,9 +91,7 @@ static irqreturn_t uni_player_irq_handler(int irq, void *dev_id) >> SET_UNIPERIF_ITM_BCLR_FIFO_ERROR(player); >> >> /* Stop the player */ >> - snd_pcm_stream_lock(player->substream); >> snd_pcm_stop(player->substream, SNDRV_PCM_STATE_XRUN); >> - snd_pcm_stream_unlock(player->substream); > > BTW, these three calls can be simplified with snd_pcm_stop_xrun(). > > > Takashi > _______________________________________________ Alsa-devel mailing list Alsa-devel@xxxxxxxxxxxxxxxx http://mailman.alsa-project.org/mailman/listinfo/alsa-devel