summaryrefslogtreecommitdiff
path: root/kernel/signal.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2020-03-30 13:43:00 +0200
committerTakashi Iwai <tiwai@suse.de>2020-03-30 13:43:00 +0200
commit3c22baeab40b2f8e75907cfd7aa69147d5343d2c (patch)
treee8300e52242ae3a9c7bfe6089ee7125324095e27 /kernel/signal.c
parentaa21c3d4b941739651e77747d2f7a20a6c1d87bc (diff)
parent1c521d7e62262793789845989edca57dea24eb7d (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.c23
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);
}