Skip to content

Commit dd05080

Browse files
committed
Merge branch 'sched-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull scheduler fixes from Ingo Molnar: "Three fixes for scheduler crashes, each triggers in relatively rare, hardware environment dependent situations" * 'sched-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: sched/fair: Rework sched_fair time accounting math64: Add mul_u64_u32_shr() sched: Remove PREEMPT_NEED_RESCHED from generic code sched: Initialize power_orig for overlapping groups
2 parents 1070d5a + 9dbdb15 commit dd05080

8 files changed

Lines changed: 126 additions & 107 deletions

File tree

arch/x86/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ config X86
2626
select HAVE_AOUT if X86_32
2727
select HAVE_UNSTABLE_SCHED_CLOCK
2828
select ARCH_SUPPORTS_NUMA_BALANCING
29+
select ARCH_SUPPORTS_INT128 if X86_64
2930
select ARCH_WANTS_PROT_NUMA_PROT_NONE
3031
select HAVE_IDE
3132
select HAVE_OPROFILE

arch/x86/include/asm/preempt.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@
77

88
DECLARE_PER_CPU(int, __preempt_count);
99

10+
/*
11+
* We use the PREEMPT_NEED_RESCHED bit as an inverted NEED_RESCHED such
12+
* that a decrement hitting 0 means we can and should reschedule.
13+
*/
14+
#define PREEMPT_ENABLED (0 + PREEMPT_NEED_RESCHED)
15+
1016
/*
1117
* We mask the PREEMPT_NEED_RESCHED bit so as not to confuse all current users
1218
* that think a non-zero value indicates we cannot preempt.
@@ -74,6 +80,11 @@ static __always_inline void __preempt_count_sub(int val)
7480
__this_cpu_add_4(__preempt_count, -val);
7581
}
7682

83+
/*
84+
* Because we keep PREEMPT_NEED_RESCHED set when we do _not_ need to reschedule
85+
* a decrement which hits zero means we have no preempt_count and should
86+
* reschedule.
87+
*/
7788
static __always_inline bool __preempt_count_dec_and_test(void)
7889
{
7990
GEN_UNARY_RMWcc("decl", __preempt_count, __percpu_arg(0), "e");

include/asm-generic/preempt.h

Lines changed: 11 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,18 @@
33

44
#include <linux/thread_info.h>
55

6-
/*
7-
* We mask the PREEMPT_NEED_RESCHED bit so as not to confuse all current users
8-
* that think a non-zero value indicates we cannot preempt.
9-
*/
6+
#define PREEMPT_ENABLED (0)
7+
108
static __always_inline int preempt_count(void)
119
{
12-
return current_thread_info()->preempt_count & ~PREEMPT_NEED_RESCHED;
10+
return current_thread_info()->preempt_count;
1311
}
1412

1513
static __always_inline int *preempt_count_ptr(void)
1614
{
1715
return &current_thread_info()->preempt_count;
1816
}
1917

20-
/*
21-
* We now loose PREEMPT_NEED_RESCHED and cause an extra reschedule; however the
22-
* alternative is loosing a reschedule. Better schedule too often -- also this
23-
* should be a very rare operation.
24-
*/
2518
static __always_inline void preempt_count_set(int pc)
2619
{
2720
*preempt_count_ptr() = pc;
@@ -41,28 +34,17 @@ static __always_inline void preempt_count_set(int pc)
4134
task_thread_info(p)->preempt_count = PREEMPT_ENABLED; \
4235
} while (0)
4336

44-
/*
45-
* We fold the NEED_RESCHED bit into the preempt count such that
46-
* preempt_enable() can decrement and test for needing to reschedule with a
47-
* single instruction.
48-
*
49-
* We invert the actual bit, so that when the decrement hits 0 we know we both
50-
* need to resched (the bit is cleared) and can resched (no preempt count).
51-
*/
52-
5337
static __always_inline void set_preempt_need_resched(void)
5438
{
55-
*preempt_count_ptr() &= ~PREEMPT_NEED_RESCHED;
5639
}
5740

5841
static __always_inline void clear_preempt_need_resched(void)
5942
{
60-
*preempt_count_ptr() |= PREEMPT_NEED_RESCHED;
6143
}
6244

6345
static __always_inline bool test_preempt_need_resched(void)
6446
{
65-
return !(*preempt_count_ptr() & PREEMPT_NEED_RESCHED);
47+
return false;
6648
}
6749

6850
/*
@@ -81,15 +63,20 @@ static __always_inline void __preempt_count_sub(int val)
8163

8264
static __always_inline bool __preempt_count_dec_and_test(void)
8365
{
84-
return !--*preempt_count_ptr();
66+
/*
67+
* Because of load-store architectures cannot do per-cpu atomic
68+
* operations; we cannot use PREEMPT_NEED_RESCHED because it might get
69+
* lost.
70+
*/
71+
return !--*preempt_count_ptr() && tif_need_resched();
8572
}
8673

8774
/*
8875
* Returns true when we need to resched and can (barring IRQ state).
8976
*/
9077
static __always_inline bool should_resched(void)
9178
{
92-
return unlikely(!*preempt_count_ptr());
79+
return unlikely(!preempt_count() && tif_need_resched());
9380
}
9481

9582
#ifdef CONFIG_PREEMPT

include/linux/math64.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,4 +133,34 @@ __iter_div_u64_rem(u64 dividend, u32 divisor, u64 *remainder)
133133
return ret;
134134
}
135135

136+
#if defined(CONFIG_ARCH_SUPPORTS_INT128) && defined(__SIZEOF_INT128__)
137+
138+
#ifndef mul_u64_u32_shr
139+
static inline u64 mul_u64_u32_shr(u64 a, u32 mul, unsigned int shift)
140+
{
141+
return (u64)(((unsigned __int128)a * mul) >> shift);
142+
}
143+
#endif /* mul_u64_u32_shr */
144+
145+
#else
146+
147+
#ifndef mul_u64_u32_shr
148+
static inline u64 mul_u64_u32_shr(u64 a, u32 mul, unsigned int shift)
149+
{
150+
u32 ah, al;
151+
u64 ret;
152+
153+
al = a;
154+
ah = a >> 32;
155+
156+
ret = ((u64)al * mul) >> shift;
157+
if (ah)
158+
ret += ((u64)ah * mul) << (32 - shift);
159+
160+
return ret;
161+
}
162+
#endif /* mul_u64_u32_shr */
163+
164+
#endif
165+
136166
#endif /* _LINUX_MATH64_H */

include/linux/sched.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -440,8 +440,6 @@ struct task_cputime {
440440
.sum_exec_runtime = 0, \
441441
}
442442

443-
#define PREEMPT_ENABLED (PREEMPT_NEED_RESCHED)
444-
445443
#ifdef CONFIG_PREEMPT_COUNT
446444
#define PREEMPT_DISABLED (1 + PREEMPT_ENABLED)
447445
#else
@@ -932,7 +930,8 @@ struct pipe_inode_info;
932930
struct uts_namespace;
933931

934932
struct load_weight {
935-
unsigned long weight, inv_weight;
933+
unsigned long weight;
934+
u32 inv_weight;
936935
};
937936

938937
struct sched_avg {

init/Kconfig

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -809,6 +809,12 @@ config GENERIC_SCHED_CLOCK
809809
config ARCH_SUPPORTS_NUMA_BALANCING
810810
bool
811811

812+
#
813+
# For architectures that know their GCC __int128 support is sound
814+
#
815+
config ARCH_SUPPORTS_INT128
816+
bool
817+
812818
# For architectures that (ab)use NUMA to represent different memory regions
813819
# all cpu-local but of different latencies, such as SuperH.
814820
#

kernel/sched/core.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5112,6 +5112,7 @@ build_overlap_sched_groups(struct sched_domain *sd, int cpu)
51125112
* die on a /0 trap.
51135113
*/
51145114
sg->sgp->power = SCHED_POWER_SCALE * cpumask_weight(sg_span);
5115+
sg->sgp->power_orig = sg->sgp->power;
51155116

51165117
/*
51175118
* Make sure the first group of this domain contains the

0 commit comments

Comments
 (0)