aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-04-03 08:06:53 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-04-03 08:06:53 -0400
commit7b367f5dba5c5162a7308e85d3fc9170b0cb3e5f (patch)
treea93a93e01dcb4203d545ef61edcb5c4236b49ded
parent17084b7e07909d3a8d51b66b7dfb50a2083a2685 (diff)
parent353def94606fda16d9ae1761b4b0583286481ec5 (diff)
Merge branch 'core-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull core kernel fixes from Ingo Molnar: "This contains the nohz/atomic cleanup/fix for the fetch_or() ugliness you noted during the original nohz pull request, plus there's also misc fixes: - fix liblockdep build bug - fix uapi header build bug - print more lockdep hash collision info to help debug recent reports of hash collisions - update MAINTAINERS email address" * 'core-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: MAINTAINERS: Update my email address locking/lockdep: Print chain_key collision information uapi/linux/stddef.h: Provide __always_inline to userspace headers tools/lib/lockdep: Fix unsupported 'basename -s' in run_tests.sh locking/atomic, sched: Unexport fetch_or() timers/nohz: Convert tick dependency mask to atomic_t locking/atomic: Introduce atomic_fetch_or()
-rw-r--r--MAINTAINERS2
-rw-r--r--include/linux/atomic.h34
-rw-r--r--include/linux/sched.h4
-rw-r--r--include/uapi/linux/stddef.h4
-rw-r--r--kernel/locking/lockdep.c79
-rw-r--r--kernel/sched/core.c18
-rw-r--r--kernel/time/tick-sched.c61
-rw-r--r--kernel/time/tick-sched.h2
-rwxr-xr-xtools/lib/lockdep/run_tests.sh12
9 files changed, 158 insertions, 58 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index fbd6f5288116..1c32f8a3d6c4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6403,7 +6403,7 @@ KPROBES
6403M: Ananth N Mavinakayanahalli <ananth@in.ibm.com> 6403M: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
6404M: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com> 6404M: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
6405M: "David S. Miller" <davem@davemloft.net> 6405M: "David S. Miller" <davem@davemloft.net>
6406M: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> 6406M: Masami Hiramatsu <mhiramat@kernel.org>
6407S: Maintained 6407S: Maintained
6408F: Documentation/kprobes.txt 6408F: Documentation/kprobes.txt
6409F: include/linux/kprobes.h 6409F: include/linux/kprobes.h
diff --git a/include/linux/atomic.h b/include/linux/atomic.h
index df4f369254c0..506c3531832e 100644
--- a/include/linux/atomic.h
+++ b/include/linux/atomic.h
@@ -559,25 +559,25 @@ static inline int atomic_dec_if_positive(atomic_t *v)
559#endif 559#endif
560 560
561/** 561/**
562 * fetch_or - perform *ptr |= mask and return old value of *ptr 562 * atomic_fetch_or - perform *p |= mask and return old value of *p
563 * @ptr: pointer to value 563 * @p: pointer to atomic_t
564 * @mask: mask to OR on the value 564 * @mask: mask to OR on the atomic_t
565 *
566 * cmpxchg based fetch_or, macro so it works for different integer types
567 */ 565 */
568#ifndef fetch_or 566#ifndef atomic_fetch_or
569#define fetch_or(ptr, mask) \ 567static inline int atomic_fetch_or(atomic_t *p, int mask)
570({ typeof(*(ptr)) __old, __val = *(ptr); \ 568{
571 for (;;) { \ 569 int old, val = atomic_read(p);
572 __old = cmpxchg((ptr), __val, __val | (mask)); \ 570
573 if (__old == __val) \ 571 for (;;) {
574 break; \ 572 old = atomic_cmpxchg(p, val, val | mask);
575 __val = __old; \ 573 if (old == val)
576 } \ 574 break;
577 __old; \ 575 val = old;
578}) 576 }
579#endif
580 577
578 return old;
579}
580#endif
581 581
582#ifdef CONFIG_GENERIC_ATOMIC64 582#ifdef CONFIG_GENERIC_ATOMIC64
583#include <asm-generic/atomic64.h> 583#include <asm-generic/atomic64.h>
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 60bba7e032dc..52c4847b05e2 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -720,7 +720,7 @@ struct signal_struct {
720 struct task_cputime cputime_expires; 720 struct task_cputime cputime_expires;
721 721
722#ifdef CONFIG_NO_HZ_FULL 722#ifdef CONFIG_NO_HZ_FULL
723 unsigned long tick_dep_mask; 723 atomic_t tick_dep_mask;
724#endif 724#endif
725 725
726 struct list_head cpu_timers[3]; 726 struct list_head cpu_timers[3];
@@ -1549,7 +1549,7 @@ struct task_struct {
1549#endif 1549#endif
1550 1550
1551#ifdef CONFIG_NO_HZ_FULL 1551#ifdef CONFIG_NO_HZ_FULL
1552 unsigned long tick_dep_mask; 1552 atomic_t tick_dep_mask;
1553#endif 1553#endif
1554 unsigned long nvcsw, nivcsw; /* context switch counts */ 1554 unsigned long nvcsw, nivcsw; /* context switch counts */
1555 u64 start_time; /* monotonic time in nsec */ 1555 u64 start_time; /* monotonic time in nsec */
diff --git a/include/uapi/linux/stddef.h b/include/uapi/linux/stddef.h
index aa9f10428743..621fa8ac4425 100644
--- a/include/uapi/linux/stddef.h
+++ b/include/uapi/linux/stddef.h
@@ -1 +1,5 @@
1#include <linux/compiler.h> 1#include <linux/compiler.h>
2
3#ifndef __always_inline
4#define __always_inline inline
5#endif
diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c
index 53ab2f85d77e..2324ba5310db 100644
--- a/kernel/locking/lockdep.c
+++ b/kernel/locking/lockdep.c
@@ -2000,6 +2000,77 @@ static inline int get_first_held_lock(struct task_struct *curr,
2000} 2000}
2001 2001
2002/* 2002/*
2003 * Returns the next chain_key iteration
2004 */
2005static u64 print_chain_key_iteration(int class_idx, u64 chain_key)
2006{
2007 u64 new_chain_key = iterate_chain_key(chain_key, class_idx);
2008
2009 printk(" class_idx:%d -> chain_key:%016Lx",
2010 class_idx,
2011 (unsigned long long)new_chain_key);
2012 return new_chain_key;
2013}
2014
2015static void
2016print_chain_keys_held_locks(struct task_struct *curr, struct held_lock *hlock_next)
2017{
2018 struct held_lock *hlock;
2019 u64 chain_key = 0;
2020 int depth = curr->lockdep_depth;
2021 int i;
2022
2023 printk("depth: %u\n", depth + 1);
2024 for (i = get_first_held_lock(curr, hlock_next); i < depth; i++) {
2025 hlock = curr->held_locks + i;
2026 chain_key = print_chain_key_iteration(hlock->class_idx, chain_key);
2027
2028 print_lock(hlock);
2029 }
2030
2031 print_chain_key_iteration(hlock_next->class_idx, chain_key);
2032 print_lock(hlock_next);
2033}
2034
2035static void print_chain_keys_chain(struct lock_chain *chain)
2036{
2037 int i;
2038 u64 chain_key = 0;
2039 int class_id;
2040
2041 printk("depth: %u\n", chain->depth);
2042 for (i = 0; i < chain->depth; i++) {
2043 class_id = chain_hlocks[chain->base + i];
2044 chain_key = print_chain_key_iteration(class_id + 1, chain_key);
2045
2046 print_lock_name(lock_classes + class_id);
2047 printk("\n");
2048 }
2049}
2050
2051static void print_collision(struct task_struct *curr,
2052 struct held_lock *hlock_next,
2053 struct lock_chain *chain)
2054{
2055 printk("\n");
2056 printk("======================\n");
2057 printk("[chain_key collision ]\n");
2058 print_kernel_ident();
2059 printk("----------------------\n");
2060 printk("%s/%d: ", current->comm, task_pid_nr(current));
2061 printk("Hash chain already cached but the contents don't match!\n");
2062
2063 printk("Held locks:");
2064 print_chain_keys_held_locks(curr, hlock_next);
2065
2066 printk("Locks in cached chain:");
2067 print_chain_keys_chain(chain);
2068
2069 printk("\nstack backtrace:\n");
2070 dump_stack();
2071}
2072
2073/*
2003 * Checks whether the chain and the current held locks are consistent 2074 * Checks whether the chain and the current held locks are consistent
2004 * in depth and also in content. If they are not it most likely means 2075 * in depth and also in content. If they are not it most likely means
2005 * that there was a collision during the calculation of the chain_key. 2076 * that there was a collision during the calculation of the chain_key.
@@ -2014,14 +2085,18 @@ static int check_no_collision(struct task_struct *curr,
2014 2085
2015 i = get_first_held_lock(curr, hlock); 2086 i = get_first_held_lock(curr, hlock);
2016 2087
2017 if (DEBUG_LOCKS_WARN_ON(chain->depth != curr->lockdep_depth - (i - 1))) 2088 if (DEBUG_LOCKS_WARN_ON(chain->depth != curr->lockdep_depth - (i - 1))) {
2089 print_collision(curr, hlock, chain);
2018 return 0; 2090 return 0;
2091 }
2019 2092
2020 for (j = 0; j < chain->depth - 1; j++, i++) { 2093 for (j = 0; j < chain->depth - 1; j++, i++) {
2021 id = curr->held_locks[i].class_idx - 1; 2094 id = curr->held_locks[i].class_idx - 1;
2022 2095
2023 if (DEBUG_LOCKS_WARN_ON(chain_hlocks[chain->base + j] != id)) 2096 if (DEBUG_LOCKS_WARN_ON(chain_hlocks[chain->base + j] != id)) {
2097 print_collision(curr, hlock, chain);
2024 return 0; 2098 return 0;
2099 }
2025 } 2100 }
2026#endif 2101#endif
2027 return 1; 2102 return 1;
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index d8465eeab8b3..8b489fcac37b 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -321,6 +321,24 @@ static inline void init_hrtick(void)
321} 321}
322#endif /* CONFIG_SCHED_HRTICK */ 322#endif /* CONFIG_SCHED_HRTICK */
323 323
324/*
325 * cmpxchg based fetch_or, macro so it works for different integer types
326 */
327#define fetch_or(ptr, mask) \
328 ({ \
329 typeof(ptr) _ptr = (ptr); \
330 typeof(mask) _mask = (mask); \
331 typeof(*_ptr) _old, _val = *_ptr; \
332 \
333 for (;;) { \
334 _old = cmpxchg(_ptr, _val, _val | _mask); \
335 if (_old == _val) \
336 break; \
337 _val = _old; \
338 } \
339 _old; \
340})
341
324#if defined(CONFIG_SMP) && defined(TIF_POLLING_NRFLAG) 342#if defined(CONFIG_SMP) && defined(TIF_POLLING_NRFLAG)
325/* 343/*
326 * Atomically set TIF_NEED_RESCHED and test for TIF_POLLING_NRFLAG, 344 * Atomically set TIF_NEED_RESCHED and test for TIF_POLLING_NRFLAG,
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index 084b79f5917e..58e3310c9b21 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -157,52 +157,50 @@ static void tick_sched_handle(struct tick_sched *ts, struct pt_regs *regs)
157cpumask_var_t tick_nohz_full_mask; 157cpumask_var_t tick_nohz_full_mask;
158cpumask_var_t housekeeping_mask; 158cpumask_var_t housekeeping_mask;
159bool tick_nohz_full_running; 159bool tick_nohz_full_running;
160static unsigned long tick_dep_mask; 160static atomic_t tick_dep_mask;
161 161
162static void trace_tick_dependency(unsigned long dep) 162static bool check_tick_dependency(atomic_t *dep)
163{ 163{
164 if (dep & TICK_DEP_MASK_POSIX_TIMER) { 164 int val = atomic_read(dep);
165
166 if (val & TICK_DEP_MASK_POSIX_TIMER) {
165 trace_tick_stop(0, TICK_DEP_MASK_POSIX_TIMER); 167 trace_tick_stop(0, TICK_DEP_MASK_POSIX_TIMER);
166 return; 168 return true;
167 } 169 }
168 170
169 if (dep & TICK_DEP_MASK_PERF_EVENTS) { 171 if (val & TICK_DEP_MASK_PERF_EVENTS) {
170 trace_tick_stop(0, TICK_DEP_MASK_PERF_EVENTS); 172 trace_tick_stop(0, TICK_DEP_MASK_PERF_EVENTS);
171 return; 173 return true;
172 } 174 }
173 175
174 if (dep & TICK_DEP_MASK_SCHED) { 176 if (val & TICK_DEP_MASK_SCHED) {
175 trace_tick_stop(0, TICK_DEP_MASK_SCHED); 177 trace_tick_stop(0, TICK_DEP_MASK_SCHED);
176 return; 178 return true;
177 } 179 }
178 180
179 if (dep & TICK_DEP_MASK_CLOCK_UNSTABLE) 181 if (val & TICK_DEP_MASK_CLOCK_UNSTABLE) {
180 trace_tick_stop(0, TICK_DEP_MASK_CLOCK_UNSTABLE); 182 trace_tick_stop(0, TICK_DEP_MASK_CLOCK_UNSTABLE);
183 return true;
184 }
185
186 return false;
181} 187}
182 188
183static bool can_stop_full_tick(struct tick_sched *ts) 189static bool can_stop_full_tick(struct tick_sched *ts)
184{ 190{
185 WARN_ON_ONCE(!irqs_disabled()); 191 WARN_ON_ONCE(!irqs_disabled());
186 192
187 if (tick_dep_mask) { 193 if (check_tick_dependency(&tick_dep_mask))
188 trace_tick_dependency(tick_dep_mask);
189 return false; 194 return false;
190 }
191 195
192 if (ts->tick_dep_mask) { 196 if (check_tick_dependency(&ts->tick_dep_mask))
193 trace_tick_dependency(ts->tick_dep_mask);
194 return false; 197 return false;
195 }
196 198
197 if (current->tick_dep_mask) { 199 if (check_tick_dependency(&current->tick_dep_mask))
198 trace_tick_dependency(current->tick_dep_mask);
199 return false; 200 return false;
200 }
201 201
202 if (current->signal->tick_dep_mask) { 202 if (check_tick_dependency(&current->signal->tick_dep_mask))
203 trace_tick_dependency(current->signal->tick_dep_mask);
204 return false; 203 return false;
205 }
206 204
207 return true; 205 return true;
208} 206}
@@ -259,12 +257,12 @@ static void tick_nohz_full_kick_all(void)
259 preempt_enable(); 257 preempt_enable();
260} 258}
261 259
262static void tick_nohz_dep_set_all(unsigned long *dep, 260static void tick_nohz_dep_set_all(atomic_t *dep,
263 enum tick_dep_bits bit) 261 enum tick_dep_bits bit)
264{ 262{
265 unsigned long prev; 263 int prev;
266 264
267 prev = fetch_or(dep, BIT_MASK(bit)); 265 prev = atomic_fetch_or(dep, BIT(bit));
268 if (!prev) 266 if (!prev)
269 tick_nohz_full_kick_all(); 267 tick_nohz_full_kick_all();
270} 268}
@@ -280,7 +278,7 @@ void tick_nohz_dep_set(enum tick_dep_bits bit)
280 278
281void tick_nohz_dep_clear(enum tick_dep_bits bit) 279void tick_nohz_dep_clear(enum tick_dep_bits bit)
282{ 280{
283 clear_bit(bit, &tick_dep_mask); 281 atomic_andnot(BIT(bit), &tick_dep_mask);
284} 282}
285 283
286/* 284/*
@@ -289,12 +287,12 @@ void tick_nohz_dep_clear(enum tick_dep_bits bit)
289 */ 287 */
290void tick_nohz_dep_set_cpu(int cpu, enum tick_dep_bits bit) 288void tick_nohz_dep_set_cpu(int cpu, enum tick_dep_bits bit)
291{ 289{
292 unsigned long prev; 290 int prev;
293 struct tick_sched *ts; 291 struct tick_sched *ts;
294 292
295 ts = per_cpu_ptr(&tick_cpu_sched, cpu); 293 ts = per_cpu_ptr(&tick_cpu_sched, cpu);
296 294
297 prev = fetch_or(&ts->tick_dep_mask, BIT_MASK(bit)); 295 prev = atomic_fetch_or(&ts->tick_dep_mask, BIT(bit));
298 if (!prev) { 296 if (!prev) {
299 preempt_disable(); 297 preempt_disable();
300 /* Perf needs local kick that is NMI safe */ 298 /* Perf needs local kick that is NMI safe */
@@ -313,7 +311,7 @@ void tick_nohz_dep_clear_cpu(int cpu, enum tick_dep_bits bit)
313{ 311{
314 struct tick_sched *ts = per_cpu_ptr(&tick_cpu_sched, cpu); 312 struct tick_sched *ts = per_cpu_ptr(&tick_cpu_sched, cpu);
315 313
316 clear_bit(bit, &ts->tick_dep_mask); 314 atomic_andnot(BIT(bit), &ts->tick_dep_mask);
317} 315}
318 316
319/* 317/*
@@ -331,7 +329,7 @@ void tick_nohz_dep_set_task(struct task_struct *tsk, enum tick_dep_bits bit)
331 329
332void tick_nohz_dep_clear_task(struct task_struct *tsk, enum tick_dep_bits bit) 330void tick_nohz_dep_clear_task(struct task_struct *tsk, enum tick_dep_bits bit)
333{ 331{
334 clear_bit(bit, &tsk->tick_dep_mask); 332 atomic_andnot(BIT(bit), &tsk->tick_dep_mask);
335} 333}
336 334
337/* 335/*
@@ -345,7 +343,7 @@ void tick_nohz_dep_set_signal(struct signal_struct *sig, enum tick_dep_bits bit)
345 343
346void tick_nohz_dep_clear_signal(struct signal_struct *sig, enum tick_dep_bits bit) 344void tick_nohz_dep_clear_signal(struct signal_struct *sig, enum tick_dep_bits bit)
347{ 345{
348 clear_bit(bit, &sig->tick_dep_mask); 346 atomic_andnot(BIT(bit), &sig->tick_dep_mask);
349} 347}
350 348
351/* 349/*
@@ -366,7 +364,8 @@ void __tick_nohz_task_switch(void)
366 ts = this_cpu_ptr(&tick_cpu_sched); 364 ts = this_cpu_ptr(&tick_cpu_sched);
367 365
368 if (ts->tick_stopped) { 366 if (ts->tick_stopped) {
369 if (current->tick_dep_mask || current->signal->tick_dep_mask) 367 if (atomic_read(&current->tick_dep_mask) ||
368 atomic_read(&current->signal->tick_dep_mask))
370 tick_nohz_full_kick(); 369 tick_nohz_full_kick();
371 } 370 }
372out: 371out:
diff --git a/kernel/time/tick-sched.h b/kernel/time/tick-sched.h
index eb4e32566a83..bf38226e5c17 100644
--- a/kernel/time/tick-sched.h
+++ b/kernel/time/tick-sched.h
@@ -60,7 +60,7 @@ struct tick_sched {
60 u64 next_timer; 60 u64 next_timer;
61 ktime_t idle_expires; 61 ktime_t idle_expires;
62 int do_timer_last; 62 int do_timer_last;
63 unsigned long tick_dep_mask; 63 atomic_t tick_dep_mask;
64}; 64};
65 65
66extern struct tick_sched *tick_get_tick_sched(int cpu); 66extern struct tick_sched *tick_get_tick_sched(int cpu);
diff --git a/tools/lib/lockdep/run_tests.sh b/tools/lib/lockdep/run_tests.sh
index 5334ad9d39b7..1069d96248c1 100755
--- a/tools/lib/lockdep/run_tests.sh
+++ b/tools/lib/lockdep/run_tests.sh
@@ -3,7 +3,7 @@
3make &> /dev/null 3make &> /dev/null
4 4
5for i in `ls tests/*.c`; do 5for i in `ls tests/*.c`; do
6 testname=$(basename -s .c "$i") 6 testname=$(basename "$i" .c)
7 gcc -o tests/$testname -pthread -lpthread $i liblockdep.a -Iinclude -D__USE_LIBLOCKDEP &> /dev/null 7 gcc -o tests/$testname -pthread -lpthread $i liblockdep.a -Iinclude -D__USE_LIBLOCKDEP &> /dev/null
8 echo -ne "$testname... " 8 echo -ne "$testname... "
9 if [ $(timeout 1 ./tests/$testname | wc -l) -gt 0 ]; then 9 if [ $(timeout 1 ./tests/$testname | wc -l) -gt 0 ]; then
@@ -11,11 +11,13 @@ for i in `ls tests/*.c`; do
11 else 11 else
12 echo "FAILED!" 12 echo "FAILED!"
13 fi 13 fi
14 rm tests/$testname 14 if [ -f "tests/$testname" ]; then
15 rm tests/$testname
16 fi
15done 17done
16 18
17for i in `ls tests/*.c`; do 19for i in `ls tests/*.c`; do
18 testname=$(basename -s .c "$i") 20 testname=$(basename "$i" .c)
19 gcc -o tests/$testname -pthread -lpthread -Iinclude $i &> /dev/null 21 gcc -o tests/$testname -pthread -lpthread -Iinclude $i &> /dev/null
20 echo -ne "(PRELOAD) $testname... " 22 echo -ne "(PRELOAD) $testname... "
21 if [ $(timeout 1 ./lockdep ./tests/$testname | wc -l) -gt 0 ]; then 23 if [ $(timeout 1 ./lockdep ./tests/$testname | wc -l) -gt 0 ]; then
@@ -23,5 +25,7 @@ for i in `ls tests/*.c`; do
23 else 25 else
24 echo "FAILED!" 26 echo "FAILED!"
25 fi 27 fi
26 rm tests/$testname 28 if [ -f "tests/$testname" ]; then
29 rm tests/$testname
30 fi
27done 31done