@@ -339,18 +339,8 @@ static long futex_wait_restart(struct restart_block *restart);
339
339
* @q: the futex_q to queue up on
340
340
* @timeout: the prepared hrtimer_sleeper, or null for no timeout
341
341
*/
342
- void futex_wait_queue (struct futex_hash_bucket * hb , struct futex_q * q ,
343
- struct hrtimer_sleeper * timeout )
342
+ void futex_do_wait (struct futex_q * q , struct hrtimer_sleeper * timeout )
344
343
{
345
- /*
346
- * The task state is guaranteed to be set before another task can
347
- * wake it. set_current_state() is implemented using smp_store_mb() and
348
- * futex_queue() calls spin_unlock() upon completion, both serializing
349
- * access to the hash list and forcing another memory barrier.
350
- */
351
- set_current_state (TASK_INTERRUPTIBLE |TASK_FREEZABLE );
352
- futex_queue (q , hb , current );
353
-
354
344
/* Arm the timer */
355
345
if (timeout )
356
346
hrtimer_sleeper_start_expires (timeout , HRTIMER_MODE_ABS );
@@ -578,7 +568,8 @@ int futex_wait_multiple(struct futex_vector *vs, unsigned int count,
578
568
* @val: the expected value
579
569
* @flags: futex flags (FLAGS_SHARED, etc.)
580
570
* @q: the associated futex_q
581
- * @hb: storage for hash_bucket pointer to be returned to caller
571
+ * @key2: the second futex_key if used for requeue PI
572
+ * task: Task queueing this futex
582
573
*
583
574
* Setup the futex_q and locate the hash_bucket. Get the futex value and
584
575
* compare it with the expected value. Handle atomic faults internally.
@@ -589,8 +580,10 @@ int futex_wait_multiple(struct futex_vector *vs, unsigned int count,
589
580
* - <1 - -EFAULT or -EWOULDBLOCK (uaddr does not contain val) and hb is unlocked
590
581
*/
591
582
int futex_wait_setup (u32 __user * uaddr , u32 val , unsigned int flags ,
592
- struct futex_q * q , struct futex_hash_bucket * * hb )
583
+ struct futex_q * q , union futex_key * key2 ,
584
+ struct task_struct * task )
593
585
{
586
+ struct futex_hash_bucket * hb ;
594
587
u32 uval ;
595
588
int ret ;
596
589
@@ -618,12 +611,12 @@ int futex_wait_setup(u32 __user *uaddr, u32 val, unsigned int flags,
618
611
return ret ;
619
612
620
613
retry_private :
621
- * hb = futex_q_lock (q );
614
+ hb = futex_q_lock (q );
622
615
623
616
ret = futex_get_value_locked (& uval , uaddr );
624
617
625
618
if (ret ) {
626
- futex_q_unlock (* hb );
619
+ futex_q_unlock (hb );
627
620
628
621
ret = get_user (uval , uaddr );
629
622
if (ret )
@@ -636,18 +629,32 @@ int futex_wait_setup(u32 __user *uaddr, u32 val, unsigned int flags,
636
629
}
637
630
638
631
if (uval != val ) {
639
- futex_q_unlock (* hb );
640
- ret = - EWOULDBLOCK ;
632
+ futex_q_unlock (hb );
633
+ return - EWOULDBLOCK ;
641
634
}
642
635
636
+ if (key2 && futex_match (& q -> key , key2 )) {
637
+ futex_q_unlock (hb );
638
+ return - EINVAL ;
639
+ }
640
+
641
+ /*
642
+ * The task state is guaranteed to be set before another task can
643
+ * wake it. set_current_state() is implemented using smp_store_mb() and
644
+ * futex_queue() calls spin_unlock() upon completion, both serializing
645
+ * access to the hash list and forcing another memory barrier.
646
+ */
647
+ if (task == current )
648
+ set_current_state (TASK_INTERRUPTIBLE |TASK_FREEZABLE );
649
+ futex_queue (q , hb , task );
650
+
643
651
return ret ;
644
652
}
645
653
646
654
int __futex_wait (u32 __user * uaddr , unsigned int flags , u32 val ,
647
655
struct hrtimer_sleeper * to , u32 bitset )
648
656
{
649
657
struct futex_q q = futex_q_init ;
650
- struct futex_hash_bucket * hb ;
651
658
int ret ;
652
659
653
660
if (!bitset )
@@ -660,12 +667,12 @@ int __futex_wait(u32 __user *uaddr, unsigned int flags, u32 val,
660
667
* Prepare to wait on uaddr. On success, it holds hb->lock and q
661
668
* is initialized.
662
669
*/
663
- ret = futex_wait_setup (uaddr , val , flags , & q , & hb );
670
+ ret = futex_wait_setup (uaddr , val , flags , & q , NULL , current );
664
671
if (ret )
665
672
return ret ;
666
673
667
674
/* futex_queue and wait for wakeup, timeout, or a signal. */
668
- futex_wait_queue ( hb , & q , to );
675
+ futex_do_wait ( & q , to );
669
676
670
677
/* If we were woken (and unqueued), we succeeded, whatever. */
671
678
if (!futex_unqueue (& q ))
0 commit comments