From: Nick Piggin LTP test sigaction_16_24 fails, because it expects sem_wait to be restarted if SA_RESTART is set. sem_wait is implemented with futex_wait, that currently doesn't support being restarted. Ulrich confirms that the call should be restartable. Implement a restart_block method to handle the relative timeout, and allow restarts. Signed-off-by: Nick Piggin Cc: Ulrich Drepper Cc: Rusty Russell Cc: Roland McGrath Cc: Oleg Nesterov Acked-by: Ingo Molnar Signed-off-by: Andrew Morton --- kernel/futex.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff -puN kernel/futex.c~futex-restartable-futex_wait kernel/futex.c --- a/kernel/futex.c~futex-restartable-futex_wait +++ a/kernel/futex.c @@ -980,6 +980,7 @@ static void unqueue_me_pi(struct futex_q drop_futex_key_refs(&q->key); } +static long futex_wait_restart(struct restart_block *restart); static int futex_wait(u32 __user *uaddr, u32 val, unsigned long time) { struct task_struct *curr = current; @@ -1079,11 +1080,22 @@ static int futex_wait(u32 __user *uaddr, return 0; if (time == 0) return -ETIMEDOUT; + /* * We expect signal_pending(current), but another thread may * have handled it for us already. */ - return -EINTR; + if (time == MAX_SCHEDULE_TIMEOUT) + return -ERESTARTSYS; + else { + struct restart_block *restart; + restart = ¤t_thread_info()->restart_block; + restart->fn = futex_wait_restart; + restart->arg0 = (unsigned long)uaddr; + restart->arg1 = (unsigned long)val; + restart->arg2 = time; + return -ERESTART_RESTARTBLOCK; + } out_unlock_release_sem: queue_unlock(&q, hb); @@ -1093,6 +1105,17 @@ static int futex_wait(u32 __user *uaddr, return ret; } +static long futex_wait_restart(struct restart_block *restart) +{ + u32 __user *uaddr = (u32 __user *)restart->arg0; + u32 val = (u32)restart->arg1; + unsigned long time = restart->arg2; + + restart->fn = do_no_restart_syscall; + return (long)futex_wait(uaddr, val, time); +} + + /* * Userspace tried a 0 -> TID atomic transition of the futex value * and failed. The kernel side here does the whole locking operation: _