On Tue, 2006-10-03 at 08:57 +0100, David Woodhouse wrote:
> On Tue, 2006-10-03 at 00:27 -0700, Andrew Morton wrote:
> > 
> > I'm about to send this Linuswards.  Architectures which implement
> > TIF_RESTORE_SIGMASK can wire it up.
> 
> It needs compat_sys_epoll_wait() for the signal stuff though.

Something like the patch below ought to suffice, although it's not
tested further than just building it.

----
[PATCH] Provide compat_sys_epoll_pwait(), wire up on PowerPC.

Also add a comment trying to make sense of the definition of
struct epoll_event.

Signed-off-by: David Woodhouse <[EMAIL PROTECTED]>

diff -u a/fs/eventpoll.c b/fs/eventpoll.c
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -35,6 +35,7 @@
 #include <linux/mount.h>
 #include <linux/bitops.h>
 #include <linux/mutex.h>
+#include <linux/compat.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/io.h>
@@ -745,6 +746,53 @@
        return error;
 }
 
+#ifdef CONFIG_COMPAT
+extern void sigset_from_compat(sigset_t *set, compat_sigset_t *compat);
+
+asmlinkage long compat_sys_epoll_pwait(int epfd, struct epoll_event __user 
*events,
+                                      int maxevents, int timeout,
+                                      const compat_sigset_t __user *sigmask,
+                                      compat_size_t sigsetsize)
+{
+       int error;
+       compat_sigset_t ss32;
+       sigset_t ksigmask, sigsaved;
+
+       /*
+        * If the caller wants a certain signal mask to be set during the wait,
+        * we apply it here.
+        */
+       if (sigmask) {
+               if (sigsetsize != sizeof(compat_sigset_t))
+                       return -EINVAL;
+               if (copy_from_user(&ss32, sigmask, sizeof(ss32)))
+                       return -EFAULT;
+               sigset_from_compat(&ksigmask, &ss32);
+
+               sigdelsetmask(&ksigmask, sigmask(SIGKILL) | sigmask(SIGSTOP));
+               sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
+       }
+
+       error = sys_epoll_wait(epfd, events, maxevents, timeout);
+
+       /*
+        * If we changed the signal mask, we need to restore the original one.
+        * In case we've got a signal while waiting, we do not restore the 
signal
+        * mask yet, and we allow do_signal() to deliver the signal on the way 
back
+        * to userspace, before the signal mask is restored.
+        */
+       if (sigmask) {
+               if (error == -EINTR) {
+                       memcpy(&current->saved_sigmask, &sigsaved, 
sizeof(sigsaved));
+                       set_thread_flag(TIF_RESTORE_SIGMASK);
+               } else
+                       sigprocmask(SIG_SETMASK, &sigsaved, NULL);
+       }
+
+       return error;
+}
+#endif /* CONFIG_COMPAT */
+
 #endif /* #ifdef TIF_RESTORE_SIGMASK */
 
 
only in patch2:
unchanged:
--- a/include/asm-powerpc/systbl.h
+++ b/include/asm-powerpc/systbl.h
@@ -304,3 +304,4 @@ SYSCALL_SPU(fchmodat)
 SYSCALL_SPU(faccessat)
 COMPAT_SYS_SPU(get_robust_list)
 COMPAT_SYS_SPU(set_robust_list)
+COMPAT_SYS(epoll_pwait)
only in patch2:
unchanged:
--- a/include/asm-powerpc/unistd.h
+++ b/include/asm-powerpc/unistd.h
@@ -323,10 +323,11 @@ #define __NR_fchmodat             297
 #define __NR_faccessat         298
 #define __NR_get_robust_list   299
 #define __NR_set_robust_list   300
+#define __NR_epoll_pwait       301
 
 #ifdef __KERNEL__
 
-#define __NR_syscalls          301
+#define __NR_syscalls          302
 
 #define __NR__exit __NR_exit
 #define NR_syscalls    __NR_syscalls
only in patch2:
unchanged:
--- a/include/linux/eventpoll.h
+++ b/include/linux/eventpoll.h
@@ -29,8 +29,11 @@ #define EPOLLONESHOT (1 << 30)
 #define EPOLLET (1 << 31)
 
 /* 
- * On x86-64 make the 64bit structure have the same alignment as the
- * 32bit structure. This makes 32bit emulation easier.
+ * On i386, the u64 won't be aligned to 64-bits. So on x86_64 we pack
+ * the structure to be compatible. It seems that other 32-bit architectures
+ * will align the u64 naturally anyway, so we don't have to worry there.
+ * For example, both ppc and ppc64 put an extra 32 bits of padding in 
+ * between the fields.
  */
 #ifdef __x86_64__
 #define EPOLL_PACKED __attribute__((packed))


-- 
dwmw2

-
To unsubscribe from this list: send the line "unsubscribe linux-arch" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to