aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/futex.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/futex.c')
-rw-r--r--kernel/futex.c37
1 files changed, 30 insertions, 7 deletions
diff --git a/kernel/futex.c b/kernel/futex.c
index 0006d64c448e..a6baaec44b8f 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -109,6 +109,9 @@ struct futex_q {
109 /* Optional priority inheritance state: */ 109 /* Optional priority inheritance state: */
110 struct futex_pi_state *pi_state; 110 struct futex_pi_state *pi_state;
111 struct task_struct *task; 111 struct task_struct *task;
112
113 /* Bitset for the optional bitmasked wakeup */
114 u32 bitset;
112}; 115};
113 116
114/* 117/*
@@ -722,7 +725,7 @@ double_lock_hb(struct futex_hash_bucket *hb1, struct futex_hash_bucket *hb2)
722 * to this virtual address: 725 * to this virtual address:
723 */ 726 */
724static int futex_wake(u32 __user *uaddr, struct rw_semaphore *fshared, 727static int futex_wake(u32 __user *uaddr, struct rw_semaphore *fshared,
725 int nr_wake) 728 int nr_wake, u32 bitset)
726{ 729{
727 struct futex_hash_bucket *hb; 730 struct futex_hash_bucket *hb;
728 struct futex_q *this, *next; 731 struct futex_q *this, *next;
@@ -730,6 +733,9 @@ static int futex_wake(u32 __user *uaddr, struct rw_semaphore *fshared,
730 union futex_key key; 733 union futex_key key;
731 int ret; 734 int ret;
732 735
736 if (!bitset)
737 return -EINVAL;
738
733 futex_lock_mm(fshared); 739 futex_lock_mm(fshared);
734 740
735 ret = get_futex_key(uaddr, fshared, &key); 741 ret = get_futex_key(uaddr, fshared, &key);
@@ -746,6 +752,11 @@ static int futex_wake(u32 __user *uaddr, struct rw_semaphore *fshared,
746 ret = -EINVAL; 752 ret = -EINVAL;
747 break; 753 break;
748 } 754 }
755
756 /* Check if one of the bits is set in both bitsets */
757 if (!(this->bitset & bitset))
758 continue;
759
749 wake_futex(this); 760 wake_futex(this);
750 if (++ret >= nr_wake) 761 if (++ret >= nr_wake)
751 break; 762 break;
@@ -1156,7 +1167,7 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q,
1156static long futex_wait_restart(struct restart_block *restart); 1167static long futex_wait_restart(struct restart_block *restart);
1157 1168
1158static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared, 1169static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared,
1159 u32 val, ktime_t *abs_time) 1170 u32 val, ktime_t *abs_time, u32 bitset)
1160{ 1171{
1161 struct task_struct *curr = current; 1172 struct task_struct *curr = current;
1162 DECLARE_WAITQUEUE(wait, curr); 1173 DECLARE_WAITQUEUE(wait, curr);
@@ -1167,7 +1178,11 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared,
1167 struct hrtimer_sleeper t; 1178 struct hrtimer_sleeper t;
1168 int rem = 0; 1179 int rem = 0;
1169 1180
1181 if (!bitset)
1182 return -EINVAL;
1183
1170 q.pi_state = NULL; 1184 q.pi_state = NULL;
1185 q.bitset = bitset;
1171 retry: 1186 retry:
1172 futex_lock_mm(fshared); 1187 futex_lock_mm(fshared);
1173 1188
@@ -1295,6 +1310,7 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared,
1295 restart->futex.uaddr = (u32 *)uaddr; 1310 restart->futex.uaddr = (u32 *)uaddr;
1296 restart->futex.val = val; 1311 restart->futex.val = val;
1297 restart->futex.time = abs_time->tv64; 1312 restart->futex.time = abs_time->tv64;
1313 restart->futex.bitset = bitset;
1298 restart->futex.flags = 0; 1314 restart->futex.flags = 0;
1299 1315
1300 if (fshared) 1316 if (fshared)
@@ -1321,7 +1337,8 @@ static long futex_wait_restart(struct restart_block *restart)
1321 restart->fn = do_no_restart_syscall; 1337 restart->fn = do_no_restart_syscall;
1322 if (restart->futex.flags & FLAGS_SHARED) 1338 if (restart->futex.flags & FLAGS_SHARED)
1323 fshared = &current->mm->mmap_sem; 1339 fshared = &current->mm->mmap_sem;
1324 return (long)futex_wait(uaddr, fshared, restart->futex.val, &t); 1340 return (long)futex_wait(uaddr, fshared, restart->futex.val, &t,
1341 restart->futex.bitset);
1325} 1342}
1326 1343
1327 1344
@@ -1942,7 +1959,8 @@ retry:
1942 * PI futexes happens in exit_pi_state(): 1959 * PI futexes happens in exit_pi_state():
1943 */ 1960 */
1944 if (!pi && (uval & FUTEX_WAITERS)) 1961 if (!pi && (uval & FUTEX_WAITERS))
1945 futex_wake(uaddr, &curr->mm->mmap_sem, 1); 1962 futex_wake(uaddr, &curr->mm->mmap_sem, 1,
1963 FUTEX_BITSET_MATCH_ANY);
1946 } 1964 }
1947 return 0; 1965 return 0;
1948} 1966}
@@ -2042,10 +2060,14 @@ long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout,
2042 2060
2043 switch (cmd) { 2061 switch (cmd) {
2044 case FUTEX_WAIT: 2062 case FUTEX_WAIT:
2045 ret = futex_wait(uaddr, fshared, val, timeout); 2063 val3 = FUTEX_BITSET_MATCH_ANY;
2064 case FUTEX_WAIT_BITSET:
2065 ret = futex_wait(uaddr, fshared, val, timeout, val3);
2046 break; 2066 break;
2047 case FUTEX_WAKE: 2067 case FUTEX_WAKE:
2048 ret = futex_wake(uaddr, fshared, val); 2068 val3 = FUTEX_BITSET_MATCH_ANY;
2069 case FUTEX_WAKE_BITSET:
2070 ret = futex_wake(uaddr, fshared, val, val3);
2049 break; 2071 break;
2050 case FUTEX_FD: 2072 case FUTEX_FD:
2051 /* non-zero val means F_SETOWN(getpid()) & F_SETSIG(val) */ 2073 /* non-zero val means F_SETOWN(getpid()) & F_SETSIG(val) */
@@ -2085,7 +2107,8 @@ asmlinkage long sys_futex(u32 __user *uaddr, int op, u32 val,
2085 u32 val2 = 0; 2107 u32 val2 = 0;
2086 int cmd = op & FUTEX_CMD_MASK; 2108 int cmd = op & FUTEX_CMD_MASK;
2087 2109
2088 if (utime && (cmd == FUTEX_WAIT || cmd == FUTEX_LOCK_PI)) { 2110 if (utime && (cmd == FUTEX_WAIT || cmd == FUTEX_LOCK_PI ||
2111 cmd == FUTEX_WAIT_BITSET)) {
2089 if (copy_from_user(&ts, utime, sizeof(ts)) != 0) 2112 if (copy_from_user(&ts, utime, sizeof(ts)) != 0)
2090 return -EFAULT; 2113 return -EFAULT;
2091 if (!timespec_valid(&ts)) 2114 if (!timespec_valid(&ts))