From patchwork Mon Nov 3 18:45:07 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 5219051 X-Patchwork-Delegate: tiwai@suse.de Return-Path: X-Original-To: patchwork-alsa-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id C89E6C11AC for ; Mon, 3 Nov 2014 18:45:33 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id CE55B20114 for ; Mon, 3 Nov 2014 18:45:32 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.kernel.org (Postfix) with ESMTP id 76A2220136 for ; Mon, 3 Nov 2014 18:45:31 +0000 (UTC) Received: by alsa0.perex.cz (Postfix, from userid 1000) id D315C260542; Mon, 3 Nov 2014 19:45:25 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_NONE, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 Received: from alsa0.perex.cz (localhost [IPv6:::1]) by alsa0.perex.cz (Postfix) with ESMTP id C3B4F2604F8; Mon, 3 Nov 2014 19:45:20 +0100 (CET) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id 7140626050A; Mon, 3 Nov 2014 19:45:19 +0100 (CET) Received: from mx2.suse.de (cantor2.suse.de [195.135.220.15]) by alsa0.perex.cz (Postfix) with ESMTP id 766FF260489 for ; Mon, 3 Nov 2014 19:45:11 +0100 (CET) Received: from relay2.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 0979CAB08; Mon, 3 Nov 2014 18:45:09 +0000 (UTC) Date: Mon, 03 Nov 2014 19:45:07 +0100 Message-ID: From: Takashi Iwai To: Liam Girdwood In-Reply-To: <1415035212.2471.26.camel@loki> References: <1415021524.2471.16.camel@loki> <1415035212.2471.26.camel@loki> User-Agent: Wanderlust/2.15.9 (Almost Unreal) SEMI/1.14.6 (Maruoka) FLIM/1.14.9 (=?UTF-8?B?R29qxY0=?=) APEL/10.8 Emacs/24.3 (x86_64-suse-linux-gnu) MULE/6.0 (HANACHIRUSATO) MIME-Version: 1.0 (generated by SEMI 1.14.6 - "Maruoka") Cc: "alsa-devel@alsa-project.org" , Wilbur Wang , Qiao Zhou , Mark Brown , Chao Xie Subject: Re: [alsa-devel] [Question about DPCM] dpcm_run_new_update races again xrun X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org X-Virus-Scanned: ClamAV using ClamSMTP At Mon, 03 Nov 2014 17:20:12 +0000, Liam Girdwood wrote: > > On Mon, 2014-11-03 at 17:54 +0100, Takashi Iwai wrote: > > At Mon, 03 Nov 2014 15:42:16 +0100, > > Takashi Iwai wrote: > > > > > > At Mon, 03 Nov 2014 13:32:04 +0000, > > > Liam Girdwood wrote: > > > > > > > > On Mon, 2014-11-03 at 03:28 -0800, Qiao Zhou wrote: > > > > > Hi Mark, Liam > > > > > > > > > > I met one BE not-function issue when developing DPCM feature, and found > > > > > dpcm_run_new_update is not protected well against xrun(interrupt context). > > > > > Could you help to give some suggestions? > > > > > > > > > > > > > I'm wondering if this would be better solved by improving the locking so > > > > that an XRUN could not run at the same time as the runtime update. Both > > > > functions are async, but are only protected by a mutex atm (like the > > > > rest of PCM ops except trigger which is atomic). We maybe need to add a > > > > spinlock to both runtime_update() and dpcm_fe_dai_trigger() > > > > > > Be careful, you cannot take spinlock while hw_params, for example. > > > > > > Why do you need to set runtime_update to NO in the trigger callback in > > > the first place? The trigger may influence on the FE streaming state, > > > but not on the FE/BE connection state, right? > > > > Thinking of this again, this doesn't look like a good suggestion, > > either. > > > > As mentioned, we can't take a lock for the whole lengthy operation > > like prepare or hw_params. So, instead of taking a lock, the trigger > > should be delayed when some operation is being performed. (I thought > > at first just performing FE's trigger and delaying BE later, but FE/BE > > trigger can be more complex than that, so it ends up with the whole > > delayed trigger.) > > > > The patch below is a quick hack (only compile tested!). It uses PCM's > > stream lock for protecting against the race for the state transition, > > and the trigger callback checks the state, aborts immediately if there > > is a concurrent operation. At the exit of state change, it invokes > > the delayed trigger. > > > > Let me know if this really works as imagined. Then I'll cook up a > > proper patch. > > > > I'll give the patch a try tomorrow and it would be good for Marvell to > test tomorrow too (as my system does not XRUN). FWIW, below is a simple hack to simulate an XRUN via proc file. Just write any value xrun_injection proc file and it triggers XRUN, e.g. # echo > /proc/asound/card0/pcm0p/sub0/xrun_injection For simulating the race, you should impose some artificial delay in the function you'll try to conflict, then trigger xrun. Takashi diff --git a/include/sound/pcm.h b/include/sound/pcm.h index e862497f7556..9e46132529c4 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -416,6 +416,7 @@ struct snd_pcm_substream { struct snd_info_entry *proc_status_entry; struct snd_info_entry *proc_prealloc_entry; struct snd_info_entry *proc_prealloc_max_entry; + struct snd_info_entry *proc_xrun_injection; #endif /* misc flags */ unsigned int hw_opened: 1; diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 42ded997b223..fa442d0504f0 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -478,6 +478,19 @@ static void snd_pcm_substream_proc_status_read(struct snd_info_entry *entry, mutex_unlock(&substream->pcm->open_mutex); } +static void snd_pcm_xrun_injection_write(struct snd_info_entry *entry, + struct snd_info_buffer *buffer) +{ + struct snd_pcm_substream *substream = entry->private_data; + struct snd_pcm_runtime *runtime; + + snd_pcm_stream_lock_irq(substream); + runtime = substream->runtime; + if (runtime && runtime->status->state == SNDRV_PCM_STATE_RUNNING) + snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); + snd_pcm_stream_unlock_irq(substream); +} + #ifdef CONFIG_SND_PCM_XRUN_DEBUG static void snd_pcm_xrun_debug_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) @@ -610,6 +623,20 @@ static int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream) } substream->proc_status_entry = entry; + entry = snd_info_create_card_entry(card, "xrun_injection", + substream->proc_root); + if (entry) { + entry->private_data = substream; + entry->c.text.read = NULL; + entry->c.text.write = snd_pcm_xrun_injection_write; + entry->mode = S_IFREG | S_IWUSR; + if (snd_info_register(entry) < 0) { + snd_info_free_entry(entry); + entry = NULL; + } + } + substream->proc_status_entry = entry; + return 0; } @@ -623,6 +650,8 @@ static int snd_pcm_substream_proc_done(struct snd_pcm_substream *substream) substream->proc_sw_params_entry = NULL; snd_info_free_entry(substream->proc_status_entry); substream->proc_status_entry = NULL; + snd_info_free_entry(substream->proc_xrun_injection); + substream->proc_xrun_injection = NULL; snd_info_free_entry(substream->proc_root); substream->proc_root = NULL; return 0;