Skip to content

Commit b772b8e

Browse files
committed
Merge branch 'core-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull core fixes from Ingo Molnar: - workaround for gcc asm handling - futex race fixes - objtool build warning fix - two watchdog fixes: a crash fix (revert) and a bug fix for /proc/sys/kernel/watchdog_thresh handling. * 'core-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: objtool: Prevent GCC from merging annotate_unreachable(), take 2 objtool: Resync objtool's instruction decoder source code copy with the kernel's latest version watchdog/hardlockup/perf: Use atomics to track in-use cpu counter watchdog/harclockup/perf: Revert a33d448 ("watchdog/hardlockup/perf: Simplify deferred event destroy") futex: Fix more put_pi_state() vs. exit_pi_state_list() races
2 parents 3131dc4 + ec1e1b6 commit b772b8e

File tree

4 files changed

+33
-10
lines changed

4 files changed

+33
-10
lines changed

include/linux/compiler.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,13 +191,13 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val,
191191
asm("%c0:\n\t" \
192192
".pushsection .discard.reachable\n\t" \
193193
".long %c0b - .\n\t" \
194-
".popsection\n\t" : : "i" (__LINE__)); \
194+
".popsection\n\t" : : "i" (__COUNTER__)); \
195195
})
196196
#define annotate_unreachable() ({ \
197197
asm("%c0:\n\t" \
198198
".pushsection .discard.unreachable\n\t" \
199199
".long %c0b - .\n\t" \
200-
".popsection\n\t" : : "i" (__LINE__)); \
200+
".popsection\n\t" : : "i" (__COUNTER__)); \
201201
})
202202
#define ASM_UNREACHABLE \
203203
"999:\n\t" \

kernel/futex.c

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -903,11 +903,27 @@ void exit_pi_state_list(struct task_struct *curr)
903903
*/
904904
raw_spin_lock_irq(&curr->pi_lock);
905905
while (!list_empty(head)) {
906-
907906
next = head->next;
908907
pi_state = list_entry(next, struct futex_pi_state, list);
909908
key = pi_state->key;
910909
hb = hash_futex(&key);
910+
911+
/*
912+
* We can race against put_pi_state() removing itself from the
913+
* list (a waiter going away). put_pi_state() will first
914+
* decrement the reference count and then modify the list, so
915+
* its possible to see the list entry but fail this reference
916+
* acquire.
917+
*
918+
* In that case; drop the locks to let put_pi_state() make
919+
* progress and retry the loop.
920+
*/
921+
if (!atomic_inc_not_zero(&pi_state->refcount)) {
922+
raw_spin_unlock_irq(&curr->pi_lock);
923+
cpu_relax();
924+
raw_spin_lock_irq(&curr->pi_lock);
925+
continue;
926+
}
911927
raw_spin_unlock_irq(&curr->pi_lock);
912928

913929
spin_lock(&hb->lock);
@@ -918,18 +934,19 @@ void exit_pi_state_list(struct task_struct *curr)
918934
* task still owns the PI-state:
919935
*/
920936
if (head->next != next) {
937+
/* retain curr->pi_lock for the loop invariant */
921938
raw_spin_unlock(&pi_state->pi_mutex.wait_lock);
922939
spin_unlock(&hb->lock);
940+
put_pi_state(pi_state);
923941
continue;
924942
}
925943

926944
WARN_ON(pi_state->owner != curr);
927945
WARN_ON(list_empty(&pi_state->list));
928946
list_del_init(&pi_state->list);
929947
pi_state->owner = NULL;
930-
raw_spin_unlock(&curr->pi_lock);
931948

932-
get_pi_state(pi_state);
949+
raw_spin_unlock(&curr->pi_lock);
933950
raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock);
934951
spin_unlock(&hb->lock);
935952

kernel/watchdog_hld.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#define pr_fmt(fmt) "NMI watchdog: " fmt
1414

1515
#include <linux/nmi.h>
16+
#include <linux/atomic.h>
1617
#include <linux/module.h>
1718
#include <linux/sched/debug.h>
1819

@@ -22,10 +23,11 @@
2223
static DEFINE_PER_CPU(bool, hard_watchdog_warn);
2324
static DEFINE_PER_CPU(bool, watchdog_nmi_touch);
2425
static DEFINE_PER_CPU(struct perf_event *, watchdog_ev);
26+
static DEFINE_PER_CPU(struct perf_event *, dead_event);
2527
static struct cpumask dead_events_mask;
2628

2729
static unsigned long hardlockup_allcpu_dumped;
28-
static unsigned int watchdog_cpus;
30+
static atomic_t watchdog_cpus = ATOMIC_INIT(0);
2931

3032
void arch_touch_nmi_watchdog(void)
3133
{
@@ -189,7 +191,8 @@ void hardlockup_detector_perf_enable(void)
189191
if (hardlockup_detector_event_create())
190192
return;
191193

192-
if (!watchdog_cpus++)
194+
/* use original value for check */
195+
if (!atomic_fetch_inc(&watchdog_cpus))
193196
pr_info("Enabled. Permanently consumes one hw-PMU counter.\n");
194197

195198
perf_event_enable(this_cpu_read(watchdog_ev));
@@ -204,8 +207,10 @@ void hardlockup_detector_perf_disable(void)
204207

205208
if (event) {
206209
perf_event_disable(event);
210+
this_cpu_write(watchdog_ev, NULL);
211+
this_cpu_write(dead_event, event);
207212
cpumask_set_cpu(smp_processor_id(), &dead_events_mask);
208-
watchdog_cpus--;
213+
atomic_dec(&watchdog_cpus);
209214
}
210215
}
211216

@@ -219,15 +224,15 @@ void hardlockup_detector_perf_cleanup(void)
219224
int cpu;
220225

221226
for_each_cpu(cpu, &dead_events_mask) {
222-
struct perf_event *event = per_cpu(watchdog_ev, cpu);
227+
struct perf_event *event = per_cpu(dead_event, cpu);
223228

224229
/*
225230
* Required because for_each_cpu() reports unconditionally
226231
* CPU0 as set on UP kernels. Sigh.
227232
*/
228233
if (event)
229234
perf_event_release_kernel(event);
230-
per_cpu(watchdog_ev, cpu) = NULL;
235+
per_cpu(dead_event, cpu) = NULL;
231236
}
232237
cpumask_clear(&dead_events_mask);
233238
}

tools/objtool/arch/x86/insn/gen-insn-attr-x86.awk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#!/bin/awk -f
2+
# SPDX-License-Identifier: GPL-2.0
23
# gen-insn-attr-x86.awk: Instruction attribute table generator
34
# Written by Masami Hiramatsu <[email protected]>
45
#

0 commit comments

Comments
 (0)