aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/libc/include/libc_private.h4
-rw-r--r--lib/libc/sys/Makefile.inc1
-rw-r--r--lib/libc/sys/interposing_table.c1
-rw-r--r--lib/libc/sys/kevent.c53
-rw-r--r--lib/libc/sys/kqueue.225
-rw-r--r--lib/libthr/thread/thr_syscalls.c24
-rw-r--r--share/man/man3/pthread_testcancel.311
7 files changed, 116 insertions, 3 deletions
diff --git a/lib/libc/include/libc_private.h b/lib/libc/include/libc_private.h
index e4bf4a6afd82..ceaa2a34fe78 100644
--- a/lib/libc/include/libc_private.h
+++ b/lib/libc/include/libc_private.h
@@ -221,6 +221,7 @@ enum {
INTERPOS__pthread_mutex_init_calloc_cb,
INTERPOS_spinlock,
INTERPOS_spinunlock,
+ INTERPOS_kevent,
INTERPOS_MAX
};
@@ -293,6 +294,7 @@ void * __sys_freebsd6_mmap(void *, __size_t, int, int, int, int, __off_t);
struct aiocb;
struct fd_set;
struct iovec;
+struct kevent;
struct msghdr;
struct pollfd;
struct rusage;
@@ -315,6 +317,8 @@ int __sys_fsync(int);
__pid_t __sys_fork(void);
int __sys_ftruncate(int, __off_t);
int __sys_gettimeofday(struct timeval *, struct timezone *);
+int __sys_kevent(int, const struct kevent *, int, struct kevent *,
+ int, const struct timespec *);
__off_t __sys_lseek(int, __off_t, int);
void *__sys_mmap(void *, __size_t, int, int, int, __off_t);
int __sys_msync(void *, __size_t, int);
diff --git a/lib/libc/sys/Makefile.inc b/lib/libc/sys/Makefile.inc
index 0edf644bae5f..7745b2a2caa6 100644
--- a/lib/libc/sys/Makefile.inc
+++ b/lib/libc/sys/Makefile.inc
@@ -51,6 +51,7 @@ INTERPOSED = \
fcntl \
fsync \
fork \
+ kevent \
msync \
nanosleep \
open \
diff --git a/lib/libc/sys/interposing_table.c b/lib/libc/sys/interposing_table.c
index 0fd6c75ce99c..4290bc65e54c 100644
--- a/lib/libc/sys/interposing_table.c
+++ b/lib/libc/sys/interposing_table.c
@@ -75,6 +75,7 @@ interpos_func_t __libc_interposing[INTERPOS_MAX] = {
SLOT(_pthread_mutex_init_calloc_cb, _pthread_mutex_init_calloc_cb_stub),
SLOT(spinlock, __libc_spinlock_stub),
SLOT(spinunlock, __libc_spinunlock_stub),
+ SLOT(kevent, __sys_kevent),
};
#undef SLOT
diff --git a/lib/libc/sys/kevent.c b/lib/libc/sys/kevent.c
new file mode 100644
index 000000000000..5f84ef8b10a6
--- /dev/null
+++ b/lib/libc/sys/kevent.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2015 The FreeBSD Foundation.
+ * All rights reserved.
+ *
+ * Portions of this software were developed by Konstantin Belousov
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice(s), this list of conditions and the following disclaimer as
+ * the first lines of this file unmodified other than the possible
+ * addition of one or more copyright notices.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice(s), this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/event.h>
+#include <sys/time.h>
+#include "libc_private.h"
+
+__weak_reference(__sys_kevent, __kevent);
+
+#pragma weak kevent
+int
+kevent(int kq, const struct kevent *changelist, int nchanges,
+ struct kevent *eventlist, int nevents, const struct timespec *timeout)
+{
+
+ return (((int (*)(int, const struct kevent *, int,
+ struct kevent *, int, const struct timespec *))
+ __libc_interposing[INTERPOS_kevent])(kq, changelist, nchanges,
+ eventlist, nevents, timeout));
+}
diff --git a/lib/libc/sys/kqueue.2 b/lib/libc/sys/kqueue.2
index 93223f1fea6e..c5e8cafd5579 100644
--- a/lib/libc/sys/kqueue.2
+++ b/lib/libc/sys/kqueue.2
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd July 18, 2014
+.Dd March 29, 2015
.Dt KQUEUE 2
.Os
.Sh NAME
@@ -41,7 +41,7 @@
.Fn kqueue "void"
.Ft int
.Fn kevent "int kq" "const struct kevent *changelist" "int nchanges" "struct kevent *eventlist" "int nevents" "const struct timespec *timeout"
-.Fn EV_SET "&kev" ident filter flags fflags data udata
+.Fn EV_SET "kev" ident filter flags fflags data udata
.Sh DESCRIPTION
The
.Fn kqueue
@@ -550,6 +550,16 @@ On return,
.Va fflags
contains the users defined flags in the lower 24 bits.
.El
+.Sh CANCELLATION BEHAVIOUR
+If
+.Fa nevents
+is non-zero, i.e. the function is potentially blocking, the call
+is a cancellation point.
+Otherwise, i.e. if
+.Fa nevents
+is zero, the call is not cancellable.
+Cancellation can only occur before any changes are made to the kqueue,
+or when the call was blocked and no changes to the queue were requested.
.Sh RETURN VALUES
The
.Fn kqueue
@@ -620,6 +630,8 @@ The specified descriptor is invalid.
.It Bq Er EINTR
A signal was delivered before the timeout expired and before any
events were placed on the kqueue for return.
+.It Bq Er EINTR
+A cancellation request was delivered to the thread, but not yet handled.
.It Bq Er EINVAL
The specified time limit or filter is invalid.
.It Bq Er ENOENT
@@ -634,6 +646,14 @@ sysctl.
.It Bq Er ESRCH
The specified process to attach to does not exist.
.El
+.Pp
+When
+.Fn kevent
+call fails with
+.Er EINTR
+error, all changes in the
+.Fa changelist
+have been applied.
.Sh SEE ALSO
.Xr aio_error 2 ,
.Xr aio_read 2 ,
@@ -643,6 +663,7 @@ The specified process to attach to does not exist.
.Xr select 2 ,
.Xr sigaction 2 ,
.Xr write 2 ,
+.Xr pthread_setcancelstate 3 ,
.Xr signal 3
.Sh HISTORY
The
diff --git a/lib/libthr/thread/thr_syscalls.c b/lib/libthr/thread/thr_syscalls.c
index 10fbad4a2ad0..e71bf4ae91c8 100644
--- a/lib/libthr/thread/thr_syscalls.c
+++ b/lib/libthr/thread/thr_syscalls.c
@@ -341,6 +341,29 @@ __thr_pselect(int count, fd_set *rfds, fd_set *wfds, fd_set *efds,
return (ret);
}
+static int
+__thr_kevent(int kq, const struct kevent *changelist, int nchanges,
+ struct kevent *eventlist, int nevents, const struct timespec *timeout)
+{
+ struct pthread *curthread;
+ int ret;
+
+ if (nevents == 0) {
+ /*
+ * No blocking, do not make the call cancellable.
+ */
+ return (__sys_kevent(kq, changelist, nchanges, eventlist,
+ nevents, timeout));
+ }
+ curthread = _get_curthread();
+ _thr_cancel_enter(curthread);
+ ret = __sys_kevent(kq, changelist, nchanges, eventlist, nevents,
+ timeout);
+ _thr_cancel_leave(curthread, ret == -1 && nchanges == 0);
+
+ return (ret);
+}
+
/*
* Cancellation behavior:
* Thread may be canceled at start, but if the system call got some data,
@@ -599,6 +622,7 @@ __thr_interpose_libc(void)
SLOT(writev);
SLOT(spinlock);
SLOT(spinunlock);
+ SLOT(kevent);
#undef SLOT
*(__libc_interposing_slot(
INTERPOS__pthread_mutex_init_calloc_cb)) =
diff --git a/share/man/man3/pthread_testcancel.3 b/share/man/man3/pthread_testcancel.3
index ef6a1c11bd98..a6b27f67c9ca 100644
--- a/share/man/man3/pthread_testcancel.3
+++ b/share/man/man3/pthread_testcancel.3
@@ -1,5 +1,5 @@
.\" $FreeBSD$
-.Dd June 11, 2013
+.Dd March 29, 2015
.Dt PTHREAD_TESTCANCEL 3
.Os
.Sh NAME
@@ -107,6 +107,7 @@ functions:
.Fn close ,
.Fn creat ,
.Fn fsync ,
+.Fn kevent ,
.Fn mq_receive ,
.Fn mq_send ,
.Fn mq_timedreceive ,
@@ -147,12 +148,20 @@ functions:
.Fn waitpid ,
.Fn write ,
.Fn writev .
+.Pp
The
.Fn fcntl
function is a cancellation point if
.Fa cmd
is
.Dv F_SETLKW .
+.Pp
+The
+.Fn kevent
+function is a cancellation point if it is potentially blocking,
+i.e. when the
+.Fa nevents
+argument is non-zero.
.Sh RETURN VALUES
If successful, the
.Fn pthread_setcancelstate