Commit 1acdac104668a0834cfa267de9946fac7764d486
1 parent
3e1d7a6219
Exists in
master
and in
39 other branches
futex: make clock selectable for FUTEX_WAIT_BITSET
FUTEX_WAIT_BITSET could be used instead of FUTEX_WAIT by setting the bit set to FUTEX_BITSET_MATCH_ANY, but FUTEX_WAIT uses CLOCK_REALTIME while FUTEX_WAIT_BITSET uses CLOCK_MONOTONIC. Add a flag to select CLOCK_REALTIME for FUTEX_WAIT_BITSET so glibc can replace the FUTEX_WAIT logic which needs to do gettimeofday() calls before and after the syscall to convert the absolute timeout to a relative timeout for FUTEX_WAIT. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: Ulrich Drepper <drepper@redhat.com>
Showing 2 changed files with 19 additions and 8 deletions Side-by-side Diff
include/linux/futex.h
... | ... | @@ -25,7 +25,8 @@ |
25 | 25 | #define FUTEX_WAKE_BITSET 10 |
26 | 26 | |
27 | 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 | 31 | #define FUTEX_WAIT_PRIVATE (FUTEX_WAIT | FUTEX_PRIVATE_FLAG) |
31 | 32 | #define FUTEX_WAKE_PRIVATE (FUTEX_WAKE | FUTEX_PRIVATE_FLAG) |
kernel/futex.c
... | ... | @@ -1142,12 +1142,13 @@ |
1142 | 1142 | * In case we must use restart_block to restart a futex_wait, |
1143 | 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 | 1148 | static long futex_wait_restart(struct restart_block *restart); |
1148 | 1149 | |
1149 | 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 | 1153 | struct task_struct *curr = current; |
1153 | 1154 | DECLARE_WAITQUEUE(wait, curr); |
... | ... | @@ -1233,8 +1234,10 @@ |
1233 | 1234 | slack = current->timer_slack_ns; |
1234 | 1235 | if (rt_task(current)) |
1235 | 1236 | slack = 0; |
1236 | - hrtimer_init_on_stack(&t.timer, CLOCK_MONOTONIC, | |
1237 | - HRTIMER_MODE_ABS); | |
1237 | + hrtimer_init_on_stack(&t.timer, | |
1238 | + clockrt ? CLOCK_REALTIME : | |
1239 | + CLOCK_MONOTONIC, | |
1240 | + HRTIMER_MODE_ABS); | |
1238 | 1241 | hrtimer_init_sleeper(&t, current); |
1239 | 1242 | hrtimer_set_expires_range_ns(&t.timer, *abs_time, slack); |
1240 | 1243 | |
... | ... | @@ -1289,6 +1292,8 @@ |
1289 | 1292 | |
1290 | 1293 | if (fshared) |
1291 | 1294 | restart->futex.flags |= FLAGS_SHARED; |
1295 | + if (clockrt) | |
1296 | + restart->futex.flags |= FLAGS_CLOCKRT; | |
1292 | 1297 | return -ERESTART_RESTARTBLOCK; |
1293 | 1298 | } |
1294 | 1299 | |
... | ... | @@ -1312,7 +1317,8 @@ |
1312 | 1317 | if (restart->futex.flags & FLAGS_SHARED) |
1313 | 1318 | fshared = 1; |
1314 | 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 | |
1319 | 1325 | |
1320 | 1326 | |
... | ... | @@ -1905,18 +1911,22 @@ |
1905 | 1911 | long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout, |
1906 | 1912 | u32 __user *uaddr2, u32 val2, u32 val3) |
1907 | 1913 | { |
1908 | - int ret = -ENOSYS; | |
1914 | + int clockrt, ret = -ENOSYS; | |
1909 | 1915 | int cmd = op & FUTEX_CMD_MASK; |
1910 | 1916 | int fshared = 0; |
1911 | 1917 | |
1912 | 1918 | if (!(op & FUTEX_PRIVATE_FLAG)) |
1913 | 1919 | fshared = 1; |
1914 | 1920 | |
1921 | + clockrt = op & FUTEX_CLOCK_REALTIME; | |
1922 | + if (clockrt && cmd != FUTEX_WAIT_BITSET) | |
1923 | + return -ENOSYS; | |
1924 | + | |
1915 | 1925 | switch (cmd) { |
1916 | 1926 | case FUTEX_WAIT: |
1917 | 1927 | val3 = FUTEX_BITSET_MATCH_ANY; |
1918 | 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 | 1930 | break; |
1921 | 1931 | case FUTEX_WAKE: |
1922 | 1932 | val3 = FUTEX_BITSET_MATCH_ANY; |