@@ -506,6 +506,12 @@ static int do_timer_create(clockid_t which_clock, struct sigevent *event,
506506 return - EAGAIN ;
507507
508508 spin_lock_init (& new_timer -> it_lock );
509+
510+ /*
511+ * Add the timer to the hash table. The timer is not yet valid
512+ * because new_timer::it_signal is still NULL. The timer id is also
513+ * not yet visible to user space.
514+ */
509515 new_timer_id = posix_timer_add (new_timer );
510516 if (new_timer_id < 0 ) {
511517 error = new_timer_id ;
@@ -551,6 +557,7 @@ static int do_timer_create(clockid_t which_clock, struct sigevent *event,
551557 goto out ;
552558
553559 spin_lock_irq (& current -> sighand -> siglock );
560+ /* This makes the timer valid in the hash table */
554561 new_timer -> it_signal = current -> signal ;
555562 list_add (& new_timer -> list , & current -> signal -> posix_timers );
556563 spin_unlock_irq (& current -> sighand -> siglock );
@@ -597,13 +604,6 @@ COMPAT_SYSCALL_DEFINE3(timer_create, clockid_t, which_clock,
597604}
598605#endif
599606
600- /*
601- * Locking issues: We need to protect the result of the id look up until
602- * we get the timer locked down so it is not deleted under us. The
603- * removal is done under the idr spinlock so we use that here to bridge
604- * the find to the timer lock. To avoid a dead lock, the timer id MUST
605- * be release with out holding the timer lock.
606- */
607607static struct k_itimer * __lock_timer (timer_t timer_id , unsigned long * flags )
608608{
609609 struct k_itimer * timr ;
@@ -615,10 +615,35 @@ static struct k_itimer *__lock_timer(timer_t timer_id, unsigned long *flags)
615615 if ((unsigned long long )timer_id > INT_MAX )
616616 return NULL ;
617617
618+ /*
619+ * The hash lookup and the timers are RCU protected.
620+ *
621+ * Timers are added to the hash in invalid state where
622+ * timr::it_signal == NULL. timer::it_signal is only set after the
623+ * rest of the initialization succeeded.
624+ *
625+ * Timer destruction happens in steps:
626+ * 1) Set timr::it_signal to NULL with timr::it_lock held
627+ * 2) Release timr::it_lock
628+ * 3) Remove from the hash under hash_lock
629+ * 4) Call RCU for removal after the grace period
630+ *
631+ * Holding rcu_read_lock() accross the lookup ensures that
632+ * the timer cannot be freed.
633+ *
634+ * The lookup validates locklessly that timr::it_signal ==
635+ * current::it_signal and timr::it_id == @timer_id. timr::it_id
636+ * can't change, but timr::it_signal becomes NULL during
637+ * destruction.
638+ */
618639 rcu_read_lock ();
619640 timr = posix_timer_by_id (timer_id );
620641 if (timr ) {
621642 spin_lock_irqsave (& timr -> it_lock , * flags );
643+ /*
644+ * Validate under timr::it_lock that timr::it_signal is
645+ * still valid. Pairs with #1 above.
646+ */
622647 if (timr -> it_signal == current -> signal ) {
623648 rcu_read_unlock ();
624649 return timr ;
0 commit comments