diff options
| -rw-r--r-- | include/linux/rcupdate.h | 4 | ||||
| -rw-r--r-- | kernel/signal.c | 24 | ||||
| -rw-r--r-- | tools/objtool/check.c | 22 |
3 files changed, 30 insertions, 20 deletions
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index e679b175b411..65163aa0bb04 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h | |||
| @@ -652,9 +652,7 @@ static inline void rcu_read_lock(void) | |||
| 652 | * Unfortunately, this function acquires the scheduler's runqueue and | 652 | * Unfortunately, this function acquires the scheduler's runqueue and |
| 653 | * priority-inheritance spinlocks. This means that deadlock could result | 653 | * priority-inheritance spinlocks. This means that deadlock could result |
| 654 | * if the caller of rcu_read_unlock() already holds one of these locks or | 654 | * if the caller of rcu_read_unlock() already holds one of these locks or |
| 655 | * any lock that is ever acquired while holding them; or any lock which | 655 | * any lock that is ever acquired while holding them. |
| 656 | * can be taken from interrupt context because rcu_boost()->rt_mutex_lock() | ||
| 657 | * does not disable irqs while taking ->wait_lock. | ||
| 658 | * | 656 | * |
| 659 | * That said, RCU readers are never priority boosted unless they were | 657 | * That said, RCU readers are never priority boosted unless they were |
| 660 | * preempted. Therefore, one way to avoid deadlock is to make sure | 658 | * preempted. Therefore, one way to avoid deadlock is to make sure |
diff --git a/kernel/signal.c b/kernel/signal.c index 0f865d67415d..8d8a940422a8 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
| @@ -1244,19 +1244,12 @@ struct sighand_struct *__lock_task_sighand(struct task_struct *tsk, | |||
| 1244 | { | 1244 | { |
| 1245 | struct sighand_struct *sighand; | 1245 | struct sighand_struct *sighand; |
| 1246 | 1246 | ||
| 1247 | rcu_read_lock(); | ||
| 1247 | for (;;) { | 1248 | for (;;) { |
| 1248 | /* | ||
| 1249 | * Disable interrupts early to avoid deadlocks. | ||
| 1250 | * See rcu_read_unlock() comment header for details. | ||
| 1251 | */ | ||
| 1252 | local_irq_save(*flags); | ||
| 1253 | rcu_read_lock(); | ||
| 1254 | sighand = rcu_dereference(tsk->sighand); | 1249 | sighand = rcu_dereference(tsk->sighand); |
| 1255 | if (unlikely(sighand == NULL)) { | 1250 | if (unlikely(sighand == NULL)) |
| 1256 | rcu_read_unlock(); | ||
| 1257 | local_irq_restore(*flags); | ||
| 1258 | break; | 1251 | break; |
| 1259 | } | 1252 | |
| 1260 | /* | 1253 | /* |
| 1261 | * This sighand can be already freed and even reused, but | 1254 | * This sighand can be already freed and even reused, but |
| 1262 | * we rely on SLAB_TYPESAFE_BY_RCU and sighand_ctor() which | 1255 | * we rely on SLAB_TYPESAFE_BY_RCU and sighand_ctor() which |
| @@ -1268,15 +1261,12 @@ struct sighand_struct *__lock_task_sighand(struct task_struct *tsk, | |||
| 1268 | * __exit_signal(). In the latter case the next iteration | 1261 | * __exit_signal(). In the latter case the next iteration |
| 1269 | * must see ->sighand == NULL. | 1262 | * must see ->sighand == NULL. |
| 1270 | */ | 1263 | */ |
| 1271 | spin_lock(&sighand->siglock); | 1264 | spin_lock_irqsave(&sighand->siglock, *flags); |
| 1272 | if (likely(sighand == tsk->sighand)) { | 1265 | if (likely(sighand == tsk->sighand)) |
| 1273 | rcu_read_unlock(); | ||
| 1274 | break; | 1266 | break; |
| 1275 | } | 1267 | spin_unlock_irqrestore(&sighand->siglock, *flags); |
| 1276 | spin_unlock(&sighand->siglock); | ||
| 1277 | rcu_read_unlock(); | ||
| 1278 | local_irq_restore(*flags); | ||
| 1279 | } | 1268 | } |
| 1269 | rcu_read_unlock(); | ||
| 1280 | 1270 | ||
| 1281 | return sighand; | 1271 | return sighand; |
| 1282 | } | 1272 | } |
diff --git a/tools/objtool/check.c b/tools/objtool/check.c index 3a31b238f885..38047c6aa575 100644 --- a/tools/objtool/check.c +++ b/tools/objtool/check.c | |||
| @@ -543,6 +543,28 @@ static int add_jump_destinations(struct objtool_file *file) | |||
| 543 | dest_off); | 543 | dest_off); |
| 544 | return -1; | 544 | return -1; |
| 545 | } | 545 | } |
| 546 | |||
| 547 | /* | ||
| 548 | * For GCC 8+, create parent/child links for any cold | ||
| 549 | * subfunctions. This is _mostly_ redundant with a similar | ||
| 550 | * initialization in read_symbols(). | ||
| 551 | * | ||
| 552 | * If a function has aliases, we want the *first* such function | ||
| 553 | * in the symbol table to be the subfunction's parent. In that | ||
| 554 | * case we overwrite the initialization done in read_symbols(). | ||
| 555 | * | ||
| 556 | * However this code can't completely replace the | ||
| 557 | * read_symbols() code because this doesn't detect the case | ||
| 558 | * where the parent function's only reference to a subfunction | ||
| 559 | * is through a switch table. | ||
| 560 | */ | ||
| 561 | if (insn->func && insn->jump_dest->func && | ||
| 562 | insn->func != insn->jump_dest->func && | ||
| 563 | !strstr(insn->func->name, ".cold.") && | ||
| 564 | strstr(insn->jump_dest->func->name, ".cold.")) { | ||
| 565 | insn->func->cfunc = insn->jump_dest->func; | ||
| 566 | insn->jump_dest->func->pfunc = insn->func; | ||
| 567 | } | ||
| 546 | } | 568 | } |
| 547 | 569 | ||
| 548 | return 0; | 570 | return 0; |
