Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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()

+158 -58
+1 -1
MAINTAINERS
··· 6403 6403 M: Ananth N Mavinakayanahalli <ananth@in.ibm.com> 6404 6404 M: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com> 6405 6405 M: "David S. Miller" <davem@davemloft.net> 6406 - M: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> 6406 + M: Masami Hiramatsu <mhiramat@kernel.org> 6407 6407 S: Maintained 6408 6408 F: Documentation/kprobes.txt 6409 6409 F: include/linux/kprobes.h
+17 -17
include/linux/atomic.h
··· 559 559 #endif 560 560 561 561 /** 562 - * fetch_or - perform *ptr |= mask and return old value of *ptr 563 - * @ptr: pointer to value 564 - * @mask: mask to OR on the value 565 - * 566 - * cmpxchg based fetch_or, macro so it works for different integer types 562 + * atomic_fetch_or - perform *p |= mask and return old value of *p 563 + * @p: pointer to atomic_t 564 + * @mask: mask to OR on the atomic_t 567 565 */ 568 - #ifndef fetch_or 569 - #define fetch_or(ptr, mask) \ 570 - ({ typeof(*(ptr)) __old, __val = *(ptr); \ 571 - for (;;) { \ 572 - __old = cmpxchg((ptr), __val, __val | (mask)); \ 573 - if (__old == __val) \ 574 - break; \ 575 - __val = __old; \ 576 - } \ 577 - __old; \ 578 - }) 579 - #endif 566 + #ifndef atomic_fetch_or 567 + static inline int atomic_fetch_or(atomic_t *p, int mask) 568 + { 569 + int old, val = atomic_read(p); 580 570 571 + for (;;) { 572 + old = atomic_cmpxchg(p, val, val | mask); 573 + if (old == val) 574 + break; 575 + val = old; 576 + } 577 + 578 + return old; 579 + } 580 + #endif 581 581 582 582 #ifdef CONFIG_GENERIC_ATOMIC64 583 583 #include <asm-generic/atomic64.h>
+2 -2
include/linux/sched.h
··· 720 720 struct task_cputime cputime_expires; 721 721 722 722 #ifdef CONFIG_NO_HZ_FULL 723 - unsigned long tick_dep_mask; 723 + atomic_t tick_dep_mask; 724 724 #endif 725 725 726 726 struct list_head cpu_timers[3]; ··· 1549 1549 #endif 1550 1550 1551 1551 #ifdef CONFIG_NO_HZ_FULL 1552 - unsigned long tick_dep_mask; 1552 + atomic_t tick_dep_mask; 1553 1553 #endif 1554 1554 unsigned long nvcsw, nivcsw; /* context switch counts */ 1555 1555 u64 start_time; /* monotonic time in nsec */
+4
include/uapi/linux/stddef.h
··· 1 1 #include <linux/compiler.h> 2 + 3 + #ifndef __always_inline 4 + #define __always_inline inline 5 + #endif
+77 -2
kernel/locking/lockdep.c
··· 2000 2000 } 2001 2001 2002 2002 /* 2003 + * Returns the next chain_key iteration 2004 + */ 2005 + static 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 + 2015 + static void 2016 + print_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 + 2035 + static 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 + 2051 + static 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 2074 * Checks whether the chain and the current held locks are consistent 2004 2075 * in depth and also in content. If they are not it most likely means 2005 2076 * that there was a collision during the calculation of the chain_key. ··· 2085 2014 2086 2015 i = get_first_held_lock(curr, hlock); 2087 2016 2088 - if (DEBUG_LOCKS_WARN_ON(chain->depth != curr->lockdep_depth - (i - 1))) 2017 + if (DEBUG_LOCKS_WARN_ON(chain->depth != curr->lockdep_depth - (i - 1))) { 2018 + print_collision(curr, hlock, chain); 2089 2019 return 0; 2020 + } 2090 2021 2091 2022 for (j = 0; j < chain->depth - 1; j++, i++) { 2092 2023 id = curr->held_locks[i].class_idx - 1; 2093 2024 2094 - if (DEBUG_LOCKS_WARN_ON(chain_hlocks[chain->base + j] != id)) 2025 + if (DEBUG_LOCKS_WARN_ON(chain_hlocks[chain->base + j] != id)) { 2026 + print_collision(curr, hlock, chain); 2095 2027 return 0; 2028 + } 2096 2029 } 2097 2030 #endif 2098 2031 return 1;
+18
kernel/sched/core.c
··· 321 321 } 322 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 342 #if defined(CONFIG_SMP) && defined(TIF_POLLING_NRFLAG) 325 343 /* 326 344 * Atomically set TIF_NEED_RESCHED and test for TIF_POLLING_NRFLAG,
+30 -31
kernel/time/tick-sched.c
··· 157 157 cpumask_var_t tick_nohz_full_mask; 158 158 cpumask_var_t housekeeping_mask; 159 159 bool tick_nohz_full_running; 160 - static unsigned long tick_dep_mask; 160 + static atomic_t tick_dep_mask; 161 161 162 - static void trace_tick_dependency(unsigned long dep) 162 + static 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 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 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 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 182 trace_tick_stop(0, TICK_DEP_MASK_CLOCK_UNSTABLE); 183 + return true; 184 + } 185 + 186 + return false; 181 187 } 182 188 183 189 static bool can_stop_full_tick(struct tick_sched *ts) 184 190 { 185 191 WARN_ON_ONCE(!irqs_disabled()); 186 192 187 - if (tick_dep_mask) { 188 - trace_tick_dependency(tick_dep_mask); 193 + if (check_tick_dependency(&tick_dep_mask)) 189 194 return false; 190 - } 191 195 192 - if (ts->tick_dep_mask) { 193 - trace_tick_dependency(ts->tick_dep_mask); 196 + if (check_tick_dependency(&ts->tick_dep_mask)) 194 197 return false; 195 - } 196 198 197 - if (current->tick_dep_mask) { 198 - trace_tick_dependency(current->tick_dep_mask); 199 + if (check_tick_dependency(&current->tick_dep_mask)) 199 200 return false; 200 - } 201 201 202 - if (current->signal->tick_dep_mask) { 203 - trace_tick_dependency(current->signal->tick_dep_mask); 202 + if (check_tick_dependency(&current->signal->tick_dep_mask)) 204 203 return false; 205 - } 206 204 207 205 return true; 208 206 } ··· 257 259 preempt_enable(); 258 260 } 259 261 260 - static void tick_nohz_dep_set_all(unsigned long *dep, 262 + static void tick_nohz_dep_set_all(atomic_t *dep, 261 263 enum tick_dep_bits bit) 262 264 { 263 - unsigned long prev; 265 + int prev; 264 266 265 - prev = fetch_or(dep, BIT_MASK(bit)); 267 + prev = atomic_fetch_or(dep, BIT(bit)); 266 268 if (!prev) 267 269 tick_nohz_full_kick_all(); 268 270 } ··· 278 280 279 281 void tick_nohz_dep_clear(enum tick_dep_bits bit) 280 282 { 281 - clear_bit(bit, &tick_dep_mask); 283 + atomic_andnot(BIT(bit), &tick_dep_mask); 282 284 } 283 285 284 286 /* ··· 287 289 */ 288 290 void tick_nohz_dep_set_cpu(int cpu, enum tick_dep_bits bit) 289 291 { 290 - unsigned long prev; 292 + int prev; 291 293 struct tick_sched *ts; 292 294 293 295 ts = per_cpu_ptr(&tick_cpu_sched, cpu); 294 296 295 - prev = fetch_or(&ts->tick_dep_mask, BIT_MASK(bit)); 297 + prev = atomic_fetch_or(&ts->tick_dep_mask, BIT(bit)); 296 298 if (!prev) { 297 299 preempt_disable(); 298 300 /* Perf needs local kick that is NMI safe */ ··· 311 313 { 312 314 struct tick_sched *ts = per_cpu_ptr(&tick_cpu_sched, cpu); 313 315 314 - clear_bit(bit, &ts->tick_dep_mask); 316 + atomic_andnot(BIT(bit), &ts->tick_dep_mask); 315 317 } 316 318 317 319 /* ··· 329 331 330 332 void tick_nohz_dep_clear_task(struct task_struct *tsk, enum tick_dep_bits bit) 331 333 { 332 - clear_bit(bit, &tsk->tick_dep_mask); 334 + atomic_andnot(BIT(bit), &tsk->tick_dep_mask); 333 335 } 334 336 335 337 /* ··· 343 345 344 346 void tick_nohz_dep_clear_signal(struct signal_struct *sig, enum tick_dep_bits bit) 345 347 { 346 - clear_bit(bit, &sig->tick_dep_mask); 348 + atomic_andnot(BIT(bit), &sig->tick_dep_mask); 347 349 } 348 350 349 351 /* ··· 364 366 ts = this_cpu_ptr(&tick_cpu_sched); 365 367 366 368 if (ts->tick_stopped) { 367 - if (current->tick_dep_mask || current->signal->tick_dep_mask) 369 + if (atomic_read(&current->tick_dep_mask) || 370 + atomic_read(&current->signal->tick_dep_mask)) 368 371 tick_nohz_full_kick(); 369 372 } 370 373 out:
+1 -1
kernel/time/tick-sched.h
··· 60 60 u64 next_timer; 61 61 ktime_t idle_expires; 62 62 int do_timer_last; 63 - unsigned long tick_dep_mask; 63 + atomic_t tick_dep_mask; 64 64 }; 65 65 66 66 extern struct tick_sched *tick_get_tick_sched(int cpu);
+8 -4
tools/lib/lockdep/run_tests.sh
··· 3 3 make &> /dev/null 4 4 5 5 for i in `ls tests/*.c`; do 6 - testname=$(basename -s .c "$i") 6 + testname=$(basename "$i" .c) 7 7 gcc -o tests/$testname -pthread -lpthread $i liblockdep.a -Iinclude -D__USE_LIBLOCKDEP &> /dev/null 8 8 echo -ne "$testname... " 9 9 if [ $(timeout 1 ./tests/$testname | wc -l) -gt 0 ]; then ··· 11 11 else 12 12 echo "FAILED!" 13 13 fi 14 - rm tests/$testname 14 + if [ -f "tests/$testname" ]; then 15 + rm tests/$testname 16 + fi 15 17 done 16 18 17 19 for i in `ls tests/*.c`; do 18 - testname=$(basename -s .c "$i") 20 + testname=$(basename "$i" .c) 19 21 gcc -o tests/$testname -pthread -lpthread -Iinclude $i &> /dev/null 20 22 echo -ne "(PRELOAD) $testname... " 21 23 if [ $(timeout 1 ./lockdep ./tests/$testname | wc -l) -gt 0 ]; then ··· 25 23 else 26 24 echo "FAILED!" 27 25 fi 28 - rm tests/$testname 26 + if [ -f "tests/$testname" ]; then 27 + rm tests/$testname 28 + fi 29 29 done