diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2008-11-20 13:02:53 -0500 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2008-11-24 14:00:40 -0500 |
commit | 1acdac104668a0834cfa267de9946fac7764d486 (patch) | |
tree | bae8ffeb2425412c0bffbdf728b45104fe3178f2 | |
parent | 3e1d7a6219ab64e13b10b1a77c0625db9a8bd8db (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.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; |