diff options
author | Takashi Iwai <tiwai@suse.de> | 2020-03-30 13:43:00 +0200 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2020-03-30 13:43:00 +0200 |
commit | 3c22baeab40b2f8e75907cfd7aa69147d5343d2c (patch) | |
tree | e8300e52242ae3a9c7bfe6089ee7125324095e27 /kernel/signal.c | |
parent | aa21c3d4b941739651e77747d2f7a20a6c1d87bc (diff) | |
parent | 1c521d7e62262793789845989edca57dea24eb7d (diff) |
Merge tag 'asoc-v5.7' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus
ASoC: Updates for v5.7
This is a very big update for the core since Morimoto-san has been
rather busy continuing his refactorings to clean up a lot of the cruft
that we have accumilated over the years. We've also gained several new
drivers, including initial (but still not complete) parts of the Intel
SoundWire support.
- Lots of refactorings to modernize the code from Morimoto-san.
- Conversion of SND_SOC_ALL_CODECS to use imply from Geert Uytterhoeven.
- Continued refactoring and fixing of the Intel support.
- Soundwire and more advanced clocking support for Realtek RT5682.
- Support for amlogic GX, Meson 8, Meson 8B and T9015 DAC, Broadcom
DSL/PON, Ingenic JZ4760 and JZ4770, Realtek RL6231, and TI TAS2563 and
TLV320ADCX140.
Diffstat (limited to 'kernel/signal.c')
-rw-r--r-- | kernel/signal.c | 23 |
1 files changed, 14 insertions, 9 deletions
diff --git a/kernel/signal.c b/kernel/signal.c index 9ad8dea93dbb2..5b2396350dd18 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -413,27 +413,32 @@ __sigqueue_alloc(int sig, struct task_struct *t, gfp_t flags, int override_rlimi { struct sigqueue *q = NULL; struct user_struct *user; + int sigpending; /* * Protect access to @t credentials. This can go away when all * callers hold rcu read lock. + * + * NOTE! A pending signal will hold on to the user refcount, + * and we get/put the refcount only when the sigpending count + * changes from/to zero. */ rcu_read_lock(); - user = get_uid(__task_cred(t)->user); - atomic_inc(&user->sigpending); + user = __task_cred(t)->user; + sigpending = atomic_inc_return(&user->sigpending); + if (sigpending == 1) + get_uid(user); rcu_read_unlock(); - if (override_rlimit || - atomic_read(&user->sigpending) <= - task_rlimit(t, RLIMIT_SIGPENDING)) { + if (override_rlimit || likely(sigpending <= task_rlimit(t, RLIMIT_SIGPENDING))) { q = kmem_cache_alloc(sigqueue_cachep, flags); } else { print_dropped_signal(sig); } if (unlikely(q == NULL)) { - atomic_dec(&user->sigpending); - free_uid(user); + if (atomic_dec_and_test(&user->sigpending)) + free_uid(user); } else { INIT_LIST_HEAD(&q->list); q->flags = 0; @@ -447,8 +452,8 @@ static void __sigqueue_free(struct sigqueue *q) { if (q->flags & SIGQUEUE_PREALLOC) return; - atomic_dec(&q->user->sigpending); - free_uid(q->user); + if (atomic_dec_and_test(&q->user->sigpending)) + free_uid(q->user); kmem_cache_free(sigqueue_cachep, q); } |