aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorDavide Libenzi <davidel@xmailserver.org>2006-10-11 04:21:44 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-10-11 14:14:21 -0400
commitb611967de4dc5c52049676c4369dcac622a7cdfe (patch)
tree8c19038c8bbaa4851dcb99bed33707deaf5170d1 /fs
parent0f836e5fecf59d0d0353e9af11fd14a32a3001ae (diff)
[PATCH] epoll_pwait()
Implement the epoll_pwait system call, that extend the event wait mechanism with the same logic ppoll and pselect do. The definition of epoll_pwait is: int epoll_pwait(int epfd, struct epoll_event *events, int maxevents, int timeout, const sigset_t *sigmask, size_t sigsetsize); The difference between the vanilla epoll_wait and epoll_pwait is that the latter allows the caller to specify a signal mask to be set while waiting for events. Hence epoll_pwait will wait until either one monitored event, or an unmasked signal happen. If sigmask is NULL, the epoll_pwait system call will act exactly like epoll_wait. For the POSIX definition of pselect, information is available here: http://www.opengroup.org/onlinepubs/009695399/functions/select.html Signed-off-by: Davide Libenzi <davidel@xmailserver.org> Cc: David Woodhouse <dwmw2@infradead.org> Cc: Andi Kleen <ak@muc.de> Cc: Michael Kerrisk <mtk-manpages@gmx.net> Cc: Ulrich Drepper <drepper@redhat.com> Cc: Roland McGrath <roland@redhat.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/eventpoll.c56
1 files changed, 53 insertions, 3 deletions
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 557d5b614fae..ae228ec54e94 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -105,6 +105,8 @@
105/* Maximum msec timeout value storeable in a long int */ 105/* Maximum msec timeout value storeable in a long int */
106#define EP_MAX_MSTIMEO min(1000ULL * MAX_SCHEDULE_TIMEOUT / HZ, (LONG_MAX - 999ULL) / HZ) 106#define EP_MAX_MSTIMEO min(1000ULL * MAX_SCHEDULE_TIMEOUT / HZ, (LONG_MAX - 999ULL) / HZ)
107 107
108#define EP_MAX_EVENTS (INT_MAX / sizeof(struct epoll_event))
109
108 110
109struct epoll_filefd { 111struct epoll_filefd {
110 struct file *file; 112 struct file *file;
@@ -497,7 +499,7 @@ void eventpoll_release_file(struct file *file)
497 */ 499 */
498asmlinkage long sys_epoll_create(int size) 500asmlinkage long sys_epoll_create(int size)
499{ 501{
500 int error, fd; 502 int error, fd = -1;
501 struct eventpoll *ep; 503 struct eventpoll *ep;
502 struct inode *inode; 504 struct inode *inode;
503 struct file *file; 505 struct file *file;
@@ -640,7 +642,6 @@ eexit_1:
640 return error; 642 return error;
641} 643}
642 644
643#define MAX_EVENTS (INT_MAX / sizeof(struct epoll_event))
644 645
645/* 646/*
646 * Implement the event wait interface for the eventpoll file. It is the kernel 647 * Implement the event wait interface for the eventpoll file. It is the kernel
@@ -657,7 +658,7 @@ asmlinkage long sys_epoll_wait(int epfd, struct epoll_event __user *events,
657 current, epfd, events, maxevents, timeout)); 658 current, epfd, events, maxevents, timeout));
658 659
659 /* The maximum number of event must be greater than zero */ 660 /* The maximum number of event must be greater than zero */
660 if (maxevents <= 0 || maxevents > MAX_EVENTS) 661 if (maxevents <= 0 || maxevents > EP_MAX_EVENTS)
661 return -EINVAL; 662 return -EINVAL;
662 663
663 /* Verify that the area passed by the user is writeable */ 664 /* Verify that the area passed by the user is writeable */
@@ -699,6 +700,55 @@ eexit_1:
699} 700}
700 701
701 702
703#ifdef TIF_RESTORE_SIGMASK
704
705/*
706 * Implement the event wait interface for the eventpoll file. It is the kernel
707 * part of the user space epoll_pwait(2).
708 */
709asmlinkage long sys_epoll_pwait(int epfd, struct epoll_event __user *events,
710 int maxevents, int timeout, const sigset_t __user *sigmask,
711 size_t sigsetsize)
712{
713 int error;
714 sigset_t ksigmask, sigsaved;
715
716 /*
717 * If the caller wants a certain signal mask to be set during the wait,
718 * we apply it here.
719 */
720 if (sigmask) {
721 if (sigsetsize != sizeof(sigset_t))
722 return -EINVAL;
723 if (copy_from_user(&ksigmask, sigmask, sizeof(ksigmask)))
724 return -EFAULT;
725 sigdelsetmask(&ksigmask, sigmask(SIGKILL) | sigmask(SIGSTOP));
726 sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
727 }
728
729 error = sys_epoll_wait(epfd, events, maxevents, timeout);
730
731 /*
732 * If we changed the signal mask, we need to restore the original one.
733 * In case we've got a signal while waiting, we do not restore the
734 * signal mask yet, and we allow do_signal() to deliver the signal on
735 * the way back to userspace, before the signal mask is restored.
736 */
737 if (sigmask) {
738 if (error == -EINTR) {
739 memcpy(&current->saved_sigmask, &sigsaved,
740 sizeof(sigsaved));
741 set_thread_flag(TIF_RESTORE_SIGMASK);
742 } else
743 sigprocmask(SIG_SETMASK, &sigsaved, NULL);
744 }
745
746 return error;
747}
748
749#endif /* #ifdef TIF_RESTORE_SIGMASK */
750
751
702/* 752/*
703 * Creates the file descriptor to be used by the epoll interface. 753 * Creates the file descriptor to be used by the epoll interface.
704 */ 754 */