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

* 'core-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
futex: Fix handling of bad requeue syscall pairing
futex: Fix compat_futex to be same as futex for REQUEUE_PI
locking, sched: Give waitqueue spinlocks their own lockdep classes
futex: Update futex_q lock_ptr on requeue proxy lock

+37 -11
+8 -1
include/linux/wait.h
··· 77 77 #define __WAIT_BIT_KEY_INITIALIZER(word, bit) \ 78 78 { .flags = word, .bit_nr = bit, } 79 79 80 - extern void init_waitqueue_head(wait_queue_head_t *q); 80 + extern void __init_waitqueue_head(wait_queue_head_t *q, struct lock_class_key *); 81 + 82 + #define init_waitqueue_head(q) \ 83 + do { \ 84 + static struct lock_class_key __key; \ 85 + \ 86 + __init_waitqueue_head((q), &__key); \ 87 + } while (0) 81 88 82 89 #ifdef CONFIG_LOCKDEP 83 90 # define __WAIT_QUEUE_HEAD_INIT_ONSTACK(name) \
+22 -6
kernel/futex.c
··· 1010 1010 * requeue_pi_wake_futex() - Wake a task that acquired the lock during requeue 1011 1011 * q: the futex_q 1012 1012 * key: the key of the requeue target futex 1013 + * hb: the hash_bucket of the requeue target futex 1013 1014 * 1014 1015 * During futex_requeue, with requeue_pi=1, it is possible to acquire the 1015 1016 * target futex if it is uncontended or via a lock steal. Set the futex_q key 1016 1017 * to the requeue target futex so the waiter can detect the wakeup on the right 1017 1018 * futex, but remove it from the hb and NULL the rt_waiter so it can detect 1018 - * atomic lock acquisition. Must be called with the q->lock_ptr held. 1019 + * atomic lock acquisition. Set the q->lock_ptr to the requeue target hb->lock 1020 + * to protect access to the pi_state to fixup the owner later. Must be called 1021 + * with both q->lock_ptr and hb->lock held. 1019 1022 */ 1020 1023 static inline 1021 - void requeue_pi_wake_futex(struct futex_q *q, union futex_key *key) 1024 + void requeue_pi_wake_futex(struct futex_q *q, union futex_key *key, 1025 + struct futex_hash_bucket *hb) 1022 1026 { 1023 1027 drop_futex_key_refs(&q->key); 1024 1028 get_futex_key_refs(key); ··· 1033 1029 1034 1030 WARN_ON(!q->rt_waiter); 1035 1031 q->rt_waiter = NULL; 1032 + 1033 + q->lock_ptr = &hb->lock; 1034 + #ifdef CONFIG_DEBUG_PI_LIST 1035 + q->list.plist.lock = &hb->lock; 1036 + #endif 1036 1037 1037 1038 wake_up_state(q->task, TASK_NORMAL); 1038 1039 } ··· 1097 1088 ret = futex_lock_pi_atomic(pifutex, hb2, key2, ps, top_waiter->task, 1098 1089 set_waiters); 1099 1090 if (ret == 1) 1100 - requeue_pi_wake_futex(top_waiter, key2); 1091 + requeue_pi_wake_futex(top_waiter, key2, hb2); 1101 1092 1102 1093 return ret; 1103 1094 } ··· 1256 1247 if (!match_futex(&this->key, &key1)) 1257 1248 continue; 1258 1249 1259 - WARN_ON(!requeue_pi && this->rt_waiter); 1260 - WARN_ON(requeue_pi && !this->rt_waiter); 1250 + /* 1251 + * FUTEX_WAIT_REQEUE_PI and FUTEX_CMP_REQUEUE_PI should always 1252 + * be paired with each other and no other futex ops. 1253 + */ 1254 + if ((requeue_pi && !this->rt_waiter) || 1255 + (!requeue_pi && this->rt_waiter)) { 1256 + ret = -EINVAL; 1257 + break; 1258 + } 1261 1259 1262 1260 /* 1263 1261 * Wake nr_wake waiters. For requeue_pi, if we acquired the ··· 1289 1273 this->task, 1); 1290 1274 if (ret == 1) { 1291 1275 /* We got the lock. */ 1292 - requeue_pi_wake_futex(this, &key2); 1276 + requeue_pi_wake_futex(this, &key2, hb2); 1293 1277 continue; 1294 1278 } else if (ret) { 1295 1279 /* -EDEADLK */
+4 -2
kernel/futex_compat.c
··· 180 180 int cmd = op & FUTEX_CMD_MASK; 181 181 182 182 if (utime && (cmd == FUTEX_WAIT || cmd == FUTEX_LOCK_PI || 183 - cmd == FUTEX_WAIT_BITSET)) { 183 + cmd == FUTEX_WAIT_BITSET || 184 + cmd == FUTEX_WAIT_REQUEUE_PI)) { 184 185 if (get_compat_timespec(&ts, utime)) 185 186 return -EFAULT; 186 187 if (!timespec_valid(&ts)) ··· 192 191 t = ktime_add_safe(ktime_get(), t); 193 192 tp = &t; 194 193 } 195 - if (cmd == FUTEX_REQUEUE || cmd == FUTEX_CMP_REQUEUE) 194 + if (cmd == FUTEX_REQUEUE || cmd == FUTEX_CMP_REQUEUE || 195 + cmd == FUTEX_CMP_REQUEUE_PI || cmd == FUTEX_WAKE_OP) 196 196 val2 = (int) (unsigned long) utime; 197 197 198 198 return do_futex(uaddr, op, val, tp, uaddr2, val2, val3);
+3 -2
kernel/wait.c
··· 10 10 #include <linux/wait.h> 11 11 #include <linux/hash.h> 12 12 13 - void init_waitqueue_head(wait_queue_head_t *q) 13 + void __init_waitqueue_head(wait_queue_head_t *q, struct lock_class_key *key) 14 14 { 15 15 spin_lock_init(&q->lock); 16 + lockdep_set_class(&q->lock, key); 16 17 INIT_LIST_HEAD(&q->task_list); 17 18 } 18 19 19 - EXPORT_SYMBOL(init_waitqueue_head); 20 + EXPORT_SYMBOL(__init_waitqueue_head); 20 21 21 22 void add_wait_queue(wait_queue_head_t *q, wait_queue_t *wait) 22 23 {