From patchwork Wed Apr 8 16:55:08 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Sakamoto X-Patchwork-Id: 6181621 Return-Path: X-Original-To: patchwork-alsa-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 3B9F29F2E9 for ; Wed, 8 Apr 2015 16:57:11 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 516932037A for ; Wed, 8 Apr 2015 16:57:10 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.kernel.org (Postfix) with ESMTP id BA2B8202E5 for ; Wed, 8 Apr 2015 16:57:08 +0000 (UTC) Received: by alsa0.perex.cz (Postfix, from userid 1000) id 010E3265756; Wed, 8 Apr 2015 18:57:08 +0200 (CEST) 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, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 Received: from alsa0.perex.cz (localhost [IPv6:::1]) by alsa0.perex.cz (Postfix) with ESMTP id F402B26574A; Wed, 8 Apr 2015 18:55:38 +0200 (CEST) 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 6A3F926559B; Wed, 8 Apr 2015 18:55:37 +0200 (CEST) Received: from smtp310.phy.lolipop.jp (smtp310.phy.lolipop.jp [210.157.22.78]) by alsa0.perex.cz (Postfix) with ESMTP id 8BFA0265677 for ; Wed, 8 Apr 2015 18:55:13 +0200 (CEST) Received: from smtp310.phy.lolipop.lan (HELO smtp310.phy.lolipop.jp) (172.17.1.10) (smtp-auth username m12129643-o-takashi, mechanism plain) by smtp310.phy.lolipop.jp (qpsmtpd/0.82) with ESMTPA; Thu, 09 Apr 2015 01:55:11 +0900 Received: from 127.0.0.1 (127.0.0.1) by smtp310.phy.lolipop.jp (LOLIPOP-Fsecure); Thu, 09 Apr 2015 01:55:09 +0900 (JST) X-Virus-Status: clean(LOLIPOP-Fsecure) From: Takashi Sakamoto To: clemens@ladisch.de, tiwai@suse.de Date: Thu, 9 Apr 2015 01:55:08 +0900 Message-Id: <1428512108-1852-3-git-send-email-o-takashi@sakamocchi.jp> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1428512108-1852-1-git-send-email-o-takashi@sakamocchi.jp> References: <1428512108-1852-1-git-send-email-o-takashi@sakamocchi.jp> Cc: alsa-devel@alsa-project.org Subject: [alsa-devel] [PATCH 2/2] ALSA: ctl: refactoring for read operation 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: , MIME-Version: 1.0 Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org X-Virus-Scanned: ClamAV using ClamSMTP snd_ctl_read() has nested loop and complicated condition for return status. This is not better for reading. This commit applies refactoring with two loops. Signed-off-by: Takashi Sakamoto --- sound/core/control.c | 74 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 46 insertions(+), 28 deletions(-) diff --git a/sound/core/control.c b/sound/core/control.c index de19d56..6870baf 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -1520,58 +1520,76 @@ static ssize_t snd_ctl_read(struct file *file, char __user *buffer, size_t count, loff_t * offset) { struct snd_ctl_file *ctl; - int err = 0; - ssize_t result = 0; + struct snd_ctl_event ev; + struct snd_kctl_event *kev; + wait_queue_t wait; + size_t result; + int err; ctl = file->private_data; if (snd_BUG_ON(!ctl || !ctl->card)) return -ENXIO; if (!ctl->subscribed) return -EBADFD; + + /* The size of given buffer should be larger than at least one event. */ if (count < sizeof(struct snd_ctl_event)) return -EINVAL; + + /* Block till any events were queued. */ spin_lock_irq(&ctl->read_lock); - while (count >= sizeof(struct snd_ctl_event)) { - struct snd_ctl_event ev; - struct snd_kctl_event *kev; - while (list_empty(&ctl->events)) { - wait_queue_t wait; - if ((file->f_flags & O_NONBLOCK) != 0 || result > 0) { - err = -EAGAIN; - goto __end_lock; - } - init_waitqueue_entry(&wait, current); - add_wait_queue(&ctl->change_sleep, &wait); - set_current_state(TASK_INTERRUPTIBLE); + while (list_empty(&ctl->events)) { + if (file->f_flags & O_NONBLOCK) { + spin_unlock_irq(&ctl->read_lock); + return -EAGAIN; + } + + /* The card was disconnected. The queued events are dropped. */ + if (ctl->card->shutdown) { spin_unlock_irq(&ctl->read_lock); - schedule(); - remove_wait_queue(&ctl->change_sleep, &wait); - if (ctl->card->shutdown) - return -ENODEV; - if (signal_pending(current)) - return -ERESTARTSYS; - spin_lock_irq(&ctl->read_lock); + return -ENODEV; } + + + init_waitqueue_entry(&wait, current); + add_wait_queue(&ctl->change_sleep, &wait); + set_current_state(TASK_INTERRUPTIBLE); + spin_unlock_irq(&ctl->read_lock); + + schedule(); + + remove_wait_queue(&ctl->change_sleep, &wait); + + if (signal_pending(current)) + return -ERESTARTSYS; + + spin_lock_irq(&ctl->read_lock); + } + + /* Copy events till the buffer filled, or no events are remained. */ + result = 0; + while (count >= sizeof(struct snd_ctl_event)) { + if (list_empty(&ctl->events)) + break; kev = snd_kctl_event(ctl->events.next); + list_del(&kev->list); + ev.type = SNDRV_CTL_EVENT_ELEM; ev.data.elem.mask = kev->mask; ev.data.elem.id = kev->id; - list_del(&kev->list); - spin_unlock_irq(&ctl->read_lock); kfree(kev); if (copy_to_user(buffer, &ev, sizeof(struct snd_ctl_event))) { err = -EFAULT; - goto __end; + break; } - spin_lock_irq(&ctl->read_lock); + buffer += sizeof(struct snd_ctl_event); count -= sizeof(struct snd_ctl_event); result += sizeof(struct snd_ctl_event); } - __end_lock: + spin_unlock_irq(&ctl->read_lock); - __end: - return result > 0 ? result : err; + return result; } static unsigned int snd_ctl_poll(struct file *file, poll_table * wait)