public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [Compatibilty patch] sigtimedwait
@ 2004-12-08  0:48 Zou, Nanhai
  2004-12-08  5:35 ` David S. Miller
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Zou, Nanhai @ 2004-12-08  0:48 UTC (permalink / raw)
  To: linux-kernel
  Cc: Andrew Morton, Luck, Tony, Andi Kleen, ralf, paulus,
	Martin Schwidefsky, Davem

[-- Attachment #1: Type: text/plain, Size: 705 bytes --]


This patch is to fix a bug in sys32_rt_sigtimedwait on IA64, X86_64 and
PPC64.
They do a compare of siginfo.si_code when copying siginfo to userspace
compat_siginfo_t structure.
The compare is wrong because siginfo.si_code is already cast to short at
this moment.

This bug will hang ipctest program in linux-ha heartbeat package.

This patch also merges all 6 32 bit layer sys_rt_sigtimedwait in IA64,
X86_64, PPC64, Sparc64, S390 and MIPS into 1 compat_rt_sigtimedwait.

I have only tested it on X86_64 and IA64.
It looks a bit weird for 
#ifdef  __MIPSEL__ in generic code. 
But I don't have any better idea for this.

Signed-off-by: Zou Nan hai <Nanhai.zou@intel.com>
Zou Nan hai

[-- Attachment #2: compat-sigtimedwait.patch --]
[-- Type: application/octet-stream, Size: 27589 bytes --]

diff -Nraup a/arch/ia64/ia32/ia32_entry.S b/arch/ia64/ia32/ia32_entry.S
--- a/arch/ia64/ia32/ia32_entry.S	2004-12-06 13:04:49.000000000 +0800
+++ b/arch/ia64/ia32/ia32_entry.S	2004-12-07 07:03:42.000000000 +0800
@@ -387,7 +387,7 @@ ia32_syscall_table:
 	data8 sys32_rt_sigaction
 	data8 sys32_rt_sigprocmask /* 175 */
 	data8 sys_rt_sigpending
-	data8 sys32_rt_sigtimedwait
+	data8 compat_rt_sigtimedwait
 	data8 sys32_rt_sigqueueinfo
 	data8 sys32_rt_sigsuspend
 	data8 sys32_pread	  /* 180 */
diff -Nraup a/arch/ia64/ia32/ia32priv.h b/arch/ia64/ia32/ia32priv.h
--- a/arch/ia64/ia32/ia32priv.h	2004-12-06 13:04:24.000000000 +0800
+++ b/arch/ia64/ia32/ia32priv.h	2004-12-07 07:03:42.000000000 +0800
@@ -559,10 +559,6 @@ struct user_regs_struct32 {
 extern int save_ia32_fpstate (struct task_struct *, struct ia32_user_i387_struct __user *);
 extern int save_ia32_fpxstate (struct task_struct *, struct ia32_user_fxsr_struct __user *);
 
-/* Prototypes for use in sys_ia32.c */
-int copy_siginfo_to_user32 (siginfo_t32 __user *to, siginfo_t *from);
-int copy_siginfo_from_user32 (siginfo_t *to, siginfo_t32 __user *from);
-
 #endif /* !CONFIG_IA32_SUPPORT */
 
 #endif /* _ASM_IA64_IA32_PRIV_H */
diff -Nraup a/arch/ia64/ia32/ia32_signal.c b/arch/ia64/ia32/ia32_signal.c
--- a/arch/ia64/ia32/ia32_signal.c	2004-10-19 05:53:06.000000000 +0800
+++ b/arch/ia64/ia32/ia32_signal.c	2004-12-07 07:03:42.000000000 +0800
@@ -589,33 +589,6 @@ sys32_rt_sigprocmask (int how, compat_si
 }
 
 asmlinkage long
-sys32_rt_sigtimedwait (compat_sigset_t __user *uthese, siginfo_t32 __user *uinfo,
-		       struct compat_timespec __user *uts, unsigned int sigsetsize)
-{
-	mm_segment_t old_fs = get_fs();
-	struct timespec t;
-	siginfo_t info;
-	sigset_t s;
-	int ret;
-
-	if (copy_from_user(&s.sig, uthese, sizeof(compat_sigset_t)))
-		return -EFAULT;
-	if (uts && get_compat_timespec(&t, uts))
-		return -EFAULT;
-	set_fs(KERNEL_DS);
-	ret = sys_rt_sigtimedwait((sigset_t __user *) &s,
-				  uinfo ? (siginfo_t __user *) &info : NULL,
-				  uts ? (struct timespec __user *) &t : NULL,
-				  sigsetsize);
-	set_fs(old_fs);
-	if (ret >= 0 && uinfo) {
-		if (copy_siginfo_to_user32(uinfo, &info))
-			return -EFAULT;
-	}
-	return ret;
-}
-
-asmlinkage long
 sys32_rt_sigqueueinfo (int pid, int sig, siginfo_t32 __user *uinfo)
 {
 	mm_segment_t old_fs = get_fs();
diff -Nraup a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
--- a/arch/mips/kernel/scall64-n32.S	2004-12-06 13:04:50.000000000 +0800
+++ b/arch/mips/kernel/scall64-n32.S	2004-12-07 07:03:42.000000000 +0800
@@ -243,7 +243,7 @@ EXPORT(sysn32_call_table)
 	PTR	sys_capget
 	PTR	sys_capset
 	PTR	sys32_rt_sigpending		/* 6125 */
-	PTR	sys32_rt_sigtimedwait
+	PTR	compat_rt_sigtimedwait
 	PTR	sys32_rt_sigqueueinfo
 	PTR	sys32_rt_sigsuspend
 	PTR	sys32_sigaltstack
diff -Nraup a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
--- a/arch/mips/kernel/scall64-o32.S	2004-12-06 13:04:50.000000000 +0800
+++ b/arch/mips/kernel/scall64-o32.S	2004-12-07 07:03:42.000000000 +0800
@@ -420,7 +420,7 @@ sys_call_table:
 	PTR	sys32_rt_sigaction
 	PTR	sys32_rt_sigprocmask 		/* 4195 */
 	PTR	sys32_rt_sigpending
-	PTR	sys32_rt_sigtimedwait
+	PTR	compat_rt_sigtimedwait
 	PTR	sys32_rt_sigqueueinfo
 	PTR	sys32_rt_sigsuspend
 	PTR	sys32_pread			/* 4200 */
diff -Nraup a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c
--- a/arch/mips/kernel/signal32.c	2004-12-06 13:04:50.000000000 +0800
+++ b/arch/mips/kernel/signal32.c	2004-12-07 07:03:42.000000000 +0800
@@ -393,7 +393,7 @@ struct rt_sigframe32 {
 	struct ucontext32 rs_uc;
 };
 
-static int copy_siginfo_to_user32(siginfo_t32 *to, siginfo_t *from)
+int copy_siginfo_to_user32(siginfo_t32 *to, siginfo_t *from)
 {
 	int err;
 
@@ -890,97 +890,6 @@ asmlinkage int sys32_rt_sigpending(compa
 	return ret;
 }
 
-asmlinkage int sys32_rt_sigtimedwait(compat_sigset_t *uthese,
-	siginfo_t32 *uinfo, struct compat_timespec *uts,
-	compat_time_t sigsetsize)
-{
-	int ret, sig;
-	sigset_t these;
-	compat_sigset_t these32;
-	struct timespec ts;
-	siginfo_t info;
-	long timeout = 0;
-
-	/*
-	 * As the result of a brainfarting competition a few years ago the
-	 * size of sigset_t for the 32-bit kernel was choosen to be 128 bits
-	 * but nothing so far is actually using that many, 64 are enough.  So
-	 * for now we just drop the high bits.
-	 */
-	if (copy_from_user (&these32, uthese, sizeof(compat_old_sigset_t)))
-		return -EFAULT;
-
-	switch (_NSIG_WORDS) {
-#ifdef __MIPSEB__
-	case 4: these.sig[3] = these32.sig[6] | (((long)these32.sig[7]) << 32);
-	case 3: these.sig[2] = these32.sig[4] | (((long)these32.sig[5]) << 32);
-	case 2: these.sig[1] = these32.sig[2] | (((long)these32.sig[3]) << 32);
-	case 1: these.sig[0] = these32.sig[0] | (((long)these32.sig[1]) << 32);
-#endif
-#ifdef __MIPSEL__
-	case 4: these.sig[3] = these32.sig[7] | (((long)these32.sig[6]) << 32);
-	case 3: these.sig[2] = these32.sig[5] | (((long)these32.sig[4]) << 32);
-	case 2: these.sig[1] = these32.sig[3] | (((long)these32.sig[2]) << 32);
-	case 1: these.sig[0] = these32.sig[1] | (((long)these32.sig[0]) << 32);
-#endif
-	}
-
-	/*
-	 * Invert the set of allowed signals to get those we
-	 * want to block.
-	 */
-	sigdelsetmask(&these, sigmask(SIGKILL)|sigmask(SIGSTOP));
-	signotset(&these);
-
-	if (uts) {
-		if (get_user (ts.tv_sec, &uts->tv_sec) ||
-		    get_user (ts.tv_nsec, &uts->tv_nsec))
-			return -EINVAL;
-		if (ts.tv_nsec >= 1000000000L || ts.tv_nsec < 0
-		    || ts.tv_sec < 0)
-			return -EINVAL;
-	}
-
-	spin_lock_irq(&current->sighand->siglock);
-	sig = dequeue_signal(current, &these, &info);
-	if (!sig) {
-		/* None ready -- temporarily unblock those we're interested
-		   in so that we'll be awakened when they arrive.  */
-		sigset_t oldblocked = current->blocked;
-		sigandsets(&current->blocked, &current->blocked, &these);
-		recalc_sigpending();
-		spin_unlock_irq(&current->sighand->siglock);
-
-		timeout = MAX_SCHEDULE_TIMEOUT;
-		if (uts)
-			timeout = (timespec_to_jiffies(&ts)
-				   + (ts.tv_sec || ts.tv_nsec));
-
-		current->state = TASK_INTERRUPTIBLE;
-		timeout = schedule_timeout(timeout);
-
-		spin_lock_irq(&current->sighand->siglock);
-		sig = dequeue_signal(current, &these, &info);
-		current->blocked = oldblocked;
-		recalc_sigpending();
-	}
-	spin_unlock_irq(&current->sighand->siglock);
-
-	if (sig) {
-		ret = sig;
-		if (uinfo) {
-			if (copy_siginfo_to_user32(uinfo, &info))
-				ret = -EFAULT;
-		}
-	} else {
-		ret = -EAGAIN;
-		if (timeout)
-			ret = -EINTR;
-	}
-
-	return ret;
-}
-
 asmlinkage int sys32_rt_sigqueueinfo(int pid, int sig, siginfo_t32 *uinfo)
 {
 	siginfo_t info;
diff -Nraup a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S
--- a/arch/ppc64/kernel/misc.S	2004-12-06 13:04:50.000000000 +0800
+++ b/arch/ppc64/kernel/misc.S	2004-12-07 07:03:42.000000000 +0800
@@ -870,7 +870,7 @@ _GLOBAL(sys_call_table32)
 	.llong .sys32_rt_sigaction
 	.llong .sys32_rt_sigprocmask
 	.llong .sys32_rt_sigpending     /* 175 */
-	.llong .sys32_rt_sigtimedwait
+	.llong .compat_rt_sigtimedwait
 	.llong .sys32_rt_sigqueueinfo
 	.llong .ppc32_rt_sigsuspend
 	.llong .sys32_pread64
diff -Nraup a/arch/ppc64/kernel/signal32.c b/arch/ppc64/kernel/signal32.c
--- a/arch/ppc64/kernel/signal32.c	2004-12-06 13:04:25.000000000 +0800
+++ b/arch/ppc64/kernel/signal32.c	2004-12-07 07:03:42.000000000 +0800
@@ -71,7 +71,7 @@ struct sigregs32 {
  *
  */
 struct rt_sigframe32 {
-	struct compat_siginfo	info;
+	siginfo_t32	info;
 	struct ucontext32	uc;
 	/*
 	 * Programs using the rs6000/xcoff abi can save up to 19 gp
@@ -342,7 +342,6 @@ long sys32_sigaction(int sig, struct old
  *       sigpending               sys32_rt_sigpending
  *       sigprocmask              sys32_rt_sigprocmask
  *       sigreturn                sys32_rt_sigreturn
- *       sigtimedwait             sys32_rt_sigtimedwait
  *       sigqueueinfo             sys32_rt_sigqueueinfo
  *       sigsuspend               sys32_rt_sigsuspend
  *
@@ -446,7 +445,7 @@ long sys32_rt_sigpending(compat_sigset_t
 }
 
 
-static long copy_siginfo_to_user32(compat_siginfo_t __user *d, siginfo_t *s)
+long copy_siginfo_to_user32(struct siginfo32 __user *d, siginfo_t *s)
 {
 	long err;
 
@@ -501,35 +500,6 @@ static long copy_siginfo_to_user32(compa
 	return err;
 }
 
-long sys32_rt_sigtimedwait(compat_sigset_t __user *uthese, compat_siginfo_t __user *uinfo,
-		struct compat_timespec __user *uts, compat_size_t sigsetsize)
-{
-	sigset_t s;
-	compat_sigset_t s32;
-	struct timespec t;
-	int ret;
-	mm_segment_t old_fs = get_fs();
-	siginfo_t info;
-
-	if (copy_from_user(&s32, uthese, sizeof(compat_sigset_t)))
-		return -EFAULT;
-	sigset_from_compat(&s, &s32);
-	if (uts && get_compat_timespec(&t, uts))
-		return -EFAULT;
-	set_fs(KERNEL_DS);
-	/* The __user pointer casts are valid because of the set_fs() */
-	ret = sys_rt_sigtimedwait((sigset_t __user *) &s,
-			uinfo ? (siginfo_t __user *) &info : NULL,
-			uts ? (struct timespec __user *) &t : NULL,
-			sigsetsize);
-	set_fs(old_fs);
-	if (ret >= 0 && uinfo) {
-		if (copy_siginfo_to_user32(uinfo, &info))
-			return -EFAULT;
-	}
-	return ret;
-}
-
 /*
  * Note: it is necessary to treat pid and sig as unsigned ints, with the
  * corresponding cast to a signed int to insure that the proper conversion
@@ -537,7 +507,7 @@ long sys32_rt_sigtimedwait(compat_sigset
  * (msr in 32-bit mode) and the register representation of a signed int
  * (msr in 64-bit mode) is performed.
  */
-long sys32_rt_sigqueueinfo(u32 pid, u32 sig, compat_siginfo_t __user *uinfo)
+long sys32_rt_sigqueueinfo(u32 pid, u32 sig, siginfo_t32 __user *uinfo)
 {
 	siginfo_t info;
 	int ret;
diff -Nraup a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c
--- a/arch/s390/kernel/compat_linux.c	2004-12-06 13:04:25.000000000 +0800
+++ b/arch/s390/kernel/compat_linux.c	2004-12-07 07:03:42.000000000 +0800
@@ -634,90 +634,6 @@ asmlinkage long sys32_rt_sigpending(comp
 	return ret;
 }
 
-extern int
-copy_siginfo_to_user32(siginfo_t32 *to, siginfo_t *from);
-
-asmlinkage long
-sys32_rt_sigtimedwait(compat_sigset_t *uthese, siginfo_t32 *uinfo,
-		      struct compat_timespec *uts, size_t sigsetsize)
-{
-	int ret, sig;
-	sigset_t these;
-	compat_sigset_t these32;
-	struct timespec ts;
-	siginfo_t info;
-	long timeout = 0;
-
-	/* XXX: Don't preclude handling different sized sigset_t's.  */
-	if (sigsetsize != sizeof(sigset_t))
-		return -EINVAL;
-
-	if (copy_from_user (&these32, uthese, sizeof(compat_sigset_t)))
-		return -EFAULT;
-
-	switch (_NSIG_WORDS) {
-	case 4: these.sig[3] = these32.sig[6] | (((long)these32.sig[7]) << 32);
-	case 3: these.sig[2] = these32.sig[4] | (((long)these32.sig[5]) << 32);
-	case 2: these.sig[1] = these32.sig[2] | (((long)these32.sig[3]) << 32);
-	case 1: these.sig[0] = these32.sig[0] | (((long)these32.sig[1]) << 32);
-	}
-		
-	/*
-	 * Invert the set of allowed signals to get those we
-	 * want to block.
-	 */
-	sigdelsetmask(&these, sigmask(SIGKILL)|sigmask(SIGSTOP));
-	signotset(&these);
-
-	if (uts) {
-		if (get_compat_timespec(&ts, uts))
-			return -EINVAL;
-		if (ts.tv_nsec >= 1000000000L || ts.tv_nsec < 0
-		    || ts.tv_sec < 0)
-			return -EINVAL;
-	}
-
-	spin_lock_irq(&current->sighand->siglock);
-	sig = dequeue_signal(current, &these, &info);
-	if (!sig) {
-		/* None ready -- temporarily unblock those we're interested
-		   in so that we'll be awakened when they arrive.  */
-		current->real_blocked = current->blocked;
-		sigandsets(&current->blocked, &current->blocked, &these);
-		recalc_sigpending();
-		spin_unlock_irq(&current->sighand->siglock);
-
-		timeout = MAX_SCHEDULE_TIMEOUT;
-		if (uts)
-			timeout = (timespec_to_jiffies(&ts)
-				   + (ts.tv_sec || ts.tv_nsec));
-
-		current->state = TASK_INTERRUPTIBLE;
-		timeout = schedule_timeout(timeout);
-
-		spin_lock_irq(&current->sighand->siglock);
-		sig = dequeue_signal(current, &these, &info);
-		current->blocked = current->real_blocked;
-		siginitset(&current->real_blocked, 0);
-		recalc_sigpending();
-	}
-	spin_unlock_irq(&current->sighand->siglock);
-
-	if (sig) {
-		ret = sig;
-		if (uinfo) {
-			if (copy_siginfo_to_user32(uinfo, &info))
-				ret = -EFAULT;
-		}
-	} else {
-		ret = -EAGAIN;
-		if (timeout)
-			ret = -EINTR;
-	}
-
-	return ret;
-}
-
 asmlinkage long
 sys32_rt_sigqueueinfo(int pid, int sig, siginfo_t32 __user *uinfo)
 {
diff -Nraup a/arch/s390/kernel/compat_linux.h b/arch/s390/kernel/compat_linux.h
--- a/arch/s390/kernel/compat_linux.h	2004-10-19 05:54:39.000000000 +0800
+++ b/arch/s390/kernel/compat_linux.h	2004-12-07 07:03:42.000000000 +0800
@@ -214,7 +214,4 @@ struct sigevent32 {
 	} _sigev_un;
 };
 
-extern int copy_siginfo_to_user32(siginfo_t32 __user *to, siginfo_t *from);
-extern int copy_siginfo_from_user32(siginfo_t *to, siginfo_t32 __user *from);
-
 #endif /* _ASM_S390X_S390_H */
diff -Nraup a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
--- a/arch/s390/kernel/compat_wrapper.S	2004-12-06 13:04:50.000000000 +0800
+++ b/arch/s390/kernel/compat_wrapper.S	2004-12-07 07:03:42.000000000 +0800
@@ -840,13 +840,13 @@ sys32_rt_sigpending_wrapper:
 	llgfr	%r3,%r3			# size_t
 	jg	sys32_rt_sigpending	# branch to system call
 
-	.globl  sys32_rt_sigtimedwait_wrapper 
-sys32_rt_sigtimedwait_wrapper:
+	.globl  compat_rt_sigtimedwait_wrapper
+compat_rt_sigtimedwait_wrapper:
 	llgtr	%r2,%r2			# const sigset_emu31_t *
 	llgtr	%r3,%r3			# siginfo_emu31_t *
 	llgtr	%r4,%r4			# const struct compat_timespec *
 	llgfr	%r5,%r5			# size_t
-	jg	sys32_rt_sigtimedwait	# branch to system call
+	jg	compat_rt_sigtimedwait	# branch to system call
 
 	.globl  sys32_rt_sigqueueinfo_wrapper 
 sys32_rt_sigqueueinfo_wrapper:
diff -Nraup a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S
--- a/arch/s390/kernel/syscalls.S	2004-10-19 05:53:13.000000000 +0800
+++ b/arch/s390/kernel/syscalls.S	2004-12-07 07:03:42.000000000 +0800
@@ -185,7 +185,7 @@ SYSCALL(sys_rt_sigreturn_glue,sys_rt_sig
 SYSCALL(sys_rt_sigaction,sys_rt_sigaction,sys32_rt_sigaction_wrapper)
 SYSCALL(sys_rt_sigprocmask,sys_rt_sigprocmask,sys32_rt_sigprocmask_wrapper)	/* 175 */
 SYSCALL(sys_rt_sigpending,sys_rt_sigpending,sys32_rt_sigpending_wrapper)
-SYSCALL(sys_rt_sigtimedwait,sys_rt_sigtimedwait,sys32_rt_sigtimedwait_wrapper)
+SYSCALL(sys_rt_sigtimedwait,sys_rt_sigtimedwait,compat_rt_sigtimedwait_wrapper)
 SYSCALL(sys_rt_sigqueueinfo,sys_rt_sigqueueinfo,sys32_rt_sigqueueinfo_wrapper)
 SYSCALL(sys_rt_sigsuspend_glue,sys_rt_sigsuspend_glue,sys32_rt_sigsuspend_glue)
 SYSCALL(sys_pread64,sys_pread64,sys32_pread64_wrapper)		/* 180 */
diff -Nraup a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
--- a/arch/sparc64/kernel/sys_sparc32.c	2004-12-06 13:04:25.000000000 +0800
+++ b/arch/sparc64/kernel/sys_sparc32.c	2004-12-07 07:03:42.000000000 +0800
@@ -1044,91 +1044,6 @@ asmlinkage long sys32_rt_sigpending(comp
 	return ret;
 }
 
-asmlinkage long sys32_rt_sigtimedwait(compat_sigset_t __user *uthese,
-				      struct siginfo32 __user *uinfo,
-				      struct compat_timespec __user *uts,
-				      compat_size_t sigsetsize)
-{
-	int ret, sig;
-	sigset_t these;
-	compat_sigset_t these32;
-	struct timespec ts;
-	siginfo_t info;
-	long timeout = 0;
-
-	/* XXX: Don't preclude handling different sized sigset_t's.  */
-	if (sigsetsize != sizeof(sigset_t))
-		return -EINVAL;
-
-	if (copy_from_user (&these32, uthese, sizeof(compat_sigset_t)))
-		return -EFAULT;
-
-	switch (_NSIG_WORDS) {
-	case 4: these.sig[3] = these32.sig[6] | (((long)these32.sig[7]) << 32);
-	case 3: these.sig[2] = these32.sig[4] | (((long)these32.sig[5]) << 32);
-	case 2: these.sig[1] = these32.sig[2] | (((long)these32.sig[3]) << 32);
-	case 1: these.sig[0] = these32.sig[0] | (((long)these32.sig[1]) << 32);
-	}
-		
-	/*
-	 * Invert the set of allowed signals to get those we
-	 * want to block.
-	 */
-	sigdelsetmask(&these, sigmask(SIGKILL)|sigmask(SIGSTOP));
-	signotset(&these);
-
-	if (uts) {
-		if (get_compat_timespec(&ts, uts))
-			return -EINVAL;
-		if (ts.tv_nsec >= 1000000000L || ts.tv_nsec < 0
-		    || ts.tv_sec < 0)
-			return -EINVAL;
-	}
-
-	spin_lock_irq(&current->sighand->siglock);
-	sig = dequeue_signal(current, &these, &info);
-	if (!sig) {
-		timeout = MAX_SCHEDULE_TIMEOUT;
-		if (uts)
-			timeout = (timespec_to_jiffies(&ts)
-				   + (ts.tv_sec || ts.tv_nsec));
-
-		if (timeout) {
-			/* None ready -- temporarily unblock those we're
-			 * interested while we are sleeping in so that we'll
-			 * be awakened when they arrive.  */
-			current->real_blocked = current->blocked;
-			sigandsets(&current->blocked, &current->blocked, &these);
-			recalc_sigpending();
-			spin_unlock_irq(&current->sighand->siglock);
-
-			current->state = TASK_INTERRUPTIBLE;
-			timeout = schedule_timeout(timeout);
-
-			spin_lock_irq(&current->sighand->siglock);
-			sig = dequeue_signal(current, &these, &info);
-			current->blocked = current->real_blocked;
-			siginitset(&current->real_blocked, 0);
-			recalc_sigpending();
-		}
-	}
-	spin_unlock_irq(&current->sighand->siglock);
-
-	if (sig) {
-		ret = sig;
-		if (uinfo) {
-			if (copy_siginfo_to_user32(uinfo, &info))
-				ret = -EFAULT;
-		}
-	} else {
-		ret = -EAGAIN;
-		if (timeout)
-			ret = -EINTR;
-	}
-
-	return ret;
-}
-
 asmlinkage long compat_sys_rt_sigqueueinfo(int pid, int sig,
 					   struct siginfo32 __user *uinfo)
 {
diff -Nraup a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S
--- a/arch/sparc64/kernel/systbls.S	2004-12-06 13:04:50.000000000 +0800
+++ b/arch/sparc64/kernel/systbls.S	2004-12-07 07:03:42.000000000 +0800
@@ -41,7 +41,7 @@ sys_call_table32:
 /*90*/	.word sys_dup2, sys_setfsuid, compat_sys_fcntl, sys32_select, sys_setfsgid
 	.word sys_fsync, sys32_setpriority, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
 /*100*/ .word sys32_getpriority, sys32_rt_sigreturn, sys32_rt_sigaction, sys32_rt_sigprocmask, sys32_rt_sigpending
-	.word sys32_rt_sigtimedwait, sys32_rt_sigqueueinfo, sys32_rt_sigsuspend, sys_setresuid, sys_getresuid
+	.word compat_rt_sigtimedwait, sys32_rt_sigqueueinfo, sys32_rt_sigsuspend, sys_setresuid, sys_getresuid
 /*110*/	.word sys_setresgid, sys_getresgid, sys_setregid, sys_nis_syscall, sys_nis_syscall
 	.word sys32_getgroups, sys32_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_getcwd
 /*120*/	.word compat_sys_readv, compat_sys_writev, sys32_settimeofday, sys32_fchown16, sys_fchmod
diff -Nraup a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S
--- a/arch/x86_64/ia32/ia32entry.S	2004-12-06 13:04:50.000000000 +0800
+++ b/arch/x86_64/ia32/ia32entry.S	2004-12-07 07:03:42.000000000 +0800
@@ -479,7 +479,7 @@ ia32_sys_call_table:
 	.quad sys32_rt_sigaction
 	.quad sys32_rt_sigprocmask	/* 175 */
 	.quad sys32_rt_sigpending
-	.quad sys32_rt_sigtimedwait
+	.quad compat_rt_sigtimedwait
 	.quad sys32_rt_sigqueueinfo
 	.quad stub32_rt_sigsuspend
 	.quad sys32_pread		/* 180 */
diff -Nraup a/arch/x86_64/ia32/ia32_signal.c b/arch/x86_64/ia32/ia32_signal.c
--- a/arch/x86_64/ia32/ia32_signal.c	2004-10-19 05:55:28.000000000 +0800
+++ b/arch/x86_64/ia32/ia32_signal.c	2004-12-07 07:03:42.000000000 +0800
@@ -44,7 +44,7 @@
 asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
 void signal_fault(struct pt_regs *regs, void __user *frame, char *where);
 
-int ia32_copy_siginfo_to_user(siginfo_t32 __user *to, siginfo_t *from)
+int copy_siginfo_to_user32(siginfo_t32 __user *to, siginfo_t *from)
 {
 	int err;
 	if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t32)))
@@ -95,7 +95,7 @@ int ia32_copy_siginfo_to_user(siginfo_t3
 	return err;
 }
 
-int ia32_copy_siginfo_from_user(siginfo_t *to, siginfo_t32 __user *from)
+int copy_siginfo_from_user32(siginfo_t *to, siginfo_t32 __user *from)
 {
 	int err;
 	u32 ptr32;
@@ -536,7 +536,7 @@ void ia32_setup_rt_frame(int sig, struct
 	}
 	err |= __put_user((u32)(u64)&frame->info, &frame->pinfo);
 	err |= __put_user((u32)(u64)&frame->uc, &frame->puc);
-	err |= ia32_copy_siginfo_to_user(&frame->info, info);
+	err |= copy_siginfo_to_user32(&frame->info, info);
 	if (err)
 		goto give_sigsegv;
 
diff -Nraup a/arch/x86_64/ia32/sys_ia32.c b/arch/x86_64/ia32/sys_ia32.c
--- a/arch/x86_64/ia32/sys_ia32.c	2004-12-06 13:04:50.000000000 +0800
+++ b/arch/x86_64/ia32/sys_ia32.c	2004-12-07 07:03:42.000000000 +0800
@@ -628,45 +628,6 @@ sys32_rt_sigpending(compat_sigset_t __us
 	return ret;
 }
 
-
-asmlinkage long
-sys32_rt_sigtimedwait(compat_sigset_t __user *uthese, siginfo_t32 __user *uinfo,
-		      struct compat_timespec __user *uts, compat_size_t sigsetsize)
-{
-	sigset_t s;
-	compat_sigset_t s32;
-	struct timespec t;
-	int ret;
-	mm_segment_t old_fs = get_fs();
-	siginfo_t info;
-		
-	if (copy_from_user (&s32, uthese, sizeof(compat_sigset_t)))
-		return -EFAULT;
-	switch (_NSIG_WORDS) {
-	case 4: s.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32);
-	case 3: s.sig[2] = s32.sig[4] | (((long)s32.sig[5]) << 32);
-	case 2: s.sig[1] = s32.sig[2] | (((long)s32.sig[3]) << 32);
-	case 1: s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32);
-	}
-	if (uts && get_compat_timespec(&t, uts))
-		return -EFAULT;
-	if (uinfo) {
-		/* stop data leak to user space in case of structure fill mismatch
-		 * between sys_rt_sigtimedwait & ia32_copy_siginfo_to_user.
-		 */
-		memset(&info, 0, sizeof(info));
-	}
-	set_fs (KERNEL_DS);
-	ret = sys_rt_sigtimedwait(&s, uinfo ? &info : NULL, uts ? &t : NULL,
-			sigsetsize);
-	set_fs (old_fs);
-	if (ret >= 0 && uinfo) {
-		if (ia32_copy_siginfo_to_user(uinfo, &info))
-			return -EFAULT;
-	}
-	return ret;
-}
-
 asmlinkage long
 sys32_rt_sigqueueinfo(int pid, int sig, siginfo_t32 __user *uinfo)
 {
@@ -674,7 +635,7 @@ sys32_rt_sigqueueinfo(int pid, int sig, 
 	int ret;
 	mm_segment_t old_fs = get_fs();
 	
-	if (ia32_copy_siginfo_from_user(&info, uinfo))
+	if (copy_siginfo_from_user32(&info, uinfo))
 		return -EFAULT;
 	set_fs (KERNEL_DS);
 	ret = sys_rt_sigqueueinfo(pid, sig, &info);
@@ -1022,7 +983,7 @@ asmlinkage long sys32_waitid(int which, 
 
 	BUG_ON(info.si_code & __SI_MASK);
 	info.si_code |= __SI_CHLD;
-	return ia32_copy_siginfo_to_user(uinfo, &info);
+	return copy_siginfo_to_user32(uinfo, &info);
 }
 
 /*
diff -Nraup a/fs/compat.c b/fs/compat.c
--- a/fs/compat.c	2004-12-06 13:04:55.000000000 +0800
+++ b/fs/compat.c	2004-12-07 07:05:57.000000000 +0800
@@ -1665,6 +1665,7 @@ out_nofds:
 	return ret;
 }
 
+
 #if defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE)
 /* Stuff for NFS server syscalls... */
 struct compat_nfsctl_svc {
diff -Nraup a/include/asm-ppc64/ppc32.h b/include/asm-ppc64/ppc32.h
--- a/include/asm-ppc64/ppc32.h	2004-10-19 05:54:07.000000000 +0800
+++ b/include/asm-ppc64/ppc32.h	2004-12-07 07:03:42.000000000 +0800
@@ -16,7 +16,7 @@
 
 /* These are here to support 32-bit syscalls on a 64-bit kernel. */
 
-typedef struct compat_siginfo {
+typedef struct siginfo32 {
 	int si_signo;
 	int si_errno;
 	int si_code;
@@ -65,7 +65,7 @@ typedef struct compat_siginfo {
 			int _fd;
 		} _sigpoll;
 	} _sifields;
-} compat_siginfo_t;
+} siginfo_32t;
 
 #define __old_sigaction32	old_sigaction32
 
diff -Nraup a/include/asm-sparc64/siginfo.h b/include/asm-sparc64/siginfo.h
--- a/include/asm-sparc64/siginfo.h	2004-10-19 05:54:40.000000000 +0800
+++ b/include/asm-sparc64/siginfo.h	2004-12-07 07:03:42.000000000 +0800
@@ -56,9 +56,6 @@ typedef struct sigevent32 {
 	} _sigev_un;
 } sigevent_t32;
 
-extern int copy_siginfo_to_user32(struct siginfo32 __user *to, siginfo_t *from);
-extern int copy_siginfo_to_kernel32(siginfo_t *to, struct siginfo32 __user *from);
-
 #endif /* CONFIG_COMPAT */
 
 #endif /* __KERNEL__ */
diff -Nraup a/include/asm-x86_64/ia32.h b/include/asm-x86_64/ia32.h
--- a/include/asm-x86_64/ia32.h	2004-10-19 05:55:07.000000000 +0800
+++ b/include/asm-x86_64/ia32.h	2004-12-07 07:03:42.000000000 +0800
@@ -165,8 +165,6 @@ struct siginfo_t;
 int do_get_thread_area(struct thread_struct *t, struct user_desc __user *info);
 int do_set_thread_area(struct thread_struct *t, struct user_desc __user *info);
 int ia32_child_tls(struct task_struct *p, struct pt_regs *childregs);
-int ia32_copy_siginfo_from_user(siginfo_t *to, siginfo_t32 __user *from);
-int ia32_copy_siginfo_to_user(siginfo_t32 __user *to, siginfo_t *from);
 #endif
 
 #endif /* !CONFIG_IA32_SUPPORT */
diff -Nraup a/include/linux/compat.h b/include/linux/compat.h
--- a/include/linux/compat.h	2004-12-06 13:04:33.000000000 +0800
+++ b/include/linux/compat.h	2004-12-07 07:03:42.000000000 +0800
@@ -143,6 +143,8 @@ long compat_get_bitmap(unsigned long *ma
 		       unsigned long bitmap_size);
 long compat_put_bitmap(compat_ulong_t __user *umask, unsigned long *mask,
 		       unsigned long bitmap_size);
-
+struct siginfo32;
+int copy_siginfo_from_user32(siginfo_t *to, struct siginfo32 __user *from);
+int copy_siginfo_to_user32(struct siginfo32 __user *to, siginfo_t *from);
 #endif /* CONFIG_COMPAT */
 #endif /* _LINUX_COMPAT_H */
diff -Nraup a/kernel/compat.c b/kernel/compat.c
--- a/kernel/compat.c	2004-12-06 13:04:57.000000000 +0800
+++ b/kernel/compat.c	2004-12-07 07:06:11.000000000 +0800
@@ -682,6 +682,92 @@ long compat_put_bitmap(compat_ulong_t __
 	return 0;
 }
 
+void
+sigset_from_compat (sigset_t *set, compat_sigset_t *compat)
+{
+	switch (_NSIG_WORDS) {
+#if defined (__MIPSEL__)
+	case 4: set->sig[3] = compat->sig[7] | (((long)compat->sig[6]) << 32 );
+	case 3: set->sig[2] = compat->sig[5] | (((long)compat->sig[4]) << 32 );
+	case 2: set->sig[1] = compat->sig[3] | (((long)compat->sig[2]) << 32 );
+	case 1: set->sig[0] = compat->sig[1] | (((long)compat->sig[0]) << 32 );
+#else
+	case 4: set->sig[3] = compat->sig[6] | (((long)compat->sig[7]) << 32 );
+	case 3: set->sig[2] = compat->sig[4] | (((long)compat->sig[5]) << 32 );
+	case 2: set->sig[1] = compat->sig[2] | (((long)compat->sig[3]) << 32 );
+	case 1: set->sig[0] = compat->sig[0] | (((long)compat->sig[1]) << 32 );
+#endif
+	}
+}
+
+asmlinkage long
+compat_rt_sigtimedwait (compat_sigset_t __user *uthese,
+		struct siginfo32 __user *uinfo,
+		struct compat_timespec __user *uts, compat_size_t sigsetsize)
+{
+	compat_sigset_t s32;
+	sigset_t s;
+	int sig;
+	struct timespec t;
+	siginfo_t info;
+	long ret, timeout = 0;
+
+	if (sigsetsize != sizeof(sigset_t))
+		return -EINVAL;
+
+	if (copy_from_user(&s32, uthese, sizeof(compat_sigset_t)))
+		return -EFAULT;
+	sigset_from_compat(&s, &s32);
+	sigdelsetmask(&s,sigmask(SIGKILL)|sigmask(SIGSTOP));
+	signotset(&s);
+
+	if (uts) {
+		if (get_compat_timespec (&t, uts))
+			return -EFAULT;
+		if (t.tv_nsec >= 1000000000L || t.tv_nsec < 0
+				|| t.tv_sec < 0)
+			return -EINVAL;
+	}
+
+	spin_lock_irq(&current->sighand->siglock);
+	sig = dequeue_signal(current, &s, &info);
+	if (!sig) {
+		timeout = MAX_SCHEDULE_TIMEOUT;
+		if (uts)
+			timeout = timespec_to_jiffies(&t)
+				+(t.tv_sec || t.tv_nsec);
+		if (timeout) {
+			current->real_blocked = current->blocked;
+			sigandsets(&current->blocked, &current->blocked, &s);
+
+			recalc_sigpending();
+			spin_unlock_irq(&current->sighand->siglock);
+
+			current->state = TASK_INTERRUPTIBLE;
+			timeout = schedule_timeout(timeout);
+
+			spin_lock_irq(&current->sighand->siglock);
+			sig = dequeue_signal(current, &s, &info);
+			current->blocked = current->real_blocked;
+			siginitset(&current->real_blocked, 0);
+			recalc_sigpending();
+		}
+	}
+	spin_unlock_irq(&current->sighand->siglock);
+
+	if (sig) {
+		ret = sig;
+		if (uinfo) {
+			if (copy_siginfo_to_user32(uinfo, &info))
+				ret = -EFAULT;
+		}
+	}else {
+		ret = timeout?-EINTR:-EAGAIN;
+	}
+	return ret;
+
+}
+
 #ifdef __ARCH_WANT_COMPAT_SYS_TIME
 
 /* compat_time_t is a 32 bit "long" and needs to get converted. */

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [Compatibilty patch] sigtimedwait
  2004-12-08  0:48 Zou, Nanhai
@ 2004-12-08  5:35 ` David S. Miller
  2004-12-08 11:32 ` Stephen Rothwell
  2004-12-08 12:09 ` Stephen Rothwell
  2 siblings, 0 replies; 8+ messages in thread
From: David S. Miller @ 2004-12-08  5:35 UTC (permalink / raw)
  To: Zou, Nanhai
  Cc: linux-kernel, akpm, tony.luck, ak, ralf, paulus, schwidefsky,
	Davem

On Wed, 8 Dec 2004 08:48:56 +0800
"Zou, Nanhai" <nanhai.zou@intel.com> wrote:

> This patch also merges all 6 32 bit layer sys_rt_sigtimedwait in IA64,
> X86_64, PPC64, Sparc64, S390 and MIPS into 1 compat_rt_sigtimedwait.
> 
> I have only tested it on X86_64 and IA64.
> It looks a bit weird for 
> #ifdef  __MIPSEL__ in generic code. 
> But I don't have any better idea for this.

The sparc64 part looks fine.

Instead of __MIPSEL__ you should be checking endianness
with the generic __BIG_ENDIAN and __LITTLE_ENDIAN
macros.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [Compatibilty patch] sigtimedwait
  2004-12-08  0:48 Zou, Nanhai
  2004-12-08  5:35 ` David S. Miller
@ 2004-12-08 11:32 ` Stephen Rothwell
  2004-12-08 12:09 ` Stephen Rothwell
  2 siblings, 0 replies; 8+ messages in thread
From: Stephen Rothwell @ 2004-12-08 11:32 UTC (permalink / raw)
  To: Zou, Nanhai
  Cc: linux-kernel, akpm, tony.luck, ak, ralf, paulus, schwidefsky,
	Davem

[-- Attachment #1: Type: text/plain, Size: 465 bytes --]

On Wed, 8 Dec 2004 08:48:56 +0800 "Zou, Nanhai" <nanhai.zou@intel.com> wrote:
>
> 
> This patch also merges all 6 32 bit layer sys_rt_sigtimedwait in IA64,
> X86_64, PPC64, Sparc64, S390 and MIPS into 1 compat_rt_sigtimedwait.

I think compat_siginfo_t/struct compat_siginfo should be the preferred
name for the structure like all the other comptibility types.

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [Compatibilty patch] sigtimedwait
  2004-12-08  0:48 Zou, Nanhai
  2004-12-08  5:35 ` David S. Miller
  2004-12-08 11:32 ` Stephen Rothwell
@ 2004-12-08 12:09 ` Stephen Rothwell
  2 siblings, 0 replies; 8+ messages in thread
From: Stephen Rothwell @ 2004-12-08 12:09 UTC (permalink / raw)
  To: Zou, Nanhai
  Cc: linux-kernel, akpm, tony.luck, ak, ralf, paulus, schwidefsky,
	Davem

[-- Attachment #1: Type: text/plain, Size: 985 bytes --]

> diff -Nraup a/include/linux/compat.h b/include/linux/compat.h
> --- a/include/linux/compat.h	2004-12-06 13:04:33.000000000 +0800
> +++ b/include/linux/compat.h	2004-12-07 07:03:42.000000000 +0800
> @@ -143,6 +143,8 @@ long compat_get_bitmap(unsigned long *ma
>  		       unsigned long bitmap_size);
>  long compat_put_bitmap(compat_ulong_t __user *umask, unsigned long *mask,
>  		       unsigned long bitmap_size);
> -
> +struct siginfo32;
> +int copy_siginfo_from_user32(siginfo_t *to, struct siginfo32 __user *from);
> +int copy_siginfo_to_user32(struct siginfo32 __user *to, siginfo_t *from);

for (some) consistency with the rest of the compat code, these should
probably be

struct compat_siginfo;

int copy_compat_siginfo_from_user(siginfo_t *to,
		struct compat_siginfo __user *from);
int copy_compat_siginfo_to_user(struct compat_siginfo __user *to,
		siginfo_t *from);

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* RE: [Compatibilty patch] sigtimedwait
@ 2004-12-10  0:40 Zou, Nanhai
  2004-12-10  1:08 ` David S. Miller
  0 siblings, 1 reply; 8+ messages in thread
From: Zou, Nanhai @ 2004-12-10  0:40 UTC (permalink / raw)
  To: David S. Miller
  Cc: linux-kernel, akpm, Luck, Tony, ak, ralf, paulus, schwidefsky

But I can't put a
#ifdef __LITTLE_ENDIAN 
here, 
Because 
only MIPS does the byte swapping in little endian mode.
X86_64 and ia64 does not.

> -----Original Message-----
> From: David S. Miller [mailto:davem@davemloft.net]
> Sent: Wednesday, December 08, 2004 1:35 PM
> To: Zou, Nanhai
> Cc: linux-kernel@vger.kernel.org; akpm@osdl.org; Luck, Tony;
ak@suse.de;
> ralf@linux-mips.org; paulus@au.ibm.com; schwidefsky@de.ibm.com;
> Davem@davemloft.net
> Subject: Re: [Compatibilty patch] sigtimedwait
> 
> On Wed, 8 Dec 2004 08:48:56 +0800
> "Zou, Nanhai" <nanhai.zou@intel.com> wrote:
> 
> > This patch also merges all 6 32 bit layer sys_rt_sigtimedwait in
IA64,
> > X86_64, PPC64, Sparc64, S390 and MIPS into 1 compat_rt_sigtimedwait.
> >
> > I have only tested it on X86_64 and IA64.
> > It looks a bit weird for
> > #ifdef  __MIPSEL__ in generic code.
> > But I don't have any better idea for this.
> 
> The sparc64 part looks fine.
> 
> Instead of __MIPSEL__ you should be checking endianness
> with the generic __BIG_ENDIAN and __LITTLE_ENDIAN
> macros.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* RE: [Compatibilty patch] sigtimedwait
@ 2004-12-10  0:49 Zou, Nanhai
  0 siblings, 0 replies; 8+ messages in thread
From: Zou, Nanhai @ 2004-12-10  0:49 UTC (permalink / raw)
  To: Stephen Rothwell
  Cc: linux-kernel, akpm, Luck, Tony, ak, ralf, paulus, schwidefsky,
	Davem

compat_siginfo_t is a better name.
However the structure siginfo_32t is used in other places in 5 arches
expect ppc64.
I think rename them in this patch will make the patch too big and not so
straightforward.
Maybe we can rename it in another separate patch.

> -----Original Message-----
> From: Stephen Rothwell [mailto:sfr@canb.auug.org.au]
> Sent: Wednesday, December 08, 2004 7:33 PM
> To: Zou, Nanhai
> Cc: linux-kernel@vger.kernel.org; akpm@osdl.org; Luck, Tony;
ak@suse.de;
> ralf@linux-mips.org; paulus@au.ibm.com; schwidefsky@de.ibm.com;
> Davem@davemloft.net
> Subject: Re: [Compatibilty patch] sigtimedwait
> 
> On Wed, 8 Dec 2004 08:48:56 +0800 "Zou, Nanhai" <nanhai.zou@intel.com>
wrote:
> >
> >
> > This patch also merges all 6 32 bit layer sys_rt_sigtimedwait in
IA64,
> > X86_64, PPC64, Sparc64, S390 and MIPS into 1 compat_rt_sigtimedwait.
> 
> I think compat_siginfo_t/struct compat_siginfo should be the preferred
> name for the structure like all the other comptibility types.
> 
> --
> Cheers,
> Stephen Rothwell                    sfr@canb.auug.org.au
> http://www.canb.auug.org.au/~sfr/

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [Compatibilty patch] sigtimedwait
  2004-12-10  0:40 [Compatibilty patch] sigtimedwait Zou, Nanhai
@ 2004-12-10  1:08 ` David S. Miller
  0 siblings, 0 replies; 8+ messages in thread
From: David S. Miller @ 2004-12-10  1:08 UTC (permalink / raw)
  To: Zou, Nanhai; +Cc: linux-kernel, akpm, tony.luck, ak, ralf, paulus, schwidefsky

On Fri, 10 Dec 2004 08:40:57 +0800
"Zou, Nanhai" <nanhai.zou@intel.com> wrote:

> But I can't put a
> #ifdef __LITTLE_ENDIAN 
> here, 
> Because 
> only MIPS does the byte swapping in little endian mode.
> X86_64 and ia64 does not.

Good point.  Perhaps we can turn this into a cleaner looking
macro name that gets set in include/asm/compat.h

^ permalink raw reply	[flat|nested] 8+ messages in thread

* RE: [Compatibilty patch] sigtimedwait
@ 2004-12-14  6:00 Zou, Nanhai
  0 siblings, 0 replies; 8+ messages in thread
From: Zou, Nanhai @ 2004-12-14  6:00 UTC (permalink / raw)
  To: David S. Miller
  Cc: linux-kernel, akpm, Luck, Tony, ak, ralf, paulus, schwidefsky,
	Stephen Rothwell

[-- Attachment #1: Type: text/plain, Size: 1049 bytes --]

Thanks for the suggestion.
I have updated the patch, add a macro __COMPAT_ENDIAN_SWAP__ in
include/asm-mips/compat.h

Also I have changed the name from siginfo_t32 to compat_siginfo_t
according to Stephen Rothwell's suggestion 

This patch is against 2.6.10-rc3-mm1.

Signed-off-by: Zou Nan hai <Nanhai.zou@intel.com>

> -----Original Message-----
> From: David S. Miller [mailto:davem@davemloft.net]
> Sent: Friday, December 10, 2004 9:08 AM
> To: Zou, Nanhai
> Cc: linux-kernel@vger.kernel.org; akpm@osdl.org; Luck, Tony;
ak@suse.de;
> ralf@linux-mips.org; paulus@au.ibm.com; schwidefsky@de.ibm.com
> Subject: Re: [Compatibilty patch] sigtimedwait
> 
> On Fri, 10 Dec 2004 08:40:57 +0800
> "Zou, Nanhai" <nanhai.zou@intel.com> wrote:
> 
> > But I can't put a
> > #ifdef __LITTLE_ENDIAN
> > here,
> > Because
> > only MIPS does the byte swapping in little endian mode.
> > X86_64 and ia64 does not.
> 
> Good point.  Perhaps we can turn this into a cleaner looking
> macro name that gets set in include/asm/compat.h

[-- Attachment #2: compat-sigtimedwait.patch --]
[-- Type: application/octet-stream, Size: 36498 bytes --]

diff -Nraup a/arch/ia64/ia32/ia32_entry.S b/arch/ia64/ia32/ia32_entry.S
--- a/arch/ia64/ia32/ia32_entry.S	2004-12-13 03:56:29.000000000 -0800
+++ b/arch/ia64/ia32/ia32_entry.S	2004-12-13 03:57:09.000000000 -0800
@@ -387,7 +387,7 @@ ia32_syscall_table:
 	data8 sys32_rt_sigaction
 	data8 sys32_rt_sigprocmask /* 175 */
 	data8 sys_rt_sigpending
-	data8 sys32_rt_sigtimedwait
+	data8 compat_rt_sigtimedwait
 	data8 sys32_rt_sigqueueinfo
 	data8 sys32_rt_sigsuspend
 	data8 sys32_pread	  /* 180 */
diff -Nraup a/arch/ia64/ia32/ia32_signal.c b/arch/ia64/ia32/ia32_signal.c
--- a/arch/ia64/ia32/ia32_signal.c	2004-12-13 03:56:29.000000000 -0800
+++ b/arch/ia64/ia32/ia32_signal.c	2004-12-13 03:59:54.000000000 -0800
@@ -59,19 +59,19 @@ struct rt_sigframe_ia32
        int sig;
        int pinfo;
        int puc;
-       siginfo_t32 info;
+       compat_siginfo_t info;
        struct ucontext_ia32 uc;
        struct _fpstate_ia32 fpstate;
        char retcode[8];
 };
 
 int
-copy_siginfo_from_user32 (siginfo_t *to, siginfo_t32 __user *from)
+copy_siginfo_from_user32 (siginfo_t *to, compat_siginfo_t __user *from)
 {
 	unsigned long tmp;
 	int err;
 
-	if (!access_ok(VERIFY_READ, from, sizeof(siginfo_t32)))
+	if (!access_ok(VERIFY_READ, from, sizeof(compat_siginfo_t)))
 		return -EFAULT;
 
 	err = __get_user(to->si_signo, &from->si_signo);
@@ -110,12 +110,12 @@ copy_siginfo_from_user32 (siginfo_t *to,
 }
 
 int
-copy_siginfo_to_user32 (siginfo_t32 __user *to, siginfo_t *from)
+copy_siginfo_to_user32 (compat_siginfo_t __user *to, siginfo_t *from)
 {
 	unsigned int addr;
 	int err;
 
-	if (!access_ok(VERIFY_WRITE, to, sizeof(siginfo_t32)))
+	if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
 		return -EFAULT;
 
 	/* If you change siginfo_t structure, please be sure
@@ -589,34 +589,7 @@ sys32_rt_sigprocmask (int how, compat_si
 }
 
 asmlinkage long
-sys32_rt_sigtimedwait (compat_sigset_t __user *uthese, siginfo_t32 __user *uinfo,
-		       struct compat_timespec __user *uts, unsigned int sigsetsize)
-{
-	mm_segment_t old_fs = get_fs();
-	struct timespec t;
-	siginfo_t info;
-	sigset_t s;
-	int ret;
-
-	if (copy_from_user(&s.sig, uthese, sizeof(compat_sigset_t)))
-		return -EFAULT;
-	if (uts && get_compat_timespec(&t, uts))
-		return -EFAULT;
-	set_fs(KERNEL_DS);
-	ret = sys_rt_sigtimedwait((sigset_t __user *) &s,
-				  uinfo ? (siginfo_t __user *) &info : NULL,
-				  uts ? (struct timespec __user *) &t : NULL,
-				  sigsetsize);
-	set_fs(old_fs);
-	if (ret >= 0 && uinfo) {
-		if (copy_siginfo_to_user32(uinfo, &info))
-			return -EFAULT;
-	}
-	return ret;
-}
-
-asmlinkage long
-sys32_rt_sigqueueinfo (int pid, int sig, siginfo_t32 __user *uinfo)
+sys32_rt_sigqueueinfo (int pid, int sig, compat_siginfo_t __user *uinfo)
 {
 	mm_segment_t old_fs = get_fs();
 	siginfo_t info;
diff -Nraup a/arch/ia64/ia32/ia32priv.h b/arch/ia64/ia32/ia32priv.h
--- a/arch/ia64/ia32/ia32priv.h	2004-12-13 03:56:29.000000000 -0800
+++ b/arch/ia64/ia32/ia32priv.h	2004-12-13 04:01:20.000000000 -0800
@@ -232,7 +232,7 @@ typedef union sigval32 {
 
 #define SIGEV_PAD_SIZE32 ((SIGEV_MAX_SIZE/sizeof(int)) - 3)
 
-typedef struct siginfo32 {
+typedef struct compat_siginfo {
 	int si_signo;
 	int si_errno;
 	int si_code;
@@ -282,7 +282,7 @@ typedef struct siginfo32 {
 			int _fd;
 		} _sigpoll;
 	} _sifields;
-} siginfo_t32;
+} compat_siginfo_t;
 
 typedef struct sigevent32 {
 	sigval_t32 sigev_value;
@@ -559,10 +559,6 @@ struct user_regs_struct32 {
 extern int save_ia32_fpstate (struct task_struct *, struct ia32_user_i387_struct __user *);
 extern int save_ia32_fpxstate (struct task_struct *, struct ia32_user_fxsr_struct __user *);
 
-/* Prototypes for use in sys_ia32.c */
-int copy_siginfo_to_user32 (siginfo_t32 __user *to, siginfo_t *from);
-int copy_siginfo_from_user32 (siginfo_t *to, siginfo_t32 __user *from);
-
 #endif /* !CONFIG_IA32_SUPPORT */
 
 #endif /* _ASM_IA64_IA32_PRIV_H */
diff -Nraup a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c
--- a/arch/ia64/ia32/sys_ia32.c	2004-12-13 03:56:29.000000000 -0800
+++ b/arch/ia64/ia32/sys_ia32.c	2004-12-13 04:13:59.000000000 -0800
@@ -2641,7 +2641,7 @@ long sys32_fadvise64_64(int fd, __u32 of
 } 
 
 asmlinkage long sys32_waitid(int which, compat_pid_t pid,
-			     siginfo_t32 __user *uinfo, int options,
+			     compat_siginfo_t __user *uinfo, int options,
 			     struct compat_rusage __user *uru)
 {
 	siginfo_t info;
diff -Nraup a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
--- a/arch/mips/kernel/scall64-n32.S	2004-12-13 03:56:29.000000000 -0800
+++ b/arch/mips/kernel/scall64-n32.S	2004-12-13 03:57:09.000000000 -0800
@@ -243,7 +243,7 @@ EXPORT(sysn32_call_table)
 	PTR	sys_capget
 	PTR	sys_capset
 	PTR	sys32_rt_sigpending		/* 6125 */
-	PTR	sys32_rt_sigtimedwait
+	PTR	compat_rt_sigtimedwait
 	PTR	sys32_rt_sigqueueinfo
 	PTR	sys32_rt_sigsuspend
 	PTR	sys32_sigaltstack
diff -Nraup a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
--- a/arch/mips/kernel/scall64-o32.S	2004-12-13 03:56:29.000000000 -0800
+++ b/arch/mips/kernel/scall64-o32.S	2004-12-13 03:57:09.000000000 -0800
@@ -420,7 +420,7 @@ sys_call_table:
 	PTR	sys32_rt_sigaction
 	PTR	sys32_rt_sigprocmask 		/* 4195 */
 	PTR	sys32_rt_sigpending
-	PTR	sys32_rt_sigtimedwait
+	PTR	compat_rt_sigtimedwait
 	PTR	sys32_rt_sigqueueinfo
 	PTR	sys32_rt_sigsuspend
 	PTR	sys32_pread			/* 4200 */
diff -Nraup a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c
--- a/arch/mips/kernel/signal32.c	2004-12-13 03:56:29.000000000 -0800
+++ b/arch/mips/kernel/signal32.c	2004-12-13 04:25:46.000000000 -0800
@@ -37,7 +37,7 @@ typedef union sigval32 {
 	s32 sival_ptr;
 } sigval_t32;
 
-typedef struct siginfo32 {
+typedef struct compat_siginfo{
 	int si_signo;
 	int si_code;
 	int si_errno;
@@ -93,7 +93,7 @@ typedef struct siginfo32 {
 		} _rt;
 
 	} _sifields;
-} siginfo_t32;
+} compat_siginfo_t;
 
 /*
  * Including <asm/unistd.h> would give use the 64-bit syscall numbers ...
@@ -389,15 +389,15 @@ struct sigframe {
 struct rt_sigframe32 {
 	u32 rs_ass[4];			/* argument save space for o32 */
 	u32 rs_code[2];			/* signal trampoline */
-	struct siginfo32 rs_info;
+	struct compat_siginfo_t rs_info;
 	struct ucontext32 rs_uc;
 };
 
-static int copy_siginfo_to_user32(siginfo_t32 *to, siginfo_t *from)
+int copy_siginfo_to_user32(compat_siginfo_t *to, siginfo_t *from)
 {
 	int err;
 
-	if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t32)))
+	if (!access_ok (VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
 		return -EFAULT;
 
 	/* If you change siginfo_t structure, please be sure
@@ -677,7 +677,7 @@ static inline void setup_rt_frame(struct
 	err |= __put_user(0x0000000c                      , frame->rs_code + 1);
 	flush_cache_sigtramp((unsigned long) frame->rs_code);
 
-	/* Convert (siginfo_t -> siginfo_t32) and copy to user. */
+	/* Convert (siginfo_t -> compat_siginfo_t) and copy to user. */
 	err |= copy_siginfo_to_user32(&frame->rs_info, info);
 
 	/* Create the ucontext.  */
@@ -890,98 +890,7 @@ asmlinkage int sys32_rt_sigpending(compa
 	return ret;
 }
 
-asmlinkage int sys32_rt_sigtimedwait(compat_sigset_t *uthese,
-	siginfo_t32 *uinfo, struct compat_timespec *uts,
-	compat_time_t sigsetsize)
-{
-	int ret, sig;
-	sigset_t these;
-	compat_sigset_t these32;
-	struct timespec ts;
-	siginfo_t info;
-	long timeout = 0;
-
-	/*
-	 * As the result of a brainfarting competition a few years ago the
-	 * size of sigset_t for the 32-bit kernel was choosen to be 128 bits
-	 * but nothing so far is actually using that many, 64 are enough.  So
-	 * for now we just drop the high bits.
-	 */
-	if (copy_from_user (&these32, uthese, sizeof(compat_old_sigset_t)))
-		return -EFAULT;
-
-	switch (_NSIG_WORDS) {
-#ifdef __MIPSEB__
-	case 4: these.sig[3] = these32.sig[6] | (((long)these32.sig[7]) << 32);
-	case 3: these.sig[2] = these32.sig[4] | (((long)these32.sig[5]) << 32);
-	case 2: these.sig[1] = these32.sig[2] | (((long)these32.sig[3]) << 32);
-	case 1: these.sig[0] = these32.sig[0] | (((long)these32.sig[1]) << 32);
-#endif
-#ifdef __MIPSEL__
-	case 4: these.sig[3] = these32.sig[7] | (((long)these32.sig[6]) << 32);
-	case 3: these.sig[2] = these32.sig[5] | (((long)these32.sig[4]) << 32);
-	case 2: these.sig[1] = these32.sig[3] | (((long)these32.sig[2]) << 32);
-	case 1: these.sig[0] = these32.sig[1] | (((long)these32.sig[0]) << 32);
-#endif
-	}
-
-	/*
-	 * Invert the set of allowed signals to get those we
-	 * want to block.
-	 */
-	sigdelsetmask(&these, sigmask(SIGKILL)|sigmask(SIGSTOP));
-	signotset(&these);
-
-	if (uts) {
-		if (get_user (ts.tv_sec, &uts->tv_sec) ||
-		    get_user (ts.tv_nsec, &uts->tv_nsec))
-			return -EINVAL;
-		if (ts.tv_nsec >= 1000000000L || ts.tv_nsec < 0
-		    || ts.tv_sec < 0)
-			return -EINVAL;
-	}
-
-	spin_lock_irq(&current->sighand->siglock);
-	sig = dequeue_signal(current, &these, &info);
-	if (!sig) {
-		/* None ready -- temporarily unblock those we're interested
-		   in so that we'll be awakened when they arrive.  */
-		sigset_t oldblocked = current->blocked;
-		sigandsets(&current->blocked, &current->blocked, &these);
-		recalc_sigpending();
-		spin_unlock_irq(&current->sighand->siglock);
-
-		timeout = MAX_SCHEDULE_TIMEOUT;
-		if (uts)
-			timeout = (timespec_to_jiffies(&ts)
-				   + (ts.tv_sec || ts.tv_nsec));
-
-		current->state = TASK_INTERRUPTIBLE;
-		timeout = schedule_timeout(timeout);
-
-		spin_lock_irq(&current->sighand->siglock);
-		sig = dequeue_signal(current, &these, &info);
-		current->blocked = oldblocked;
-		recalc_sigpending();
-	}
-	spin_unlock_irq(&current->sighand->siglock);
-
-	if (sig) {
-		ret = sig;
-		if (uinfo) {
-			if (copy_siginfo_to_user32(uinfo, &info))
-				ret = -EFAULT;
-		}
-	} else {
-		ret = -EAGAIN;
-		if (timeout)
-			ret = -EINTR;
-	}
-
-	return ret;
-}
-
-asmlinkage int sys32_rt_sigqueueinfo(int pid, int sig, siginfo_t32 *uinfo)
+asmlinkage int sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t *uinfo)
 {
 	siginfo_t info;
 	int ret;
diff -Nraup a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S
--- a/arch/ppc64/kernel/misc.S	2004-12-13 03:56:29.000000000 -0800
+++ b/arch/ppc64/kernel/misc.S	2004-12-13 03:57:09.000000000 -0800
@@ -870,7 +870,7 @@ _GLOBAL(sys_call_table32)
 	.llong .sys32_rt_sigaction
 	.llong .sys32_rt_sigprocmask
 	.llong .sys32_rt_sigpending     /* 175 */
-	.llong .sys32_rt_sigtimedwait
+	.llong .compat_rt_sigtimedwait
 	.llong .sys32_rt_sigqueueinfo
 	.llong .ppc32_rt_sigsuspend
 	.llong .sys32_pread64
diff -Nraup a/arch/ppc64/kernel/signal32.c b/arch/ppc64/kernel/signal32.c
--- a/arch/ppc64/kernel/signal32.c	2004-12-13 03:56:29.000000000 -0800
+++ b/arch/ppc64/kernel/signal32.c	2004-12-13 04:21:43.000000000 -0800
@@ -71,7 +71,7 @@ struct sigregs32 {
  *
  */
 struct rt_sigframe32 {
-	struct compat_siginfo	info;
+	compat_siginfo_t	info;
 	struct ucontext32	uc;
 	/*
 	 * Programs using the rs6000/xcoff abi can save up to 19 gp
@@ -342,7 +342,6 @@ long sys32_sigaction(int sig, struct old
  *       sigpending               sys32_rt_sigpending
  *       sigprocmask              sys32_rt_sigprocmask
  *       sigreturn                sys32_rt_sigreturn
- *       sigtimedwait             sys32_rt_sigtimedwait
  *       sigqueueinfo             sys32_rt_sigqueueinfo
  *       sigsuspend               sys32_rt_sigsuspend
  *
@@ -446,7 +445,7 @@ long sys32_rt_sigpending(compat_sigset_t
 }
 
 
-static long copy_siginfo_to_user32(compat_siginfo_t __user *d, siginfo_t *s)
+long copy_siginfo_to_user32(compat_siginfo_t __user *d, siginfo_t *s)
 {
 	long err;
 
@@ -501,35 +500,6 @@ static long copy_siginfo_to_user32(compa
 	return err;
 }
 
-long sys32_rt_sigtimedwait(compat_sigset_t __user *uthese, compat_siginfo_t __user *uinfo,
-		struct compat_timespec __user *uts, compat_size_t sigsetsize)
-{
-	sigset_t s;
-	compat_sigset_t s32;
-	struct timespec t;
-	int ret;
-	mm_segment_t old_fs = get_fs();
-	siginfo_t info;
-
-	if (copy_from_user(&s32, uthese, sizeof(compat_sigset_t)))
-		return -EFAULT;
-	sigset_from_compat(&s, &s32);
-	if (uts && get_compat_timespec(&t, uts))
-		return -EFAULT;
-	set_fs(KERNEL_DS);
-	/* The __user pointer casts are valid because of the set_fs() */
-	ret = sys_rt_sigtimedwait((sigset_t __user *) &s,
-			uinfo ? (siginfo_t __user *) &info : NULL,
-			uts ? (struct timespec __user *) &t : NULL,
-			sigsetsize);
-	set_fs(old_fs);
-	if (ret >= 0 && uinfo) {
-		if (copy_siginfo_to_user32(uinfo, &info))
-			return -EFAULT;
-	}
-	return ret;
-}
-
 /*
  * Note: it is necessary to treat pid and sig as unsigned ints, with the
  * corresponding cast to a signed int to insure that the proper conversion
diff -Nraup a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c
--- a/arch/s390/kernel/compat_linux.c	2004-12-13 03:56:29.000000000 -0800
+++ b/arch/s390/kernel/compat_linux.c	2004-12-13 04:05:10.000000000 -0800
@@ -634,92 +634,8 @@ asmlinkage long sys32_rt_sigpending(comp
 	return ret;
 }
 
-extern int
-copy_siginfo_to_user32(siginfo_t32 *to, siginfo_t *from);
-
-asmlinkage long
-sys32_rt_sigtimedwait(compat_sigset_t *uthese, siginfo_t32 *uinfo,
-		      struct compat_timespec *uts, size_t sigsetsize)
-{
-	int ret, sig;
-	sigset_t these;
-	compat_sigset_t these32;
-	struct timespec ts;
-	siginfo_t info;
-	long timeout = 0;
-
-	/* XXX: Don't preclude handling different sized sigset_t's.  */
-	if (sigsetsize != sizeof(sigset_t))
-		return -EINVAL;
-
-	if (copy_from_user (&these32, uthese, sizeof(compat_sigset_t)))
-		return -EFAULT;
-
-	switch (_NSIG_WORDS) {
-	case 4: these.sig[3] = these32.sig[6] | (((long)these32.sig[7]) << 32);
-	case 3: these.sig[2] = these32.sig[4] | (((long)these32.sig[5]) << 32);
-	case 2: these.sig[1] = these32.sig[2] | (((long)these32.sig[3]) << 32);
-	case 1: these.sig[0] = these32.sig[0] | (((long)these32.sig[1]) << 32);
-	}
-		
-	/*
-	 * Invert the set of allowed signals to get those we
-	 * want to block.
-	 */
-	sigdelsetmask(&these, sigmask(SIGKILL)|sigmask(SIGSTOP));
-	signotset(&these);
-
-	if (uts) {
-		if (get_compat_timespec(&ts, uts))
-			return -EINVAL;
-		if (ts.tv_nsec >= 1000000000L || ts.tv_nsec < 0
-		    || ts.tv_sec < 0)
-			return -EINVAL;
-	}
-
-	spin_lock_irq(&current->sighand->siglock);
-	sig = dequeue_signal(current, &these, &info);
-	if (!sig) {
-		/* None ready -- temporarily unblock those we're interested
-		   in so that we'll be awakened when they arrive.  */
-		current->real_blocked = current->blocked;
-		sigandsets(&current->blocked, &current->blocked, &these);
-		recalc_sigpending();
-		spin_unlock_irq(&current->sighand->siglock);
-
-		timeout = MAX_SCHEDULE_TIMEOUT;
-		if (uts)
-			timeout = (timespec_to_jiffies(&ts)
-				   + (ts.tv_sec || ts.tv_nsec));
-
-		current->state = TASK_INTERRUPTIBLE;
-		timeout = schedule_timeout(timeout);
-
-		spin_lock_irq(&current->sighand->siglock);
-		sig = dequeue_signal(current, &these, &info);
-		current->blocked = current->real_blocked;
-		siginitset(&current->real_blocked, 0);
-		recalc_sigpending();
-	}
-	spin_unlock_irq(&current->sighand->siglock);
-
-	if (sig) {
-		ret = sig;
-		if (uinfo) {
-			if (copy_siginfo_to_user32(uinfo, &info))
-				ret = -EFAULT;
-		}
-	} else {
-		ret = -EAGAIN;
-		if (timeout)
-			ret = -EINTR;
-	}
-
-	return ret;
-}
-
 asmlinkage long
-sys32_rt_sigqueueinfo(int pid, int sig, siginfo_t32 __user *uinfo)
+sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo)
 {
 	siginfo_t info;
 	int ret;
diff -Nraup a/arch/s390/kernel/compat_linux.h b/arch/s390/kernel/compat_linux.h
--- a/arch/s390/kernel/compat_linux.h	2004-12-13 03:56:29.000000000 -0800
+++ b/arch/s390/kernel/compat_linux.h	2004-12-13 04:05:37.000000000 -0800
@@ -34,7 +34,7 @@ typedef union sigval32 {
         __u32   sival_ptr;
 } sigval_t32;
                  
-typedef struct siginfo32 {
+typedef struct compat_siginfo {
 	int	si_signo;
 	int	si_errno;
 	int	si_code;
@@ -82,7 +82,7 @@ typedef struct siginfo32 {
 			int	_fd;
 		} _sigpoll;
 	} _sifields;
-} siginfo_t32;  
+} compat_siginfo_t;
 
 /*
  * How these fields are to be accessed.
@@ -214,7 +214,4 @@ struct sigevent32 {
 	} _sigev_un;
 };
 
-extern int copy_siginfo_to_user32(siginfo_t32 __user *to, siginfo_t *from);
-extern int copy_siginfo_from_user32(siginfo_t *to, siginfo_t32 __user *from);
-
 #endif /* _ASM_S390X_S390_H */
diff -Nraup a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c
--- a/arch/s390/kernel/compat_signal.c	2004-12-13 03:56:29.000000000 -0800
+++ b/arch/s390/kernel/compat_signal.c	2004-12-13 04:22:09.000000000 -0800
@@ -48,17 +48,17 @@ typedef struct 
 {
 	__u8 callee_used_stack[__SIGNAL_FRAMESIZE32];
 	__u8 retcode[S390_SYSCALL_SIZE];
-	struct siginfo32 info;
+	compat_siginfo_t info;
 	struct ucontext32 uc;
 } rt_sigframe32;
 
 asmlinkage int FASTCALL(do_signal(struct pt_regs *regs, sigset_t *oldset));
 
-int copy_siginfo_to_user32(siginfo_t32 __user *to, siginfo_t *from)
+int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
 {
 	int err;
 
-	if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t32)))
+	if (!access_ok (VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
 		return -EFAULT;
 
 	/* If you change siginfo_t structure, please be sure
@@ -106,12 +106,12 @@ int copy_siginfo_to_user32(siginfo_t32 _
 	return err;
 }
 
-int copy_siginfo_from_user32(siginfo_t *to, siginfo_t32 __user *from)
+int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
 {
 	int err;
 	u32 tmp;
 
-	if (!access_ok (VERIFY_READ, from, sizeof(siginfo_t32)))
+	if (!access_ok (VERIFY_READ, from, sizeof(compat_siginfo_t)))
 		return -EFAULT;
 
 	err = __get_user(to->si_signo, &from->si_signo);
diff -Nraup a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
--- a/arch/s390/kernel/compat_wrapper.S	2004-12-13 03:56:29.000000000 -0800
+++ b/arch/s390/kernel/compat_wrapper.S	2004-12-13 03:57:09.000000000 -0800
@@ -840,13 +840,13 @@ sys32_rt_sigpending_wrapper:
 	llgfr	%r3,%r3			# size_t
 	jg	sys32_rt_sigpending	# branch to system call
 
-	.globl  sys32_rt_sigtimedwait_wrapper 
-sys32_rt_sigtimedwait_wrapper:
+	.globl  compat_rt_sigtimedwait_wrapper
+compat_rt_sigtimedwait_wrapper:
 	llgtr	%r2,%r2			# const sigset_emu31_t *
 	llgtr	%r3,%r3			# siginfo_emu31_t *
 	llgtr	%r4,%r4			# const struct compat_timespec *
 	llgfr	%r5,%r5			# size_t
-	jg	sys32_rt_sigtimedwait	# branch to system call
+	jg	compat_rt_sigtimedwait	# branch to system call
 
 	.globl  sys32_rt_sigqueueinfo_wrapper 
 sys32_rt_sigqueueinfo_wrapper:
diff -Nraup a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
--- a/arch/s390/kernel/ptrace.c	2004-12-13 03:56:29.000000000 -0800
+++ b/arch/s390/kernel/ptrace.c	2004-12-13 04:14:55.000000000 -0800
@@ -559,13 +559,13 @@ do_ptrace_emu31(struct task_struct *chil
 	case PTRACE_GETSIGINFO:
 		if (child->last_siginfo == NULL)
 			return -EINVAL;
-		return copy_siginfo_to_user32((siginfo_t32 __user *) data,
+		return copy_siginfo_to_user32((compat_siginfo_t __user *) data,
 					      child->last_siginfo);
 	case PTRACE_SETSIGINFO:
 		if (child->last_siginfo == NULL)
 			return -EINVAL;
 		return copy_siginfo_from_user32(child->last_siginfo,
-						(siginfo_t32 __user *) data);
+						(compat_siginfo_t __user *) data);
 	}
 	return ptrace_request(child, request, addr, data);
 }
diff -Nraup a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S
--- a/arch/s390/kernel/syscalls.S	2004-12-13 03:56:29.000000000 -0800
+++ b/arch/s390/kernel/syscalls.S	2004-12-13 03:57:09.000000000 -0800
@@ -185,7 +185,7 @@ SYSCALL(sys_rt_sigreturn_glue,sys_rt_sig
 SYSCALL(sys_rt_sigaction,sys_rt_sigaction,sys32_rt_sigaction_wrapper)
 SYSCALL(sys_rt_sigprocmask,sys_rt_sigprocmask,sys32_rt_sigprocmask_wrapper)	/* 175 */
 SYSCALL(sys_rt_sigpending,sys_rt_sigpending,sys32_rt_sigpending_wrapper)
-SYSCALL(sys_rt_sigtimedwait,sys_rt_sigtimedwait,sys32_rt_sigtimedwait_wrapper)
+SYSCALL(sys_rt_sigtimedwait,sys_rt_sigtimedwait,compat_rt_sigtimedwait_wrapper)
 SYSCALL(sys_rt_sigqueueinfo,sys_rt_sigqueueinfo,sys32_rt_sigqueueinfo_wrapper)
 SYSCALL(sys_rt_sigsuspend_glue,sys_rt_sigsuspend_glue,sys32_rt_sigsuspend_glue)
 SYSCALL(sys_pread64,sys_pread64,sys32_pread64_wrapper)		/* 180 */
diff -Nraup a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c
--- a/arch/sparc64/kernel/signal32.c	2004-12-13 03:56:28.000000000 -0800
+++ b/arch/sparc64/kernel/signal32.c	2004-12-13 04:20:43.000000000 -0800
@@ -86,7 +86,7 @@ struct new_signal_frame32 {
 	__siginfo_fpu_t		fpu_state;
 };
 
-struct siginfo32 {
+typedef struct compat_siginfo{
 	int si_signo;
 	int si_errno;
 	int si_code;
@@ -136,11 +136,11 @@ struct siginfo32 {
 			int _fd;
 		} _sigpoll;
 	} _sifields;
-};
+}compat_siginfo_t;
 
 struct rt_signal_frame32 {
 	struct sparc_stackf32	ss;
-	struct siginfo32	info;
+	compat_siginfo_t	info;
 	struct pt_regs32	regs;
 	compat_sigset_t		mask;
 	/* __siginfo_fpu32_t * */ u32 fpu_save;
@@ -157,11 +157,11 @@ struct rt_signal_frame32 {
 #define NF_ALIGNEDSZ  (((sizeof(struct new_signal_frame32) + 7) & (~7)))
 #define RT_ALIGNEDSZ  (((sizeof(struct rt_signal_frame32) + 7) & (~7)))
 
-int copy_siginfo_to_user32(struct siginfo32 __user *to, siginfo_t *from)
+int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
 {
 	int err;
 
-	if (!access_ok(VERIFY_WRITE, to, sizeof(struct siginfo32)))
+	if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
 		return -EFAULT;
 
 	/* If you change siginfo_t structure, please be sure
@@ -210,9 +210,9 @@ int copy_siginfo_to_user32(struct siginf
 /* CAUTION: This is just a very minimalist implementation for the
  *          sake of compat_sys_rt_sigqueueinfo()
  */
-int copy_siginfo_to_kernel32(siginfo_t *to, struct siginfo32 __user *from)
+int copy_siginfo_to_kernel32(siginfo_t *to, compat_siginfo_t __user *from)
 {
-	if (!access_ok(VERIFY_WRITE, from, sizeof(struct siginfo32)))
+	if (!access_ok(VERIFY_WRITE, from, sizeof(compat_siginfo_t)))
 		return -EFAULT;
 
 	if (copy_from_user(to, from, 3*sizeof(int)) ||
diff -Nraup a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
--- a/arch/sparc64/kernel/sys_sparc32.c	2004-12-13 03:56:28.000000000 -0800
+++ b/arch/sparc64/kernel/sys_sparc32.c	2004-12-13 04:06:51.000000000 -0800
@@ -1044,93 +1044,8 @@ asmlinkage long sys32_rt_sigpending(comp
 	return ret;
 }
 
-asmlinkage long sys32_rt_sigtimedwait(compat_sigset_t __user *uthese,
-				      struct siginfo32 __user *uinfo,
-				      struct compat_timespec __user *uts,
-				      compat_size_t sigsetsize)
-{
-	int ret, sig;
-	sigset_t these;
-	compat_sigset_t these32;
-	struct timespec ts;
-	siginfo_t info;
-	long timeout = 0;
-
-	/* XXX: Don't preclude handling different sized sigset_t's.  */
-	if (sigsetsize != sizeof(sigset_t))
-		return -EINVAL;
-
-	if (copy_from_user (&these32, uthese, sizeof(compat_sigset_t)))
-		return -EFAULT;
-
-	switch (_NSIG_WORDS) {
-	case 4: these.sig[3] = these32.sig[6] | (((long)these32.sig[7]) << 32);
-	case 3: these.sig[2] = these32.sig[4] | (((long)these32.sig[5]) << 32);
-	case 2: these.sig[1] = these32.sig[2] | (((long)these32.sig[3]) << 32);
-	case 1: these.sig[0] = these32.sig[0] | (((long)these32.sig[1]) << 32);
-	}
-		
-	/*
-	 * Invert the set of allowed signals to get those we
-	 * want to block.
-	 */
-	sigdelsetmask(&these, sigmask(SIGKILL)|sigmask(SIGSTOP));
-	signotset(&these);
-
-	if (uts) {
-		if (get_compat_timespec(&ts, uts))
-			return -EINVAL;
-		if (ts.tv_nsec >= 1000000000L || ts.tv_nsec < 0
-		    || ts.tv_sec < 0)
-			return -EINVAL;
-	}
-
-	spin_lock_irq(&current->sighand->siglock);
-	sig = dequeue_signal(current, &these, &info);
-	if (!sig) {
-		timeout = MAX_SCHEDULE_TIMEOUT;
-		if (uts)
-			timeout = (timespec_to_jiffies(&ts)
-				   + (ts.tv_sec || ts.tv_nsec));
-
-		if (timeout) {
-			/* None ready -- temporarily unblock those we're
-			 * interested while we are sleeping in so that we'll
-			 * be awakened when they arrive.  */
-			current->real_blocked = current->blocked;
-			sigandsets(&current->blocked, &current->blocked, &these);
-			recalc_sigpending();
-			spin_unlock_irq(&current->sighand->siglock);
-
-			current->state = TASK_INTERRUPTIBLE;
-			timeout = schedule_timeout(timeout);
-
-			spin_lock_irq(&current->sighand->siglock);
-			sig = dequeue_signal(current, &these, &info);
-			current->blocked = current->real_blocked;
-			siginitset(&current->real_blocked, 0);
-			recalc_sigpending();
-		}
-	}
-	spin_unlock_irq(&current->sighand->siglock);
-
-	if (sig) {
-		ret = sig;
-		if (uinfo) {
-			if (copy_siginfo_to_user32(uinfo, &info))
-				ret = -EFAULT;
-		}
-	} else {
-		ret = -EAGAIN;
-		if (timeout)
-			ret = -EINTR;
-	}
-
-	return ret;
-}
-
 asmlinkage long compat_sys_rt_sigqueueinfo(int pid, int sig,
-					   struct siginfo32 __user *uinfo)
+					   compat_siginfo_t __user *uinfo)
 {
 	siginfo_t info;
 	int ret;
@@ -1739,7 +1654,7 @@ sys32_timer_create(u32 clock, struct sig
 }
 
 asmlinkage long compat_sys_waitid(u32 which, u32 pid,
-				  struct siginfo32 __user *uinfo, u32 options,
+				  compat_siginfo_t __user *uinfo, u32 options,
 				  struct compat_rusage __user *uru)
 {
 	siginfo_t info;
diff -Nraup a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S
--- a/arch/sparc64/kernel/systbls.S	2004-12-13 03:56:28.000000000 -0800
+++ b/arch/sparc64/kernel/systbls.S	2004-12-13 03:57:09.000000000 -0800
@@ -41,7 +41,7 @@ sys_call_table32:
 /*90*/	.word sys_dup2, sys_setfsuid, compat_sys_fcntl, sys32_select, sys_setfsgid
 	.word sys_fsync, sys32_setpriority, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
 /*100*/ .word sys32_getpriority, sys32_rt_sigreturn, sys32_rt_sigaction, sys32_rt_sigprocmask, sys32_rt_sigpending
-	.word sys32_rt_sigtimedwait, sys32_rt_sigqueueinfo, sys32_rt_sigsuspend, sys_setresuid, sys_getresuid
+	.word compat_rt_sigtimedwait, sys32_rt_sigqueueinfo, sys32_rt_sigsuspend, sys_setresuid, sys_getresuid
 /*110*/	.word sys_setresgid, sys_getresgid, sys_setregid, sys_nis_syscall, sys_nis_syscall
 	.word sys32_getgroups, sys32_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_getcwd
 /*120*/	.word compat_sys_readv, compat_sys_writev, sys32_settimeofday, sys32_fchown16, sys_fchmod
diff -Nraup a/arch/x86_64/ia32/ia32_signal.c b/arch/x86_64/ia32/ia32_signal.c
--- a/arch/x86_64/ia32/ia32_signal.c	2004-12-13 03:56:29.000000000 -0800
+++ b/arch/x86_64/ia32/ia32_signal.c	2004-12-13 04:08:24.000000000 -0800
@@ -44,10 +44,10 @@
 asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
 void signal_fault(struct pt_regs *regs, void __user *frame, char *where);
 
-int ia32_copy_siginfo_to_user(siginfo_t32 __user *to, siginfo_t *from)
+int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
 {
 	int err;
-	if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t32)))
+	if (!access_ok (VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
 		return -EFAULT;
 
 	/* If you change siginfo_t structure, please make sure that
@@ -95,11 +95,11 @@ int ia32_copy_siginfo_to_user(siginfo_t3
 	return err;
 }
 
-int ia32_copy_siginfo_from_user(siginfo_t *to, siginfo_t32 __user *from)
+int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
 {
 	int err;
 	u32 ptr32;
-	if (!access_ok (VERIFY_READ, from, sizeof(siginfo_t32)))
+	if (!access_ok (VERIFY_READ, from, sizeof(compat_siginfo_t)))
 		return -EFAULT;
 
 	err = __get_user(to->si_signo, &from->si_signo);
@@ -188,7 +188,7 @@ struct rt_sigframe
 	int sig;
 	u32 pinfo;
 	u32 puc;
-	struct siginfo32 info;
+	compat_siginfo_t info;
 	struct ucontext_ia32 uc;
 	struct _fpstate_ia32 fpstate;
 	char retcode[8];
@@ -536,7 +536,7 @@ void ia32_setup_rt_frame(int sig, struct
 	}
 	err |= __put_user((u32)(u64)&frame->info, &frame->pinfo);
 	err |= __put_user((u32)(u64)&frame->uc, &frame->puc);
-	err |= ia32_copy_siginfo_to_user(&frame->info, info);
+	err |= copy_siginfo_to_user32(&frame->info, info);
 	if (err)
 		goto give_sigsegv;
 
diff -Nraup a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S
--- a/arch/x86_64/ia32/ia32entry.S	2004-12-13 03:56:29.000000000 -0800
+++ b/arch/x86_64/ia32/ia32entry.S	2004-12-13 03:57:09.000000000 -0800
@@ -479,7 +479,7 @@ ia32_sys_call_table:
 	.quad sys32_rt_sigaction
 	.quad sys32_rt_sigprocmask	/* 175 */
 	.quad sys32_rt_sigpending
-	.quad sys32_rt_sigtimedwait
+	.quad compat_rt_sigtimedwait
 	.quad sys32_rt_sigqueueinfo
 	.quad stub32_rt_sigsuspend
 	.quad sys32_pread		/* 180 */
diff -Nraup a/arch/x86_64/ia32/sys_ia32.c b/arch/x86_64/ia32/sys_ia32.c
--- a/arch/x86_64/ia32/sys_ia32.c	2004-12-13 03:56:29.000000000 -0800
+++ b/arch/x86_64/ia32/sys_ia32.c	2004-12-13 04:08:59.000000000 -0800
@@ -628,53 +628,14 @@ sys32_rt_sigpending(compat_sigset_t __us
 	return ret;
 }
 
-
-asmlinkage long
-sys32_rt_sigtimedwait(compat_sigset_t __user *uthese, siginfo_t32 __user *uinfo,
-		      struct compat_timespec __user *uts, compat_size_t sigsetsize)
-{
-	sigset_t s;
-	compat_sigset_t s32;
-	struct timespec t;
-	int ret;
-	mm_segment_t old_fs = get_fs();
-	siginfo_t info;
-		
-	if (copy_from_user (&s32, uthese, sizeof(compat_sigset_t)))
-		return -EFAULT;
-	switch (_NSIG_WORDS) {
-	case 4: s.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32);
-	case 3: s.sig[2] = s32.sig[4] | (((long)s32.sig[5]) << 32);
-	case 2: s.sig[1] = s32.sig[2] | (((long)s32.sig[3]) << 32);
-	case 1: s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32);
-	}
-	if (uts && get_compat_timespec(&t, uts))
-		return -EFAULT;
-	if (uinfo) {
-		/* stop data leak to user space in case of structure fill mismatch
-		 * between sys_rt_sigtimedwait & ia32_copy_siginfo_to_user.
-		 */
-		memset(&info, 0, sizeof(info));
-	}
-	set_fs (KERNEL_DS);
-	ret = sys_rt_sigtimedwait(&s, uinfo ? &info : NULL, uts ? &t : NULL,
-			sigsetsize);
-	set_fs (old_fs);
-	if (ret >= 0 && uinfo) {
-		if (ia32_copy_siginfo_to_user(uinfo, &info))
-			return -EFAULT;
-	}
-	return ret;
-}
-
 asmlinkage long
-sys32_rt_sigqueueinfo(int pid, int sig, siginfo_t32 __user *uinfo)
+sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo)
 {
 	siginfo_t info;
 	int ret;
 	mm_segment_t old_fs = get_fs();
 	
-	if (ia32_copy_siginfo_from_user(&info, uinfo))
+	if (copy_siginfo_from_user32(&info, uinfo))
 		return -EFAULT;
 	set_fs (KERNEL_DS);
 	ret = sys_rt_sigqueueinfo(pid, sig, &info);
@@ -1000,7 +961,7 @@ asmlinkage long sys32_clone(unsigned int
 }
 
 asmlinkage long sys32_waitid(int which, compat_pid_t pid,
-			     siginfo_t32 __user *uinfo, int options,
+			     compat_siginfo_t __user *uinfo, int options,
 			     struct compat_rusage __user *uru)
 {
 	siginfo_t info;
@@ -1022,7 +983,7 @@ asmlinkage long sys32_waitid(int which, 
 
 	BUG_ON(info.si_code & __SI_MASK);
 	info.si_code |= __SI_CHLD;
-	return ia32_copy_siginfo_to_user(uinfo, &info);
+	return copy_siginfo_to_user32(uinfo, &info);
 }
 
 /*
diff -Nraup a/include/asm-mips/compat.h b/include/asm-mips/compat.h
--- a/include/asm-mips/compat.h	2004-12-13 03:56:29.000000000 -0800
+++ b/include/asm-mips/compat.h	2004-12-13 03:57:09.000000000 -0800
@@ -137,5 +137,8 @@ static inline void *compat_alloc_user_sp
 
 	return (void *) (regs->regs[29] - len);
 }
+#if defined (__MIPSEL__)
+#define __COMPAT_ENDIAN_SWAP__ 	1
+#endif
 
 #endif /* _ASM_COMPAT_H */
diff -Nraup a/include/asm-sparc64/siginfo.h b/include/asm-sparc64/siginfo.h
--- a/include/asm-sparc64/siginfo.h	2004-12-13 03:56:40.000000000 -0800
+++ b/include/asm-sparc64/siginfo.h	2004-12-13 04:25:08.000000000 -0800
@@ -24,7 +24,7 @@ typedef union sigval32 {
 	u32 sival_ptr;
 } sigval_t32;
 
-struct siginfo32;
+struct compat_siginfo;
 
 #endif /* CONFIG_COMPAT */
 
@@ -56,9 +56,6 @@ typedef struct sigevent32 {
 	} _sigev_un;
 } sigevent_t32;
 
-extern int copy_siginfo_to_user32(struct siginfo32 __user *to, siginfo_t *from);
-extern int copy_siginfo_to_kernel32(siginfo_t *to, struct siginfo32 __user *from);
-
 #endif /* CONFIG_COMPAT */
 
 #endif /* __KERNEL__ */
diff -Nraup a/include/asm-x86_64/ia32.h b/include/asm-x86_64/ia32.h
--- a/include/asm-x86_64/ia32.h	2004-12-13 03:56:29.000000000 -0800
+++ b/include/asm-x86_64/ia32.h	2004-12-13 04:23:35.000000000 -0800
@@ -78,7 +78,7 @@ struct stat64 {
 	unsigned long long	st_ino;
 } __attribute__((packed));
 
-typedef struct siginfo32 {
+typedef struct compat_siginfo{
 	int si_signo;
 	int si_errno;
 	int si_code;
@@ -128,7 +128,7 @@ typedef struct siginfo32 {
 			int _fd;
 		} _sigpoll;
 	} _sifields;
-} siginfo_t32;
+} compat_siginfo_t;
 
 struct sigframe32
 {
@@ -145,7 +145,7 @@ struct rt_sigframe32
         int sig;
         u32 pinfo;
         u32 puc;
-        struct siginfo32 info;
+        compat_siginfo_t info;
         struct ucontext_ia32 uc;
         struct _fpstate_ia32 fpstate;
 };
@@ -165,8 +165,6 @@ struct siginfo_t;
 int do_get_thread_area(struct thread_struct *t, struct user_desc __user *info);
 int do_set_thread_area(struct thread_struct *t, struct user_desc __user *info);
 int ia32_child_tls(struct task_struct *p, struct pt_regs *childregs);
-int ia32_copy_siginfo_from_user(siginfo_t *to, siginfo_t32 __user *from);
-int ia32_copy_siginfo_to_user(siginfo_t32 __user *to, siginfo_t *from);
 #endif
 
 #endif /* !CONFIG_IA32_SUPPORT */
diff -Nraup a/include/linux/compat.h b/include/linux/compat.h
--- a/include/linux/compat.h	2004-12-13 03:56:29.000000000 -0800
+++ b/include/linux/compat.h	2004-12-13 04:24:28.000000000 -0800
@@ -143,6 +143,8 @@ long compat_get_bitmap(unsigned long *ma
 		       unsigned long bitmap_size);
 long compat_put_bitmap(compat_ulong_t __user *umask, unsigned long *mask,
 		       unsigned long bitmap_size);
-
+struct compat_siginfo;
+int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from);
+int copy_siginfo_to_user32(struct compat_siginfo __user *to, siginfo_t *from);
 #endif /* CONFIG_COMPAT */
 #endif /* _LINUX_COMPAT_H */
diff -Nraup a/kernel/compat.c b/kernel/compat.c
--- a/kernel/compat.c	2004-12-13 03:56:41.000000000 -0800
+++ b/kernel/compat.c	2004-12-13 04:11:52.000000000 -0800
@@ -682,6 +682,92 @@ long compat_put_bitmap(compat_ulong_t __
 	return 0;
 }
 
+void
+sigset_from_compat (sigset_t *set, compat_sigset_t *compat)
+{
+	switch (_NSIG_WORDS) {
+#if defined (__COMPAT_ENDIAN_SWAP__)
+	case 4: set->sig[3] = compat->sig[7] | (((long)compat->sig[6]) << 32 );
+	case 3: set->sig[2] = compat->sig[5] | (((long)compat->sig[4]) << 32 );
+	case 2: set->sig[1] = compat->sig[3] | (((long)compat->sig[2]) << 32 );
+	case 1: set->sig[0] = compat->sig[1] | (((long)compat->sig[0]) << 32 );
+#else
+	case 4: set->sig[3] = compat->sig[6] | (((long)compat->sig[7]) << 32 );
+	case 3: set->sig[2] = compat->sig[4] | (((long)compat->sig[5]) << 32 );
+	case 2: set->sig[1] = compat->sig[2] | (((long)compat->sig[3]) << 32 );
+	case 1: set->sig[0] = compat->sig[0] | (((long)compat->sig[1]) << 32 );
+#endif
+	}
+}
+
+asmlinkage long
+compat_rt_sigtimedwait (compat_sigset_t __user *uthese,
+		struct compat_siginfo __user *uinfo,
+		struct compat_timespec __user *uts, compat_size_t sigsetsize)
+{
+	compat_sigset_t s32;
+	sigset_t s;
+	int sig;
+	struct timespec t;
+	siginfo_t info;
+	long ret, timeout = 0;
+
+	if (sigsetsize != sizeof(sigset_t))
+		return -EINVAL;
+
+	if (copy_from_user(&s32, uthese, sizeof(compat_sigset_t)))
+		return -EFAULT;
+	sigset_from_compat(&s, &s32);
+	sigdelsetmask(&s,sigmask(SIGKILL)|sigmask(SIGSTOP));
+	signotset(&s);
+
+	if (uts) {
+		if (get_compat_timespec (&t, uts))
+			return -EFAULT;
+		if (t.tv_nsec >= 1000000000L || t.tv_nsec < 0
+				|| t.tv_sec < 0)
+			return -EINVAL;
+	}
+
+	spin_lock_irq(&current->sighand->siglock);
+	sig = dequeue_signal(current, &s, &info);
+	if (!sig) {
+		timeout = MAX_SCHEDULE_TIMEOUT;
+		if (uts)
+			timeout = timespec_to_jiffies(&t)
+				+(t.tv_sec || t.tv_nsec);
+		if (timeout) {
+			current->real_blocked = current->blocked;
+			sigandsets(&current->blocked, &current->blocked, &s);
+
+			recalc_sigpending();
+			spin_unlock_irq(&current->sighand->siglock);
+
+			current->state = TASK_INTERRUPTIBLE;
+			timeout = schedule_timeout(timeout);
+
+			spin_lock_irq(&current->sighand->siglock);
+			sig = dequeue_signal(current, &s, &info);
+			current->blocked = current->real_blocked;
+			siginitset(&current->real_blocked, 0);
+			recalc_sigpending();
+		}
+	}
+	spin_unlock_irq(&current->sighand->siglock);
+
+	if (sig) {
+		ret = sig;
+		if (uinfo) {
+			if (copy_siginfo_to_user32(uinfo, &info))
+				ret = -EFAULT;
+		}
+	}else {
+		ret = timeout?-EINTR:-EAGAIN;
+	}
+	return ret;
+
+}
+
 #ifdef __ARCH_WANT_COMPAT_SYS_TIME
 
 /* compat_time_t is a 32 bit "long" and needs to get converted. */

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2004-12-14  6:02 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-12-10  0:40 [Compatibilty patch] sigtimedwait Zou, Nanhai
2004-12-10  1:08 ` David S. Miller
  -- strict thread matches above, loose matches on Subject: below --
2004-12-14  6:00 Zou, Nanhai
2004-12-10  0:49 Zou, Nanhai
2004-12-08  0:48 Zou, Nanhai
2004-12-08  5:35 ` David S. Miller
2004-12-08 11:32 ` Stephen Rothwell
2004-12-08 12:09 ` Stephen Rothwell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox