diff options
| -rw-r--r-- | include/linux/futex.h | 3 | ||||
| -rw-r--r-- | kernel/futex.c | 24 |
2 files changed, 19 insertions, 8 deletions
diff --git a/include/linux/futex.h b/include/linux/futex.h index 8f627b9ae2b1..3bf5bb5a34f9 100644 --- a/include/linux/futex.h +++ b/include/linux/futex.h | |||
| @@ -25,7 +25,8 @@ union ktime; | |||
| 25 | #define FUTEX_WAKE_BITSET 10 | 25 | #define FUTEX_WAKE_BITSET 10 |
| 26 | 26 | ||
| 27 | #define FUTEX_PRIVATE_FLAG 128 | 27 | #define FUTEX_PRIVATE_FLAG 128 |
| 28 | #define FUTEX_CMD_MASK ~FUTEX_PRIVATE_FLAG | 28 | #define FUTEX_CLOCK_REALTIME 256 |
| 29 | #define FUTEX_CMD_MASK ~(FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME) | ||
| 29 | 30 | ||
| 30 | #define FUTEX_WAIT_PRIVATE (FUTEX_WAIT | FUTEX_PRIVATE_FLAG) | 31 | #define FUTEX_WAIT_PRIVATE (FUTEX_WAIT | FUTEX_PRIVATE_FLAG) |
| 31 | #define FUTEX_WAKE_PRIVATE (FUTEX_WAKE | FUTEX_PRIVATE_FLAG) | 32 | #define FUTEX_WAKE_PRIVATE (FUTEX_WAKE | FUTEX_PRIVATE_FLAG) |
diff --git a/kernel/futex.c b/kernel/futex.c index e10c5c8786a6..ba0d3b83c091 100644 --- a/kernel/futex.c +++ b/kernel/futex.c | |||
| @@ -1142,12 +1142,13 @@ handle_fault: | |||
| 1142 | * In case we must use restart_block to restart a futex_wait, | 1142 | * In case we must use restart_block to restart a futex_wait, |
| 1143 | * we encode in the 'flags' shared capability | 1143 | * we encode in the 'flags' shared capability |
| 1144 | */ | 1144 | */ |
| 1145 | #define FLAGS_SHARED 1 | 1145 | #define FLAGS_SHARED 0x01 |
| 1146 | #define FLAGS_CLOCKRT 0x02 | ||
| 1146 | 1147 | ||
| 1147 | static long futex_wait_restart(struct restart_block *restart); | 1148 | static long futex_wait_restart(struct restart_block *restart); |
| 1148 | 1149 | ||
| 1149 | static int futex_wait(u32 __user *uaddr, int fshared, | 1150 | static int futex_wait(u32 __user *uaddr, int fshared, |
| 1150 | u32 val, ktime_t *abs_time, u32 bitset) | 1151 | u32 val, ktime_t *abs_time, u32 bitset, int clockrt) |
| 1151 | { | 1152 | { |
| 1152 | struct task_struct *curr = current; | 1153 | struct task_struct *curr = current; |
| 1153 | DECLARE_WAITQUEUE(wait, curr); | 1154 | DECLARE_WAITQUEUE(wait, curr); |
| @@ -1233,8 +1234,10 @@ static int futex_wait(u32 __user *uaddr, int fshared, | |||
| 1233 | slack = current->timer_slack_ns; | 1234 | slack = current->timer_slack_ns; |
| 1234 | if (rt_task(current)) | 1235 | if (rt_task(current)) |
| 1235 | slack = 0; | 1236 | slack = 0; |
| 1236 | hrtimer_init_on_stack(&t.timer, CLOCK_MONOTONIC, | 1237 | hrtimer_init_on_stack(&t.timer, |
| 1237 | HRTIMER_MODE_ABS); | 1238 | clockrt ? CLOCK_REALTIME : |
| 1239 | CLOCK_MONOTONIC, | ||
| 1240 | HRTIMER_MODE_ABS); | ||
| 1238 | hrtimer_init_sleeper(&t, current); | 1241 | hrtimer_init_sleeper(&t, current); |
| 1239 | hrtimer_set_expires_range_ns(&t.timer, *abs_time, slack); | 1242 | hrtimer_set_expires_range_ns(&t.timer, *abs_time, slack); |
| 1240 | 1243 | ||
| @@ -1289,6 +1292,8 @@ static int futex_wait(u32 __user *uaddr, int fshared, | |||
| 1289 | 1292 | ||
| 1290 | if (fshared) | 1293 | if (fshared) |
| 1291 | restart->futex.flags |= FLAGS_SHARED; | 1294 | restart->futex.flags |= FLAGS_SHARED; |
| 1295 | if (clockrt) | ||
| 1296 | restart->futex.flags |= FLAGS_CLOCKRT; | ||
| 1292 | return -ERESTART_RESTARTBLOCK; | 1297 | return -ERESTART_RESTARTBLOCK; |
| 1293 | } | 1298 | } |
| 1294 | 1299 | ||
| @@ -1312,7 +1317,8 @@ static long futex_wait_restart(struct restart_block *restart) | |||
| 1312 | if (restart->futex.flags & FLAGS_SHARED) | 1317 | if (restart->futex.flags & FLAGS_SHARED) |
| 1313 | fshared = 1; | 1318 | fshared = 1; |
| 1314 | return (long)futex_wait(uaddr, fshared, restart->futex.val, &t, | 1319 | return (long)futex_wait(uaddr, fshared, restart->futex.val, &t, |
| 1315 | restart->futex.bitset); | 1320 | restart->futex.bitset, |
| 1321 | restart->futex.flags & FLAGS_CLOCKRT); | ||
| 1316 | } | 1322 | } |
| 1317 | 1323 | ||
| 1318 | 1324 | ||
| @@ -1905,18 +1911,22 @@ void exit_robust_list(struct task_struct *curr) | |||
| 1905 | long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout, | 1911 | long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout, |
| 1906 | u32 __user *uaddr2, u32 val2, u32 val3) | 1912 | u32 __user *uaddr2, u32 val2, u32 val3) |
| 1907 | { | 1913 | { |
| 1908 | int ret = -ENOSYS; | 1914 | int clockrt, ret = -ENOSYS; |
| 1909 | int cmd = op & FUTEX_CMD_MASK; | 1915 | int cmd = op & FUTEX_CMD_MASK; |
| 1910 | int fshared = 0; | 1916 | int fshared = 0; |
| 1911 | 1917 | ||
| 1912 | if (!(op & FUTEX_PRIVATE_FLAG)) | 1918 | if (!(op & FUTEX_PRIVATE_FLAG)) |
| 1913 | fshared = 1; | 1919 | fshared = 1; |
| 1914 | 1920 | ||
| 1921 | clockrt = op & FUTEX_CLOCK_REALTIME; | ||
| 1922 | if (clockrt && cmd != FUTEX_WAIT_BITSET) | ||
| 1923 | return -ENOSYS; | ||
| 1924 | |||
| 1915 | switch (cmd) { | 1925 | switch (cmd) { |
| 1916 | case FUTEX_WAIT: | 1926 | case FUTEX_WAIT: |
| 1917 | val3 = FUTEX_BITSET_MATCH_ANY; | 1927 | val3 = FUTEX_BITSET_MATCH_ANY; |
| 1918 | case FUTEX_WAIT_BITSET: | 1928 | case FUTEX_WAIT_BITSET: |
| 1919 | ret = futex_wait(uaddr, fshared, val, timeout, val3); | 1929 | ret = futex_wait(uaddr, fshared, val, timeout, val3, clockrt); |
| 1920 | break; | 1930 | break; |
| 1921 | case FUTEX_WAKE: | 1931 | case FUTEX_WAKE: |
| 1922 | val3 = FUTEX_BITSET_MATCH_ANY; | 1932 | val3 = FUTEX_BITSET_MATCH_ANY; |
