]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
ALSA: timer: Use guard() for locking
authorTakashi Iwai <tiwai@suse.de>
Tue, 27 Feb 2024 08:52:45 +0000 (09:52 +0100)
committerTakashi Iwai <tiwai@suse.de>
Wed, 28 Feb 2024 14:01:20 +0000 (15:01 +0100)
We can simplify the code gracefully with new guard() macro and co for
automatic cleanup of locks.

For making changes easier, some functions widen the application of
register_mutex, but those shouldn't influence on any actual
performance.

Also, one code block was factored out as a function so that guard()
can be applied cleanly without much indentation.

There are still a few remaining explicit spin_lock/unlock calls, and
those are for the places where we do temporary unlock/relock, which
doesn't fit well with the guard(), so far.

Only the code refactoring, and no functional changes.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
Link: https://lore.kernel.org/r/20240227085306.9764-4-tiwai@suse.de
sound/core/timer.c
sound/core/timer_compat.c

index a595c4fb4b2a0f58633aff742ec189a87cee0800..15b07d09c4b72064d1f4eaff7d41cd40c9a29d01 100644 (file)
@@ -224,14 +224,12 @@ static int check_matching_master_slave(struct snd_timer_instance *master,
                return -EBUSY;
        list_move_tail(&slave->open_list, &master->slave_list_head);
        master->timer->num_instances++;
-       spin_lock_irq(&slave_active_lock);
-       spin_lock(&master->timer->lock);
+       guard(spinlock_irq)(&slave_active_lock);
+       guard(spinlock)(&master->timer->lock);
        slave->master = master;
        slave->timer = master->timer;
        if (slave->flags & SNDRV_TIMER_IFLG_RUNNING)
                list_add_tail(&slave->active_list, &master->slave_active_head);
-       spin_unlock(&master->timer->lock);
-       spin_unlock_irq(&slave_active_lock);
        return 1;
 }
 
@@ -382,6 +380,25 @@ list_added:
 }
 EXPORT_SYMBOL(snd_timer_open);
 
+/* remove slave links, called from snd_timer_close_locked() below */
+static void remove_slave_links(struct snd_timer_instance *timeri,
+                              struct snd_timer *timer)
+{
+       struct snd_timer_instance *slave, *tmp;
+
+       guard(spinlock_irq)(&slave_active_lock);
+       guard(spinlock)(&timer->lock);
+       timeri->timer = NULL;
+       list_for_each_entry_safe(slave, tmp, &timeri->slave_list_head, open_list) {
+               list_move_tail(&slave->open_list, &snd_timer_slave_list);
+               timer->num_instances--;
+               slave->master = NULL;
+               slave->timer = NULL;
+               list_del_init(&slave->ack_list);
+               list_del_init(&slave->active_list);
+       }
+}
+
 /*
  * close a timer instance
  * call this with register_mutex down.
@@ -390,12 +407,10 @@ static void snd_timer_close_locked(struct snd_timer_instance *timeri,
                                   struct device **card_devp_to_put)
 {
        struct snd_timer *timer = timeri->timer;
-       struct snd_timer_instance *slave, *tmp;
 
        if (timer) {
-               spin_lock_irq(&timer->lock);
+               guard(spinlock)(&timer->lock);
                timeri->flags |= SNDRV_TIMER_IFLG_DEAD;
-               spin_unlock_irq(&timer->lock);
        }
 
        if (!list_empty(&timeri->open_list)) {
@@ -418,21 +433,7 @@ static void snd_timer_close_locked(struct snd_timer_instance *timeri,
                }
                spin_unlock_irq(&timer->lock);
 
-               /* remove slave links */
-               spin_lock_irq(&slave_active_lock);
-               spin_lock(&timer->lock);
-               timeri->timer = NULL;
-               list_for_each_entry_safe(slave, tmp, &timeri->slave_list_head,
-                                        open_list) {
-                       list_move_tail(&slave->open_list, &snd_timer_slave_list);
-                       timer->num_instances--;
-                       slave->master = NULL;
-                       slave->timer = NULL;
-                       list_del_init(&slave->ack_list);
-                       list_del_init(&slave->active_list);
-               }
-               spin_unlock(&timer->lock);
-               spin_unlock_irq(&slave_active_lock);
+               remove_slave_links(timeri, timer);
 
                /* slave doesn't need to release timer resources below */
                if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE)
@@ -459,9 +460,8 @@ void snd_timer_close(struct snd_timer_instance *timeri)
        if (snd_BUG_ON(!timeri))
                return;
 
-       mutex_lock(&register_mutex);
-       snd_timer_close_locked(timeri, &card_dev_to_put);
-       mutex_unlock(&register_mutex);
+       scoped_guard(mutex, &register_mutex)
+               snd_timer_close_locked(timeri, &card_dev_to_put);
        /* put_device() is called after unlock for avoiding deadlock */
        if (card_dev_to_put)
                put_device(card_dev_to_put);
@@ -480,15 +480,13 @@ unsigned long snd_timer_resolution(struct snd_timer_instance *timeri)
 {
        struct snd_timer * timer;
        unsigned long ret = 0;
-       unsigned long flags;
 
        if (timeri == NULL)
                return 0;
        timer = timeri->timer;
        if (timer) {
-               spin_lock_irqsave(&timer->lock, flags);
+               guard(spinlock_irqsave)(&timer->lock);
                ret = snd_timer_hw_resolution(timer);
-               spin_unlock_irqrestore(&timer->lock, flags);
        }
        return ret;
 }
@@ -532,26 +530,19 @@ static int snd_timer_start1(struct snd_timer_instance *timeri,
 {
        struct snd_timer *timer;
        int result;
-       unsigned long flags;
 
        timer = timeri->timer;
        if (!timer)
                return -EINVAL;
 
-       spin_lock_irqsave(&timer->lock, flags);
-       if (timeri->flags & SNDRV_TIMER_IFLG_DEAD) {
-               result = -EINVAL;
-               goto unlock;
-       }
-       if (timer->card && timer->card->shutdown) {
-               result = -ENODEV;
-               goto unlock;
-       }
+       guard(spinlock_irqsave)(&timer->lock);
+       if (timeri->flags & SNDRV_TIMER_IFLG_DEAD)
+               return -EINVAL;
+       if (timer->card && timer->card->shutdown)
+               return -ENODEV;
        if (timeri->flags & (SNDRV_TIMER_IFLG_RUNNING |
-                            SNDRV_TIMER_IFLG_START)) {
-               result = -EBUSY;
-               goto unlock;
-       }
+                            SNDRV_TIMER_IFLG_START))
+               return -EBUSY;
 
        if (start)
                timeri->ticks = timeri->cticks = ticks;
@@ -577,8 +568,6 @@ static int snd_timer_start1(struct snd_timer_instance *timeri,
        }
        snd_timer_notify1(timeri, start ? SNDRV_TIMER_EVENT_START :
                          SNDRV_TIMER_EVENT_CONTINUE);
- unlock:
-       spin_unlock_irqrestore(&timer->lock, flags);
        return result;
 }
 
@@ -586,53 +575,38 @@ static int snd_timer_start1(struct snd_timer_instance *timeri,
 static int snd_timer_start_slave(struct snd_timer_instance *timeri,
                                 bool start)
 {
-       unsigned long flags;
-       int err;
-
-       spin_lock_irqsave(&slave_active_lock, flags);
-       if (timeri->flags & SNDRV_TIMER_IFLG_DEAD) {
-               err = -EINVAL;
-               goto unlock;
-       }
-       if (timeri->flags & SNDRV_TIMER_IFLG_RUNNING) {
-               err = -EBUSY;
-               goto unlock;
-       }
+       guard(spinlock_irqsave)(&slave_active_lock);
+       if (timeri->flags & SNDRV_TIMER_IFLG_DEAD)
+               return -EINVAL;
+       if (timeri->flags & SNDRV_TIMER_IFLG_RUNNING)
+               return -EBUSY;
        timeri->flags |= SNDRV_TIMER_IFLG_RUNNING;
        if (timeri->master && timeri->timer) {
-               spin_lock(&timeri->timer->lock);
+               guard(spinlock)(&timeri->timer->lock);
                list_add_tail(&timeri->active_list,
                              &timeri->master->slave_active_head);
                snd_timer_notify1(timeri, start ? SNDRV_TIMER_EVENT_START :
                                  SNDRV_TIMER_EVENT_CONTINUE);
-               spin_unlock(&timeri->timer->lock);
        }
-       err = 1; /* delayed start */
- unlock:
-       spin_unlock_irqrestore(&slave_active_lock, flags);
-       return err;
+       return 1; /* delayed start */
 }
 
 /* stop/pause a master timer */
 static int snd_timer_stop1(struct snd_timer_instance *timeri, bool stop)
 {
        struct snd_timer *timer;
-       int result = 0;
-       unsigned long flags;
 
        timer = timeri->timer;
        if (!timer)
                return -EINVAL;
-       spin_lock_irqsave(&timer->lock, flags);
+       guard(spinlock_irqsave)(&timer->lock);
        list_del_init(&timeri->ack_list);
        list_del_init(&timeri->active_list);
        if (!(timeri->flags & (SNDRV_TIMER_IFLG_RUNNING |
-                              SNDRV_TIMER_IFLG_START))) {
-               result = -EBUSY;
-               goto unlock;
-       }
+                              SNDRV_TIMER_IFLG_START)))
+               return -EBUSY;
        if (timer->card && timer->card->shutdown)
-               goto unlock;
+               return 0;
        if (stop) {
                timeri->cticks = timeri->ticks;
                timeri->pticks = 0;
@@ -656,30 +630,25 @@ static int snd_timer_stop1(struct snd_timer_instance *timeri, bool stop)
                timeri->flags |= SNDRV_TIMER_IFLG_PAUSED;
        snd_timer_notify1(timeri, stop ? SNDRV_TIMER_EVENT_STOP :
                          SNDRV_TIMER_EVENT_PAUSE);
- unlock:
-       spin_unlock_irqrestore(&timer->lock, flags);
-       return result;
+       return 0;
 }
 
 /* stop/pause a slave timer */
 static int snd_timer_stop_slave(struct snd_timer_instance *timeri, bool stop)
 {
-       unsigned long flags;
        bool running;
 
-       spin_lock_irqsave(&slave_active_lock, flags);
+       guard(spinlock_irqsave)(&slave_active_lock);
        running = timeri->flags & SNDRV_TIMER_IFLG_RUNNING;
        timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
        if (timeri->timer) {
-               spin_lock(&timeri->timer->lock);
+               guard(spinlock)(&timeri->timer->lock);
                list_del_init(&timeri->ack_list);
                list_del_init(&timeri->active_list);
                if (running)
                        snd_timer_notify1(timeri, stop ? SNDRV_TIMER_EVENT_STOP :
                                          SNDRV_TIMER_EVENT_PAUSE);
-               spin_unlock(&timeri->timer->lock);
        }
-       spin_unlock_irqrestore(&slave_active_lock, flags);
        return running ? 0 : -EBUSY;
 }
 
@@ -804,12 +773,9 @@ static void snd_timer_process_callbacks(struct snd_timer *timer,
 static void snd_timer_clear_callbacks(struct snd_timer *timer,
                                      struct list_head *head)
 {
-       unsigned long flags;
-
-       spin_lock_irqsave(&timer->lock, flags);
+       guard(spinlock_irqsave)(&timer->lock);
        while (!list_empty(head))
                list_del_init(head->next);
-       spin_unlock_irqrestore(&timer->lock, flags);
 }
 
 /*
@@ -819,16 +785,14 @@ static void snd_timer_clear_callbacks(struct snd_timer *timer,
 static void snd_timer_work(struct work_struct *work)
 {
        struct snd_timer *timer = container_of(work, struct snd_timer, task_work);
-       unsigned long flags;
 
        if (timer->card && timer->card->shutdown) {
                snd_timer_clear_callbacks(timer, &timer->sack_list_head);
                return;
        }
 
-       spin_lock_irqsave(&timer->lock, flags);
+       guard(spinlock_irqsave)(&timer->lock);
        snd_timer_process_callbacks(timer, &timer->sack_list_head);
-       spin_unlock_irqrestore(&timer->lock, flags);
 }
 
 /*
@@ -842,8 +806,6 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left)
        struct snd_timer_instance *ti, *ts, *tmp;
        unsigned long resolution;
        struct list_head *ack_list_head;
-       unsigned long flags;
-       bool use_work = false;
 
        if (timer == NULL)
                return;
@@ -853,7 +815,7 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left)
                return;
        }
 
-       spin_lock_irqsave(&timer->lock, flags);
+       guard(spinlock_irqsave)(&timer->lock);
 
        /* remember the current resolution */
        resolution = snd_timer_hw_resolution(timer);
@@ -919,10 +881,7 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left)
        snd_timer_process_callbacks(timer, &timer->ack_list_head);
 
        /* do we have any slow callbacks? */
-       use_work = !list_empty(&timer->sack_list_head);
-       spin_unlock_irqrestore(&timer->lock, flags);
-
-       if (use_work)
+       if (!list_empty(&timer->sack_list_head))
                queue_work(system_highpri_wq, &timer->task_work);
 }
 EXPORT_SYMBOL(snd_timer_interrupt);
@@ -988,7 +947,7 @@ static int snd_timer_free(struct snd_timer *timer)
        if (!timer)
                return 0;
 
-       mutex_lock(&register_mutex);
+       guard(mutex)(&register_mutex);
        if (! list_empty(&timer->open_list_head)) {
                struct list_head *p, *n;
                struct snd_timer_instance *ti;
@@ -1000,7 +959,6 @@ static int snd_timer_free(struct snd_timer *timer)
                }
        }
        list_del(&timer->device_list);
-       mutex_unlock(&register_mutex);
 
        if (timer->private_free)
                timer->private_free(timer);
@@ -1025,7 +983,7 @@ static int snd_timer_dev_register(struct snd_device *dev)
            !timer->hw.resolution && timer->hw.c_resolution == NULL)
                return -EINVAL;
 
-       mutex_lock(&register_mutex);
+       guard(mutex)(&register_mutex);
        list_for_each_entry(timer1, &snd_timer_list, device_list) {
                if (timer1->tmr_class > timer->tmr_class)
                        break;
@@ -1046,11 +1004,9 @@ static int snd_timer_dev_register(struct snd_device *dev)
                if (timer1->tmr_subdevice < timer->tmr_subdevice)
                        continue;
                /* conflicts.. */
-               mutex_unlock(&register_mutex);
                return -EBUSY;
        }
        list_add_tail(&timer->device_list, &timer1->device_list);
-       mutex_unlock(&register_mutex);
        return 0;
 }
 
@@ -1059,20 +1015,18 @@ static int snd_timer_dev_disconnect(struct snd_device *device)
        struct snd_timer *timer = device->device_data;
        struct snd_timer_instance *ti;
 
-       mutex_lock(&register_mutex);
+       guard(mutex)(&register_mutex);
        list_del_init(&timer->device_list);
        /* wake up pending sleepers */
        list_for_each_entry(ti, &timer->open_list_head, open_list) {
                if (ti->disconnect)
                        ti->disconnect(ti);
        }
-       mutex_unlock(&register_mutex);
        return 0;
 }
 
 void snd_timer_notify(struct snd_timer *timer, int event, struct timespec64 *tstamp)
 {
-       unsigned long flags;
        unsigned long resolution = 0;
        struct snd_timer_instance *ti, *ts;
 
@@ -1083,7 +1037,7 @@ void snd_timer_notify(struct snd_timer *timer, int event, struct timespec64 *tst
        if (snd_BUG_ON(event < SNDRV_TIMER_EVENT_MSTART ||
                       event > SNDRV_TIMER_EVENT_MRESUME))
                return;
-       spin_lock_irqsave(&timer->lock, flags);
+       guard(spinlock_irqsave)(&timer->lock);
        if (event == SNDRV_TIMER_EVENT_MSTART ||
            event == SNDRV_TIMER_EVENT_MCONTINUE ||
            event == SNDRV_TIMER_EVENT_MRESUME)
@@ -1095,7 +1049,6 @@ void snd_timer_notify(struct snd_timer *timer, int event, struct timespec64 *tst
                        if (ts->ccallback)
                                ts->ccallback(ts, event, tstamp, resolution);
        }
-       spin_unlock_irqrestore(&timer->lock, flags);
 }
 EXPORT_SYMBOL(snd_timer_notify);
 
@@ -1248,7 +1201,7 @@ static void snd_timer_proc_read(struct snd_info_entry *entry,
        struct snd_timer_instance *ti;
        unsigned long resolution;
 
-       mutex_lock(&register_mutex);
+       guard(mutex)(&register_mutex);
        list_for_each_entry(timer, &snd_timer_list, device_list) {
                if (timer->card && timer->card->shutdown)
                        continue;
@@ -1270,9 +1223,8 @@ static void snd_timer_proc_read(struct snd_info_entry *entry,
                                    timer->tmr_device, timer->tmr_subdevice);
                }
                snd_iprintf(buffer, "%s :", timer->name);
-               spin_lock_irq(&timer->lock);
-               resolution = snd_timer_hw_resolution(timer);
-               spin_unlock_irq(&timer->lock);
+               scoped_guard(spinlock_irq, &timer->lock)
+                       resolution = snd_timer_hw_resolution(timer);
                if (resolution)
                        snd_iprintf(buffer, " %lu.%03luus (%lu ticks)",
                                    resolution / 1000,
@@ -1288,7 +1240,6 @@ static void snd_timer_proc_read(struct snd_info_entry *entry,
                                                  SNDRV_TIMER_IFLG_RUNNING))
                                    ? "running" : "stopped");
        }
-       mutex_unlock(&register_mutex);
 }
 
 static struct snd_info_entry *snd_timer_proc_entry;
@@ -1329,7 +1280,7 @@ static void snd_timer_user_interrupt(struct snd_timer_instance *timeri,
        struct snd_timer_read *r;
        int prev;
 
-       spin_lock(&tu->qlock);
+       guard(spinlock)(&tu->qlock);
        if (tu->qused > 0) {
                prev = tu->qtail == 0 ? tu->queue_size - 1 : tu->qtail - 1;
                r = &tu->queue[prev];
@@ -1348,7 +1299,6 @@ static void snd_timer_user_interrupt(struct snd_timer_instance *timeri,
                tu->qused++;
        }
       __wake:
-       spin_unlock(&tu->qlock);
        snd_kill_fasync(tu->fasync, SIGIO, POLL_IN);
        wake_up(&tu->qchange_sleep);
 }
@@ -1372,7 +1322,6 @@ static void snd_timer_user_ccallback(struct snd_timer_instance *timeri,
 {
        struct snd_timer_user *tu = timeri->callback_data;
        struct snd_timer_tread64 r1;
-       unsigned long flags;
 
        if (event >= SNDRV_TIMER_EVENT_START &&
            event <= SNDRV_TIMER_EVENT_PAUSE)
@@ -1384,9 +1333,8 @@ static void snd_timer_user_ccallback(struct snd_timer_instance *timeri,
        r1.tstamp_sec = tstamp->tv_sec;
        r1.tstamp_nsec = tstamp->tv_nsec;
        r1.val = resolution;
-       spin_lock_irqsave(&tu->qlock, flags);
-       snd_timer_user_append_to_tqueue(tu, &r1);
-       spin_unlock_irqrestore(&tu->qlock, flags);
+       scoped_guard(spinlock_irqsave, &tu->qlock)
+               snd_timer_user_append_to_tqueue(tu, &r1);
        snd_kill_fasync(tu->fasync, SIGIO, POLL_IN);
        wake_up(&tu->qchange_sleep);
 }
@@ -1410,51 +1358,48 @@ static void snd_timer_user_tinterrupt(struct snd_timer_instance *timeri,
 
        memset(&r1, 0, sizeof(r1));
        memset(&tstamp, 0, sizeof(tstamp));
-       spin_lock(&tu->qlock);
-       if ((tu->filter & ((1 << SNDRV_TIMER_EVENT_RESOLUTION) |
-                          (1 << SNDRV_TIMER_EVENT_TICK))) == 0) {
-               spin_unlock(&tu->qlock);
-               return;
-       }
-       if (tu->last_resolution != resolution || ticks > 0) {
-               if (timer_tstamp_monotonic)
-                       ktime_get_ts64(&tstamp);
-               else
-                       ktime_get_real_ts64(&tstamp);
-       }
-       if ((tu->filter & (1 << SNDRV_TIMER_EVENT_RESOLUTION)) &&
-           tu->last_resolution != resolution) {
-               r1.event = SNDRV_TIMER_EVENT_RESOLUTION;
+       scoped_guard(spinlock, &tu->qlock) {
+               if ((tu->filter & ((1 << SNDRV_TIMER_EVENT_RESOLUTION) |
+                                  (1 << SNDRV_TIMER_EVENT_TICK))) == 0)
+                       return;
+               if (tu->last_resolution != resolution || ticks > 0) {
+                       if (timer_tstamp_monotonic)
+                               ktime_get_ts64(&tstamp);
+                       else
+                               ktime_get_real_ts64(&tstamp);
+               }
+               if ((tu->filter & (1 << SNDRV_TIMER_EVENT_RESOLUTION)) &&
+                   tu->last_resolution != resolution) {
+                       r1.event = SNDRV_TIMER_EVENT_RESOLUTION;
+                       r1.tstamp_sec = tstamp.tv_sec;
+                       r1.tstamp_nsec = tstamp.tv_nsec;
+                       r1.val = resolution;
+                       snd_timer_user_append_to_tqueue(tu, &r1);
+                       tu->last_resolution = resolution;
+                       append++;
+               }
+               if ((tu->filter & (1 << SNDRV_TIMER_EVENT_TICK)) == 0)
+                       break;
+               if (ticks == 0)
+                       break;
+               if (tu->qused > 0) {
+                       prev = tu->qtail == 0 ? tu->queue_size - 1 : tu->qtail - 1;
+                       r = &tu->tqueue[prev];
+                       if (r->event == SNDRV_TIMER_EVENT_TICK) {
+                               r->tstamp_sec = tstamp.tv_sec;
+                               r->tstamp_nsec = tstamp.tv_nsec;
+                               r->val += ticks;
+                               append++;
+                               break;
+                       }
+               }
+               r1.event = SNDRV_TIMER_EVENT_TICK;
                r1.tstamp_sec = tstamp.tv_sec;
                r1.tstamp_nsec = tstamp.tv_nsec;
-               r1.val = resolution;
+               r1.val = ticks;
                snd_timer_user_append_to_tqueue(tu, &r1);
-               tu->last_resolution = resolution;
                append++;
        }
-       if ((tu->filter & (1 << SNDRV_TIMER_EVENT_TICK)) == 0)
-               goto __wake;
-       if (ticks == 0)
-               goto __wake;
-       if (tu->qused > 0) {
-               prev = tu->qtail == 0 ? tu->queue_size - 1 : tu->qtail - 1;
-               r = &tu->tqueue[prev];
-               if (r->event == SNDRV_TIMER_EVENT_TICK) {
-                       r->tstamp_sec = tstamp.tv_sec;
-                       r->tstamp_nsec = tstamp.tv_nsec;
-                       r->val += ticks;
-                       append++;
-                       goto __wake;
-               }
-       }
-       r1.event = SNDRV_TIMER_EVENT_TICK;
-       r1.tstamp_sec = tstamp.tv_sec;
-       r1.tstamp_nsec = tstamp.tv_nsec;
-       r1.val = ticks;
-       snd_timer_user_append_to_tqueue(tu, &r1);
-       append++;
-      __wake:
-       spin_unlock(&tu->qlock);
        if (append == 0)
                return;
        snd_kill_fasync(tu->fasync, SIGIO, POLL_IN);
@@ -1476,14 +1421,13 @@ static int realloc_user_queue(struct snd_timer_user *tu, int size)
                        return -ENOMEM;
        }
 
-       spin_lock_irq(&tu->qlock);
+       guard(spinlock_irq)(&tu->qlock);
        kfree(tu->queue);
        kfree(tu->tqueue);
        tu->queue_size = size;
        tu->queue = queue;
        tu->tqueue = tqueue;
        tu->qhead = tu->qtail = tu->qused = 0;
-       spin_unlock_irq(&tu->qlock);
 
        return 0;
 }
@@ -1519,12 +1463,12 @@ static int snd_timer_user_release(struct inode *inode, struct file *file)
        if (file->private_data) {
                tu = file->private_data;
                file->private_data = NULL;
-               mutex_lock(&tu->ioctl_lock);
-               if (tu->timeri) {
-                       snd_timer_close(tu->timeri);
-                       snd_timer_instance_free(tu->timeri);
+               scoped_guard(mutex, &tu->ioctl_lock) {
+                       if (tu->timeri) {
+                               snd_timer_close(tu->timeri);
+                               snd_timer_instance_free(tu->timeri);
+                       }
                }
-               mutex_unlock(&tu->ioctl_lock);
                snd_fasync_free(tu->fasync);
                kfree(tu->queue);
                kfree(tu->tqueue);
@@ -1559,7 +1503,7 @@ static int snd_timer_user_next_device(struct snd_timer_id __user *_tid)
 
        if (copy_from_user(&id, _tid, sizeof(id)))
                return -EFAULT;
-       mutex_lock(&register_mutex);
+       guard(mutex)(&register_mutex);
        if (id.dev_class < 0) {         /* first item */
                if (list_empty(&snd_timer_list))
                        snd_timer_user_zero_id(&id);
@@ -1636,7 +1580,6 @@ static int snd_timer_user_next_device(struct snd_timer_id __user *_tid)
                        snd_timer_user_zero_id(&id);
                }
        }
-       mutex_unlock(&register_mutex);
        if (copy_to_user(_tid, &id, sizeof(*_tid)))
                return -EFAULT;
        return 0;
@@ -1649,7 +1592,6 @@ static int snd_timer_user_ginfo(struct file *file,
        struct snd_timer_id tid;
        struct snd_timer *t;
        struct list_head *p;
-       int err = 0;
 
        ginfo = memdup_user(_ginfo, sizeof(*ginfo));
        if (IS_ERR(ginfo))
@@ -1658,56 +1600,42 @@ static int snd_timer_user_ginfo(struct file *file,
        tid = ginfo->tid;
        memset(ginfo, 0, sizeof(*ginfo));
        ginfo->tid = tid;
-       mutex_lock(&register_mutex);
+       guard(mutex)(&register_mutex);
        t = snd_timer_find(&tid);
-       if (t != NULL) {
-               ginfo->card = t->card ? t->card->number : -1;
-               if (t->hw.flags & SNDRV_TIMER_HW_SLAVE)
-                       ginfo->flags |= SNDRV_TIMER_FLG_SLAVE;
-               strscpy(ginfo->id, t->id, sizeof(ginfo->id));
-               strscpy(ginfo->name, t->name, sizeof(ginfo->name));
-               spin_lock_irq(&t->lock);
+       if (!t)
+               return -ENODEV;
+       ginfo->card = t->card ? t->card->number : -1;
+       if (t->hw.flags & SNDRV_TIMER_HW_SLAVE)
+               ginfo->flags |= SNDRV_TIMER_FLG_SLAVE;
+       strscpy(ginfo->id, t->id, sizeof(ginfo->id));
+       strscpy(ginfo->name, t->name, sizeof(ginfo->name));
+       scoped_guard(spinlock_irq, &t->lock)
                ginfo->resolution = snd_timer_hw_resolution(t);
-               spin_unlock_irq(&t->lock);
-               if (t->hw.resolution_min > 0) {
-                       ginfo->resolution_min = t->hw.resolution_min;
-                       ginfo->resolution_max = t->hw.resolution_max;
-               }
-               list_for_each(p, &t->open_list_head) {
-                       ginfo->clients++;
-               }
-       } else {
-               err = -ENODEV;
+       if (t->hw.resolution_min > 0) {
+               ginfo->resolution_min = t->hw.resolution_min;
+               ginfo->resolution_max = t->hw.resolution_max;
        }
-       mutex_unlock(&register_mutex);
-       if (err >= 0 && copy_to_user(_ginfo, ginfo, sizeof(*ginfo)))
-               err = -EFAULT;
-       return err;
+       list_for_each(p, &t->open_list_head) {
+               ginfo->clients++;
+       }
+       if (copy_to_user(_ginfo, ginfo, sizeof(*ginfo)))
+               return -EFAULT;
+       return 0;
 }
 
 static int timer_set_gparams(struct snd_timer_gparams *gparams)
 {
        struct snd_timer *t;
-       int err;
 
-       mutex_lock(&register_mutex);
+       guard(mutex)(&register_mutex);
        t = snd_timer_find(&gparams->tid);
-       if (!t) {
-               err = -ENODEV;
-               goto _error;
-       }
-       if (!list_empty(&t->open_list_head)) {
-               err = -EBUSY;
-               goto _error;
-       }
-       if (!t->hw.set_period) {
-               err = -ENOSYS;
-               goto _error;
-       }
-       err = t->hw.set_period(t, gparams->period_num, gparams->period_den);
-_error:
-       mutex_unlock(&register_mutex);
-       return err;
+       if (!t)
+               return -ENODEV;
+       if (!list_empty(&t->open_list_head))
+               return -EBUSY;
+       if (!t->hw.set_period)
+               return -ENOSYS;
+       return t->hw.set_period(t, gparams->period_num, gparams->period_den);
 }
 
 static int snd_timer_user_gparams(struct file *file,
@@ -1733,10 +1661,10 @@ static int snd_timer_user_gstatus(struct file *file,
        tid = gstatus.tid;
        memset(&gstatus, 0, sizeof(gstatus));
        gstatus.tid = tid;
-       mutex_lock(&register_mutex);
+       guard(mutex)(&register_mutex);
        t = snd_timer_find(&tid);
        if (t != NULL) {
-               spin_lock_irq(&t->lock);
+               guard(spinlock_irq)(&t->lock);
                gstatus.resolution = snd_timer_hw_resolution(t);
                if (t->hw.precise_resolution) {
                        t->hw.precise_resolution(t, &gstatus.resolution_num,
@@ -1745,11 +1673,9 @@ static int snd_timer_user_gstatus(struct file *file,
                        gstatus.resolution_num = gstatus.resolution;
                        gstatus.resolution_den = 1000000000uL;
                }
-               spin_unlock_irq(&t->lock);
        } else {
                err = -ENODEV;
        }
-       mutex_unlock(&register_mutex);
        if (err >= 0 && copy_to_user(_gstatus, &gstatus, sizeof(gstatus)))
                err = -EFAULT;
        return err;
@@ -1821,9 +1747,8 @@ static int snd_timer_user_info(struct file *file,
                info->flags |= SNDRV_TIMER_FLG_SLAVE;
        strscpy(info->id, t->id, sizeof(info->id));
        strscpy(info->name, t->name, sizeof(info->name));
-       spin_lock_irq(&t->lock);
-       info->resolution = snd_timer_hw_resolution(t);
-       spin_unlock_irq(&t->lock);
+       scoped_guard(spinlock_irq, &t->lock)
+               info->resolution = snd_timer_hw_resolution(t);
        if (copy_to_user(_info, info, sizeof(*_info)))
                return -EFAULT;
        return 0;
@@ -1884,45 +1809,47 @@ static int snd_timer_user_params(struct file *file,
                goto _end;
        }
        snd_timer_stop(tu->timeri);
-       spin_lock_irq(&t->lock);
-       tu->timeri->flags &= ~(SNDRV_TIMER_IFLG_AUTO|
-                              SNDRV_TIMER_IFLG_EXCLUSIVE|
-                              SNDRV_TIMER_IFLG_EARLY_EVENT);
-       if (params.flags & SNDRV_TIMER_PSFLG_AUTO)
-               tu->timeri->flags |= SNDRV_TIMER_IFLG_AUTO;
-       if (params.flags & SNDRV_TIMER_PSFLG_EXCLUSIVE)
-               tu->timeri->flags |= SNDRV_TIMER_IFLG_EXCLUSIVE;
-       if (params.flags & SNDRV_TIMER_PSFLG_EARLY_EVENT)
-               tu->timeri->flags |= SNDRV_TIMER_IFLG_EARLY_EVENT;
-       spin_unlock_irq(&t->lock);
+       scoped_guard(spinlock_irq, &t->lock) {
+               tu->timeri->flags &= ~(SNDRV_TIMER_IFLG_AUTO|
+                                      SNDRV_TIMER_IFLG_EXCLUSIVE|
+                                      SNDRV_TIMER_IFLG_EARLY_EVENT);
+               if (params.flags & SNDRV_TIMER_PSFLG_AUTO)
+                       tu->timeri->flags |= SNDRV_TIMER_IFLG_AUTO;
+               if (params.flags & SNDRV_TIMER_PSFLG_EXCLUSIVE)
+                       tu->timeri->flags |= SNDRV_TIMER_IFLG_EXCLUSIVE;
+               if (params.flags & SNDRV_TIMER_PSFLG_EARLY_EVENT)
+                       tu->timeri->flags |= SNDRV_TIMER_IFLG_EARLY_EVENT;
+       }
        if (params.queue_size > 0 &&
            (unsigned int)tu->queue_size != params.queue_size) {
                err = realloc_user_queue(tu, params.queue_size);
                if (err < 0)
                        goto _end;
        }
-       spin_lock_irq(&tu->qlock);
-       tu->qhead = tu->qtail = tu->qused = 0;
-       if (tu->timeri->flags & SNDRV_TIMER_IFLG_EARLY_EVENT) {
-               if (tu->tread) {
-                       struct snd_timer_tread64 tread;
-                       memset(&tread, 0, sizeof(tread));
-                       tread.event = SNDRV_TIMER_EVENT_EARLY;
-                       tread.tstamp_sec = 0;
-                       tread.tstamp_nsec = 0;
-                       tread.val = 0;
-                       snd_timer_user_append_to_tqueue(tu, &tread);
-               } else {
-                       struct snd_timer_read *r = &tu->queue[0];
-                       r->resolution = 0;
-                       r->ticks = 0;
-                       tu->qused++;
-                       tu->qtail++;
+       scoped_guard(spinlock_irq, &tu->qlock) {
+               tu->qhead = tu->qtail = tu->qused = 0;
+               if (tu->timeri->flags & SNDRV_TIMER_IFLG_EARLY_EVENT) {
+                       if (tu->tread) {
+                               struct snd_timer_tread64 tread;
+
+                               memset(&tread, 0, sizeof(tread));
+                               tread.event = SNDRV_TIMER_EVENT_EARLY;
+                               tread.tstamp_sec = 0;
+                               tread.tstamp_nsec = 0;
+                               tread.val = 0;
+                               snd_timer_user_append_to_tqueue(tu, &tread);
+                       } else {
+                               struct snd_timer_read *r = &tu->queue[0];
+
+                               r->resolution = 0;
+                               r->ticks = 0;
+                               tu->qused++;
+                               tu->qtail++;
+                       }
                }
+               tu->filter = params.filter;
+               tu->ticks = params.ticks;
        }
-       tu->filter = params.filter;
-       tu->ticks = params.ticks;
-       spin_unlock_irq(&tu->qlock);
        err = 0;
  _end:
        if (copy_to_user(_params, &params, sizeof(params)))
@@ -1945,9 +1872,8 @@ static int snd_timer_user_status32(struct file *file,
        status.resolution = snd_timer_resolution(tu->timeri);
        status.lost = tu->timeri->lost;
        status.overrun = tu->overrun;
-       spin_lock_irq(&tu->qlock);
-       status.queue = tu->qused;
-       spin_unlock_irq(&tu->qlock);
+       scoped_guard(spinlock_irq, &tu->qlock)
+               status.queue = tu->qused;
        if (copy_to_user(_status, &status, sizeof(status)))
                return -EFAULT;
        return 0;
@@ -1968,9 +1894,8 @@ static int snd_timer_user_status64(struct file *file,
        status.resolution = snd_timer_resolution(tu->timeri);
        status.lost = tu->timeri->lost;
        status.overrun = tu->overrun;
-       spin_lock_irq(&tu->qlock);
-       status.queue = tu->qused;
-       spin_unlock_irq(&tu->qlock);
+       scoped_guard(spinlock_irq, &tu->qlock)
+               status.queue = tu->qused;
        if (copy_to_user(_status, &status, sizeof(status)))
                return -EFAULT;
        return 0;
@@ -2128,12 +2053,9 @@ static long snd_timer_user_ioctl(struct file *file, unsigned int cmd,
                                 unsigned long arg)
 {
        struct snd_timer_user *tu = file->private_data;
-       long ret;
 
-       mutex_lock(&tu->ioctl_lock);
-       ret = __snd_timer_user_ioctl(file, cmd, arg, false);
-       mutex_unlock(&tu->ioctl_lock);
-       return ret;
+       guard(mutex)(&tu->ioctl_lock);
+       return __snd_timer_user_ioctl(file, cmd, arg, false);
 }
 
 static int snd_timer_user_fasync(int fd, struct file * file, int on)
@@ -2260,12 +2182,11 @@ static __poll_t snd_timer_user_poll(struct file *file, poll_table * wait)
         poll_wait(file, &tu->qchange_sleep, wait);
 
        mask = 0;
-       spin_lock_irq(&tu->qlock);
+       guard(spinlock_irq)(&tu->qlock);
        if (tu->qused)
                mask |= EPOLLIN | EPOLLRDNORM;
        if (tu->disconnected)
                mask |= EPOLLERR;
-       spin_unlock_irq(&tu->qlock);
 
        return mask;
 }
index ee973b7b804499a52936100bdfcbe4235aeb4a28..4ae9eaeb5afb1a9351e4caf872f4562b298524fe 100644 (file)
@@ -115,10 +115,7 @@ static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd,
                                        unsigned long arg)
 {
        struct snd_timer_user *tu = file->private_data;
-       long ret;
 
-       mutex_lock(&tu->ioctl_lock);
-       ret = __snd_timer_user_ioctl_compat(file, cmd, arg);
-       mutex_unlock(&tu->ioctl_lock);
-       return ret;
+       guard(mutex)(&tu->ioctl_lock);
+       return __snd_timer_user_ioctl_compat(file, cmd, arg);
 }