diff options
author | Oleg Nesterov <oleg@redhat.com> | 2011-04-27 15:44:14 -0400 |
---|---|---|
committer | Oleg Nesterov <oleg@redhat.com> | 2011-04-28 07:01:38 -0400 |
commit | 943df1485a8ff0e600729e082e568ece04d4de9e (patch) | |
tree | d2d4b7b41f163e011cb7a373376c9ae87e5941be /kernel/compat.c | |
parent | fe0faa005d43bc44c357631d51c273806086caa4 (diff) |
signal: introduce do_sigtimedwait() to factor out compat/native code
Factor out the common code in sys_rt_sigtimedwait/compat_sys_rt_sigtimedwait
to the new helper, do_sigtimedwait().
Add the comment to document the extra tick we add to timespec_to_jiffies(ts),
thanks to Linus who explained this to me.
Perhaps it would be better to move compat_sys_rt_sigtimedwait() into
signal.c under CONFIG_COMPAT, then we can make do_sigtimedwait() static.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Acked-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Matt Fleming <matt.fleming@linux.intel.com>
Diffstat (limited to 'kernel/compat.c')
-rw-r--r-- | kernel/compat.c | 41 |
1 files changed, 7 insertions, 34 deletions
diff --git a/kernel/compat.c b/kernel/compat.c index 06cbb0619531..9214dcd087b7 100644 --- a/kernel/compat.c +++ b/kernel/compat.c | |||
@@ -890,10 +890,9 @@ compat_sys_rt_sigtimedwait (compat_sigset_t __user *uthese, | |||
890 | { | 890 | { |
891 | compat_sigset_t s32; | 891 | compat_sigset_t s32; |
892 | sigset_t s; | 892 | sigset_t s; |
893 | int sig; | ||
894 | struct timespec t; | 893 | struct timespec t; |
895 | siginfo_t info; | 894 | siginfo_t info; |
896 | long ret, timeout; | 895 | long ret; |
897 | 896 | ||
898 | if (sigsetsize != sizeof(sigset_t)) | 897 | if (sigsetsize != sizeof(sigset_t)) |
899 | return -EINVAL; | 898 | return -EINVAL; |
@@ -901,45 +900,19 @@ compat_sys_rt_sigtimedwait (compat_sigset_t __user *uthese, | |||
901 | if (copy_from_user(&s32, uthese, sizeof(compat_sigset_t))) | 900 | if (copy_from_user(&s32, uthese, sizeof(compat_sigset_t))) |
902 | return -EFAULT; | 901 | return -EFAULT; |
903 | sigset_from_compat(&s, &s32); | 902 | sigset_from_compat(&s, &s32); |
904 | sigdelsetmask(&s,sigmask(SIGKILL)|sigmask(SIGSTOP)); | ||
905 | signotset(&s); | ||
906 | 903 | ||
907 | timeout = MAX_SCHEDULE_TIMEOUT; | ||
908 | if (uts) { | 904 | if (uts) { |
909 | if (get_compat_timespec (&t, uts)) | 905 | if (get_compat_timespec(&t, uts)) |
910 | return -EFAULT; | 906 | return -EFAULT; |
911 | if (!timespec_valid(&t)) | ||
912 | return -EINVAL; | ||
913 | timeout = timespec_to_jiffies(&t) + (t.tv_sec || t.tv_nsec); | ||
914 | } | 907 | } |
915 | 908 | ||
916 | spin_lock_irq(¤t->sighand->siglock); | 909 | ret = do_sigtimedwait(&s, &info, uts ? &t : NULL); |
917 | sig = dequeue_signal(current, &s, &info); | ||
918 | if (!sig && timeout) { | ||
919 | current->real_blocked = current->blocked; | ||
920 | sigandsets(¤t->blocked, ¤t->blocked, &s); | ||
921 | recalc_sigpending(); | ||
922 | spin_unlock_irq(¤t->sighand->siglock); | ||
923 | |||
924 | timeout = schedule_timeout_interruptible(timeout); | ||
925 | |||
926 | spin_lock_irq(¤t->sighand->siglock); | ||
927 | sig = dequeue_signal(current, &s, &info); | ||
928 | current->blocked = current->real_blocked; | ||
929 | siginitset(¤t->real_blocked, 0); | ||
930 | recalc_sigpending(); | ||
931 | } | ||
932 | spin_unlock_irq(¤t->sighand->siglock); | ||
933 | 910 | ||
934 | if (sig) { | 911 | if (ret > 0 && uinfo) { |
935 | ret = sig; | 912 | if (copy_siginfo_to_user32(uinfo, &info)) |
936 | if (uinfo) { | 913 | ret = -EFAULT; |
937 | if (copy_siginfo_to_user32(uinfo, &info)) | ||
938 | ret = -EFAULT; | ||
939 | } | ||
940 | } else { | ||
941 | ret = timeout?-EINTR:-EAGAIN; | ||
942 | } | 914 | } |
915 | |||
943 | return ret; | 916 | return ret; |
944 | 917 | ||
945 | } | 918 | } |