| @@ -2152,6 +2152,8 @@ static inline struct mutex *__get_task_blocked_on(struct task_struct *p) · 2151 unmodified lines |
| 2152 | 2152 | |
| 2153 | 2153 | static inline void __set_task_blocked_on(struct task_struct *p, struct mutex *m) |
| 2154 | 2154 | { |
| 2155 | + struct mutex *blocked_on = READ_ONCE(p->blocked_on); |
| 2156 | + |
| 2155 | 2157 | WARN_ON_ONCE(!m); |
| 2156 | 2158 | /* The task should only be setting itself as blocked */ |
| 2157 | 2159 | WARN_ON_ONCE(p != current); |
| @@ -2162,8 +2164,8 @@ static inline void __set_task_blocked_on(struct task_struct *p, struct mutex *m) · 4 unmodified lines |
| 2162 | 2164 | * with a different mutex. Note, setting it to the same |
| 2163 | 2165 | * lock repeatedly is ok. |
| 2164 | 2166 | */ |
| 2165 | | − WARN_ON_ONCE(p->blocked_on && p->blocked_on != m); |
| 2166 | | − p->blocked_on = m; |
| 2167 | + WARN_ON_ONCE(blocked_on && blocked_on != m); |
| 2168 | + WRITE_ONCE(p->blocked_on, m); |
| 2167 | 2169 | } |
| 2168 | 2170 | |
| 2169 | 2171 | static inline void set_task_blocked_on(struct task_struct *p, struct mutex *m) |
| @@ -2174,16 +2176,19 @@ static inline void set_task_blocked_on(struct task_struct *p, struct mutex *m) · 4 unmodified lines |
| 2174 | 2176 | |
| 2175 | 2177 | static inline void __clear_task_blocked_on(struct task_struct *p, struct mutex *m) |
| 2176 | 2178 | { |
| 2177 | | − WARN_ON_ONCE(!m); |
| 2178 | | − /* Currently we serialize blocked_on under the mutex::wait_lock */ |
| 2179 | | − lockdep_assert_held_once(&m->wait_lock); |
| 2180 | | − /* |
| 2181 | | − * There may be cases where we re-clear already cleared |
| 2182 | | − * blocked_on relationships, but make sure we are not |
| 2183 | | − * clearing the relationship with a different lock. |
| 2184 | | − */ |
| 2185 | | − WARN_ON_ONCE(m && p->blocked_on && p->blocked_on != m); |
| 2186 | | − p->blocked_on = NULL; |
| 2179 | + if (m) { |
| 2180 | + struct mutex *blocked_on = READ_ONCE(p->blocked_on); |
| 2181 | + |
| 2182 | + /* Currently we serialize blocked_on under the mutex::wait_lock */ |
| 2183 | + lockdep_assert_held_once(&m->wait_lock); |
| 2184 | + /* |
| 2185 | + * There may be cases where we re-clear already cleared |
| 2186 | + * blocked_on relationships, but make sure we are not |
| 2187 | + * clearing the relationship with a different lock. |
| 2188 | + */ |
| 2189 | + WARN_ON_ONCE(blocked_on && blocked_on != m); |
| 2190 | + } |
| 2191 | + WRITE_ONCE(p->blocked_on, NULL); |
| 2187 | 2192 | } |
| 2188 | 2193 | |
| 2189 | 2194 | static inline void clear_task_blocked_on(struct task_struct *p, struct mutex *m) |