On Thu, Apr 28, 2022 at 03:49:11PM -0500, Eric W. Biederman wrote: > static void lock_parents_siglocks(bool lock_tracer) > __releases(¤t->sighand->siglock) > __acquires(¤t->sighand->siglock) > __acquires(¤t->real_parent->sighand->siglock) > __acquires(¤t->parent->sighand->siglock) > { > struct task_struct *me = current; > struct sighand_struct *m_sighand = me->sighand; > > lockdep_assert_held(&m_sighand->siglock); > > rcu_read_lock(); > for (;;) { > struct task_struct *parent, *tracer; > struct sighand_struct *p_sighand, *t_sighand, *s1, *s2, *s3; > > parent = me->real_parent; > tracer = lock_tracer? me->parent : parent; > > p_sighand = rcu_dereference(parent->sighand); > t_sighand = rcu_dereference(tracer->sighand); > > /* Sort the sighands so that s1 >= s2 >= s3 */ > s1 = m_sighand; > s2 = p_sighand; > s3 = t_sighand; > if (s1 > s2) > swap(s1, s2); > if (s1 > s3) > swap(s1, s3); > if (s2 > s3) > swap(s2, s3); > > if (s1 != m_sighand) { > spin_unlock(&m_sighand->siglock); > spin_lock(&s1->siglock); > } > > if (s1 != s2) > spin_lock_nested(&s2->siglock, SIGLOCK_LOCK_SECOND); > if (s2 != s3) > spin_lock_nested(&s3->siglock, SIGLOCK_LOCK_THIRD); >
Might as well just use 1 and 2 for subclass at this point, or use SIGLOCK_LOCK_FIRST below. > if (likely((me->real_parent == parent) && > (me->parent == tracer) && > (parent->sighand == p_sighand) && > (tracer->sighand == t_sighand))) { > break; > } > spin_unlock(&p_sighand->siglock); > if (t_sighand != p_sighand) > spin_unlock(&t_sighand->siglock); Indent fail above ^, also you likey need this: /* * Since [pt]_sighand will likely change if we go * around, and m_sighand is the only one held, make sure * it is subclass-0, since the above 's1 != m_sighand' * clause very much relies on that. */ lock_set_subclass(&m_sighand->siglock, 0, _RET_IP_); > continue; > } > rcu_read_unlock(); > } > > Eric _______________________________________________ linux-um mailing list linux-um@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-um