All of lore.kernel.org
 help / color / mirror / Atom feed
From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
To: clemens@ladisch.de, tiwai@suse.de
Cc: alsa-devel@alsa-project.org
Subject: [PATCH 2/2] ALSA: ctl: refactoring for read operation
Date: Fri, 10 Apr 2015 08:43:01 +0900	[thread overview]
Message-ID: <1428622981-9747-3-git-send-email-o-takashi@sakamocchi.jp> (raw)
In-Reply-To: <1428622981-9747-1-git-send-email-o-takashi@sakamocchi.jp>

snd_ctl_read() has nested loop and complicated condition for return
value. This is not better for reading.

This commit applies refactoring with two loops.

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
---
 sound/core/control.c | 77 ++++++++++++++++++++++++++++++++--------------------
 1 file changed, 47 insertions(+), 30 deletions(-)

diff --git a/sound/core/control.c b/sound/core/control.c
index de19d56..da6497d 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -1520,58 +1520,75 @@ 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;
+	ssize_t result;
 
 	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);
-			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);
+	while (list_empty(&ctl->events)) {
+		if (file->f_flags & O_NONBLOCK) {
+			result = -EAGAIN;
+			goto unlock;
 		}
+
+		/* The card was disconnected. The queued events are dropped. */
+		if (ctl->card->shutdown) {
+			result = -ENODEV;
+			goto unlock;
+		}
+
+
+		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;
+			result = -EFAULT;
+			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:
+unlock:
 	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)
-- 
2.1.0

  parent reply	other threads:[~2015-04-09 23:43 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-04-08 16:55 [PATCH 0/2 RFC] control core refactoring Takashi Sakamoto
2015-04-08 16:55 ` [PATCH 1/2] ALSA: ctl: evaluate macro instead of numerical value Takashi Sakamoto
2015-04-08 16:55 ` [PATCH 2/2] ALSA: ctl: refactoring for read operation Takashi Sakamoto
2015-04-09  5:33   ` Takashi Iwai
2015-04-09  7:35     ` Takashi Sakamoto
2015-04-09  8:17       ` Takashi Iwai
2015-04-09 23:42 ` [PATCH 0/2] control core refactoring Takashi Sakamoto
2015-04-09 23:43   ` [PATCH 1/2] ALSA: ctl: evaluate macro instead of numerical value Takashi Sakamoto
2015-04-10  7:49     ` Takashi Iwai
2015-04-12  7:20       ` Takashi Iwai
2015-04-09 23:43   ` Takashi Sakamoto [this message]
2015-04-10  7:48     ` [PATCH 2/2] ALSA: ctl: refactoring for read operation Takashi Iwai
2015-04-10 10:32       ` Takashi Sakamoto
2015-04-10 10:43         ` Takashi Iwai
2015-04-10 10:52           ` Takashi Sakamoto

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1428622981-9747-3-git-send-email-o-takashi@sakamocchi.jp \
    --to=o-takashi@sakamocchi.jp \
    --cc=alsa-devel@alsa-project.org \
    --cc=clemens@ladisch.de \
    --cc=tiwai@suse.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.