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 'locking-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull locking fixes from Ingo Molnar:
"Misc fixes:

pvqspinlocks:
- an instrumentation fix

futexes:
- preempt-count vs pagefault_disable decouple corner case fix
- futex requeue plist race window fix
- futex UNLOCK_PI transaction fix for a corner case"

* 'locking-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
asm-generic/futex: Re-enable preemption in futex_atomic_cmpxchg_inatomic()
futex: Acknowledge a new waiter in counter before plist
futex: Handle unlock_pi race gracefully
locking/pvqspinlock: Fix division by zero in qstat_read()

+34 -9
+6 -2
include/asm-generic/futex.h
··· 108 108 u32 val; 109 109 110 110 preempt_disable(); 111 - if (unlikely(get_user(val, uaddr) != 0)) 111 + if (unlikely(get_user(val, uaddr) != 0)) { 112 + preempt_enable(); 112 113 return -EFAULT; 114 + } 113 115 114 - if (val == oldval && unlikely(put_user(newval, uaddr) != 0)) 116 + if (val == oldval && unlikely(put_user(newval, uaddr) != 0)) { 117 + preempt_enable(); 115 118 return -EFAULT; 119 + } 116 120 117 121 *uval = val; 118 122 preempt_enable();
+23 -4
kernel/futex.c
··· 1295 1295 if (unlikely(should_fail_futex(true))) 1296 1296 ret = -EFAULT; 1297 1297 1298 - if (cmpxchg_futex_value_locked(&curval, uaddr, uval, newval)) 1298 + if (cmpxchg_futex_value_locked(&curval, uaddr, uval, newval)) { 1299 1299 ret = -EFAULT; 1300 - else if (curval != uval) 1301 - ret = -EINVAL; 1300 + } else if (curval != uval) { 1301 + /* 1302 + * If a unconditional UNLOCK_PI operation (user space did not 1303 + * try the TID->0 transition) raced with a waiter setting the 1304 + * FUTEX_WAITERS flag between get_user() and locking the hash 1305 + * bucket lock, retry the operation. 1306 + */ 1307 + if ((FUTEX_TID_MASK & curval) == uval) 1308 + ret = -EAGAIN; 1309 + else 1310 + ret = -EINVAL; 1311 + } 1302 1312 if (ret) { 1303 1313 raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock); 1304 1314 return ret; ··· 1535 1525 if (likely(&hb1->chain != &hb2->chain)) { 1536 1526 plist_del(&q->list, &hb1->chain); 1537 1527 hb_waiters_dec(hb1); 1538 - plist_add(&q->list, &hb2->chain); 1539 1528 hb_waiters_inc(hb2); 1529 + plist_add(&q->list, &hb2->chain); 1540 1530 q->lock_ptr = &hb2->lock; 1541 1531 } 1542 1532 get_futex_key_refs(key2); ··· 2632 2622 */ 2633 2623 if (ret == -EFAULT) 2634 2624 goto pi_faulted; 2625 + /* 2626 + * A unconditional UNLOCK_PI op raced against a waiter 2627 + * setting the FUTEX_WAITERS bit. Try again. 2628 + */ 2629 + if (ret == -EAGAIN) { 2630 + spin_unlock(&hb->lock); 2631 + put_futex_key(&key); 2632 + goto retry; 2633 + } 2635 2634 /* 2636 2635 * wake_futex_pi has detected invalid state. Tell user 2637 2636 * space.
+5 -3
kernel/locking/qspinlock_stat.h
··· 136 136 } 137 137 138 138 if (counter == qstat_pv_hash_hops) { 139 - u64 frac; 139 + u64 frac = 0; 140 140 141 - frac = 100ULL * do_div(stat, kicks); 142 - frac = DIV_ROUND_CLOSEST_ULL(frac, kicks); 141 + if (kicks) { 142 + frac = 100ULL * do_div(stat, kicks); 143 + frac = DIV_ROUND_CLOSEST_ULL(frac, kicks); 144 + } 143 145 144 146 /* 145 147 * Return a X.XX decimal number