Commit 1acdac104668a0834cfa267de9946fac7764d486

Authored by Thomas Gleixner
1 parent 3e1d7a6219

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)
... ... @@ -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;