aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2008-11-20 13:02:53 -0500
committerThomas Gleixner <tglx@linutronix.de>2008-11-24 14:00:40 -0500
commit1acdac104668a0834cfa267de9946fac7764d486 (patch)
treebae8ffeb2425412c0bffbdf728b45104fe3178f2
parent3e1d7a6219ab64e13b10b1a77c0625db9a8bd8db (diff)
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>
-rw-r--r--include/linux/futex.h3
-rw-r--r--kernel/futex.c24
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
1147static long futex_wait_restart(struct restart_block *restart); 1148static long futex_wait_restart(struct restart_block *restart);
1148 1149
1149static int futex_wait(u32 __user *uaddr, int fshared, 1150static 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)
1905long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout, 1911long 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;