diff options
-rw-r--r-- | include/linux/sched/signal.h | 2 | ||||
-rw-r--r-- | kernel/time/posix-timers.c | 14 |
2 files changed, 6 insertions, 10 deletions
diff --git a/include/linux/sched/signal.h b/include/linux/sched/signal.h index d5d03d919df8..72649d7fce2a 100644 --- a/include/linux/sched/signal.h +++ b/include/linux/sched/signal.h @@ -136,7 +136,7 @@ struct signal_struct { #ifdef CONFIG_POSIX_TIMERS /* POSIX.1b Interval Timers */ - unsigned int next_posix_timer_id; + atomic_t next_posix_timer_id; struct hlist_head posix_timers; struct hlist_head ignored_posix_timers; diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c index 991d12abae45..f9a70c1373b6 100644 --- a/kernel/time/posix-timers.c +++ b/kernel/time/posix-timers.c @@ -119,21 +119,17 @@ static bool posix_timer_hashed(struct hlist_head *head, struct signal_struct *si static int posix_timer_add(struct k_itimer *timer) { struct signal_struct *sig = current->signal; - struct hlist_head *head; - unsigned int cnt, id; /* * FIXME: Replace this by a per signal struct xarray once there is * a plan to handle the resulting CRIU regression gracefully. */ - for (cnt = 0; cnt <= INT_MAX; cnt++) { - spin_lock(&hash_lock); - id = sig->next_posix_timer_id; - - /* Write the next ID back. Clamp it to the positive space */ - sig->next_posix_timer_id = (id + 1) & INT_MAX; + for (unsigned int cnt = 0; cnt <= INT_MAX; cnt++) { + /* Get the next timer ID and clamp it to positive space */ + unsigned int id = atomic_fetch_inc(&sig->next_posix_timer_id) & INT_MAX; + struct hlist_head *head = &posix_timers_hashtable[hash(sig, id)]; - head = &posix_timers_hashtable[hash(sig, id)]; + spin_lock(&hash_lock); if (!posix_timer_hashed(head, sig, id)) { /* * Set the timer ID and the signal pointer to make |