summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordchagin <dchagin@FreeBSD.org>2016-01-09 17:45:02 +0000
committerdchagin <dchagin@FreeBSD.org>2016-01-09 17:45:02 +0000
commit735299091c2bab74e403108217b1e3f01e1fd3d8 (patch)
tree1d63c42383623542fc004f49ece6483df1a920c2
parenta28a640f6442993bdc17d3c331fcf93820a3698b (diff)
downloadFreeBSD-src-735299091c2bab74e403108217b1e3f01e1fd3d8.zip
FreeBSD-src-735299091c2bab74e403108217b1e3f01e1fd3d8.tar.gz
MFC r283484:
Implement epoll_pwait() system call.
-rw-r--r--sys/amd64/linux/linux_dummy.c1
-rw-r--r--sys/amd64/linux32/linux32_dummy.c1
-rw-r--r--sys/amd64/linux32/syscalls.master2
-rw-r--r--sys/compat/linux/linux_event.c64
-rw-r--r--sys/i386/linux/linux_dummy.c1
-rw-r--r--sys/i386/linux/syscalls.master2
6 files changed, 56 insertions, 15 deletions
diff --git a/sys/amd64/linux/linux_dummy.c b/sys/amd64/linux/linux_dummy.c
index 38c14ad..e765310 100644
--- a/sys/amd64/linux/linux_dummy.c
+++ b/sys/amd64/linux/linux_dummy.c
@@ -98,7 +98,6 @@ DUMMY(tee);
DUMMY(sync_file_range);
DUMMY(vmsplice);
DUMMY(move_pages);
-DUMMY(epoll_pwait);
DUMMY(signalfd);
DUMMY(timerfd);
DUMMY(timerfd_settime);
diff --git a/sys/amd64/linux32/linux32_dummy.c b/sys/amd64/linux32/linux32_dummy.c
index 51b3207..96f3299 100644
--- a/sys/amd64/linux32/linux32_dummy.c
+++ b/sys/amd64/linux32/linux32_dummy.c
@@ -103,7 +103,6 @@ DUMMY(vmsplice);
DUMMY(move_pages);
/* linux 2.6.19: */
DUMMY(getcpu);
-DUMMY(epoll_pwait);
/* linux 2.6.22: */
DUMMY(signalfd);
DUMMY(timerfd_create);
diff --git a/sys/amd64/linux32/syscalls.master b/sys/amd64/linux32/syscalls.master
index 5413a33..caf9357 100644
--- a/sys/amd64/linux32/syscalls.master
+++ b/sys/amd64/linux32/syscalls.master
@@ -531,7 +531,7 @@
; linux 2.6.19:
318 AUE_NULL STD { int linux_getcpu(void); }
319 AUE_NULL STD { int linux_epoll_pwait(l_int epfd, struct epoll_event *events, \
- l_int maxevents, l_int timeout, l_osigset_t *mask); }
+ l_int maxevents, l_int timeout, l_sigset_t *mask); }
; linux 2.6.22:
320 AUE_FUTIMESAT STD { int linux_utimensat(l_int dfd, const char *pathname, \
const struct l_timespec *times, l_int flags); }
diff --git a/sys/compat/linux/linux_event.c b/sys/compat/linux/linux_event.c
index 4a54933..8780373 100644
--- a/sys/compat/linux/linux_event.c
+++ b/sys/compat/linux/linux_event.c
@@ -468,8 +468,9 @@ leave1:
/*
* Wait for a filter to be triggered on the epoll file descriptor.
*/
-int
-linux_epoll_wait(struct thread *td, struct linux_epoll_wait_args *args)
+static int
+linux_epoll_wait_common(struct thread *td, int epfd, struct epoll_event *events,
+ int maxevents, int timeout, sigset_t *uset)
{
struct file *epfp;
struct timespec ts, *tsp;
@@ -480,33 +481,49 @@ linux_epoll_wait(struct thread *td, struct linux_epoll_wait_args *args)
NULL};
int error;
- if (args->maxevents <= 0 || args->maxevents > LINUX_MAX_EVENTS)
+ if (maxevents <= 0 || maxevents > LINUX_MAX_EVENTS)
return (EINVAL);
- error = fget(td, args->epfd,
+ if (uset != NULL) {
+ error = kern_sigprocmask(td, SIG_SETMASK, uset,
+ &td->td_oldsigmask, 0);
+ if (error != 0)
+ return (error);
+ td->td_pflags |= TDP_OLDMASK;
+ /*
+ * Make sure that ast() is called on return to
+ * usermode and TDP_OLDMASK is cleared, restoring old
+ * sigmask.
+ */
+ thread_lock(td);
+ td->td_flags |= TDF_ASTPENDING;
+ thread_unlock(td);
+ }
+
+ error = fget(td, epfd,
cap_rights_init(&rights, CAP_KQUEUE_EVENT), &epfp);
if (error != 0)
return (error);
- coargs.leventlist = args->events;
+ coargs.leventlist = events;
coargs.p = td->td_proc;
coargs.count = 0;
coargs.error = 0;
- if (args->timeout != -1) {
- if (args->timeout < 0) {
+ if (timeout != -1) {
+ if (timeout < 0) {
error = EINVAL;
goto leave;
}
/* Convert from milliseconds to timespec. */
- ts.tv_sec = args->timeout / 1000;
- ts.tv_nsec = (args->timeout % 1000) * 1000000;
+ ts.tv_sec = timeout / 1000;
+ ts.tv_nsec = (timeout % 1000) * 1000000;
tsp = &ts;
} else {
tsp = NULL;
}
- error = kern_kevent_fp(td, epfp, 0, args->maxevents, &k_ops, tsp);
+ error = kern_kevent_fp(td, epfp, 0, maxevents, &k_ops, tsp);
if (error == 0 && coargs.error != 0)
error = coargs.error;
@@ -521,6 +538,33 @@ leave:
return (error);
}
+int
+linux_epoll_wait(struct thread *td, struct linux_epoll_wait_args *args)
+{
+
+ return (linux_epoll_wait_common(td, args->epfd, args->events,
+ args->maxevents, args->timeout, NULL));
+}
+
+int
+linux_epoll_pwait(struct thread *td, struct linux_epoll_pwait_args *args)
+{
+ sigset_t mask, *pmask;
+ l_sigset_t lmask;
+ int error;
+
+ if (args->mask != NULL) {
+ error = copyin(args->mask, &lmask, sizeof(l_sigset_t));
+ if (error != 0)
+ return (error);
+ linux_to_bsd_sigset(&lmask, &mask);
+ pmask = &mask;
+ } else
+ pmask = NULL;
+ return (linux_epoll_wait_common(td, args->epfd, args->events,
+ args->maxevents, args->timeout, pmask));
+}
+
static int
epoll_delete_event(struct thread *td, struct file *epfp, int fd, int filter)
{
diff --git a/sys/i386/linux/linux_dummy.c b/sys/i386/linux/linux_dummy.c
index 8b57c66..74452f6 100644
--- a/sys/i386/linux/linux_dummy.c
+++ b/sys/i386/linux/linux_dummy.c
@@ -99,7 +99,6 @@ DUMMY(vmsplice);
DUMMY(move_pages);
/* linux 2.6.19: */
DUMMY(getcpu);
-DUMMY(epoll_pwait);
/* linux 2.6.22: */
DUMMY(signalfd);
DUMMY(timerfd_create);
diff --git a/sys/i386/linux/syscalls.master b/sys/i386/linux/syscalls.master
index 3864762..5cb57f5 100644
--- a/sys/i386/linux/syscalls.master
+++ b/sys/i386/linux/syscalls.master
@@ -539,7 +539,7 @@
; linux 2.6.19:
318 AUE_NULL STD { int linux_getcpu(void); }
319 AUE_NULL STD { int linux_epoll_pwait(l_int epfd, struct epoll_event *events, \
- l_int maxevents, l_int timeout, l_osigset_t *mask); }
+ l_int maxevents, l_int timeout, l_sigset_t *mask); }
; linux 2.6.22:
320 AUE_FUTIMESAT STD { int linux_utimensat(l_int dfd, const char *pathname, \
const struct l_timespec *times, l_int flags); }
OpenPOWER on IntegriCloud