From 33346ed65c9b6c90f92085741cc9887c299b3a22 Mon Sep 17 00:00:00 2001 From: Matt Macy Date: Sun, 13 May 2018 23:16:04 +0000 Subject: [PATCH] Add epoch(9) man page Reviewed by: gallatin@ Approved by: sbruno@ --- share/man/man9/Makefile | 1 + share/man/man9/epoch.9 | 161 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 162 insertions(+) create mode 100644 share/man/man9/epoch.9 diff --git a/share/man/man9/Makefile b/share/man/man9/Makefile index 746a8a432c4d..bc563f1d0bb0 100644 --- a/share/man/man9/Makefile +++ b/share/man/man9/Makefile @@ -123,6 +123,7 @@ MAN= accept_filter.9 \ drbr.9 \ driver.9 \ DRIVER_MODULE.9 \ + epoch.9 \ EVENTHANDLER.9 \ eventtimers.9 \ extattr.9 \ diff --git a/share/man/man9/epoch.9 b/share/man/man9/epoch.9 new file mode 100644 index 000000000000..a1307bbde741 --- /dev/null +++ b/share/man/man9/epoch.9 @@ -0,0 +1,161 @@ +.\" +.\" Copyright (C) 2018 Matthew Macy . +.\" +.\" 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. +.\" +.\" $FreeBSD$ +.\" +.Dd May 13, 2018 +.Dt EPOCH 9 +.Os +.Sh NAME +.Nm epoch , +.Nm epoch_context , +.Nm epoch_alloc , +.Nm epoch_free , +.Nm epoch_enter , +.Nm epoch_exit , +.Nm epoch_wait , +.Nm epoch_call , +.Nm in_epoch , +.Nd kernel epoch based reclaimation +.Sh SYNOPSIS +.In sys/param.h +.In sys/proc.h +.In sys/epoch.h +.Ft epoch_t +.Fn epoch_alloc "void" +.Ft void +.Fn epoch_enter "epoch_t epoch" +.Ft void +.Fn epoch_exit "epoch_t epoch" +.Ft void +.Fn epoch_wait "epoch_t epoch" +.Ft void +.Fn epoch_call "epoch_t epoch" "epoch_context_t ctx" "void (*callback) (epoch_context_t)" +.Ft int +.Fn in_epoch "void" +.Sh DESCRIPTION +Epochs are used to guarantee liveness and immutability of data by +deferring reclamation and mutation until a grace period has elapsed. +Epochs do not have any lock ordering issues. Entering and leaving +an epoch section will never block. +.Pp +Epochs are allocated with +.Fn epoch_alloc +and freed with +.Fn epoch_free . +Threads indicate the start of an epoch critical section by calling +.Fn epoch_enter . +The end of a critical section is indicated by calling +.Fn epoch_exit . +A thread can wait until a grace period has elapsed +since any threads have entered +the epoch by calling +.Fn epoch_wait . +If the thread can't sleep or is otherwise in a performance sensitive +path it can ensure that a grace period has elapsed by calling +.Fn epoch_call +with a callback with any work that needs to wait for an epoch to elapse. +Only non-sleepable locks can be acquired during a section protected by +.Fn epoch_enter +and +.Fn epoch_exit . +INVARIANTS can assert that a thread is in an epoch by using +.Fn in_epoch . +.Pp +The epoch API currently does not support sleeping in epoch sections. +A caller cannot do epoch_enter recursively on different epochs. A +caller should never call +.Fn epoch_wait +in the middle of an epoch section as this will lead to a deadlock. +.Pp +Note that epochs are not a straight replacement for read locks. Callers +must use safe list and tailq traversal routines in an epoch (see ck_queue). +When modifying a list referenced from an epoch section safe removal +routines must be used and the caller can no longer modify a list entry +in place. An item to be modified must be handled with copy on write +and frees must be deferred until after a grace period has elapsed. + +.Sh RETURN VALUES +.Fn in_epoch +will return 1 if curthread is in an epoch, 0 otherwise. +.Sh EXAMPLES +Async free example: + +Thread 1: +.Bd -literal +{ + epoch_enter(net_epoch); + CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { + sa = ifa->ifa_addr; + if (sa->sa_family != AF_INET) + continue; + sin = (struct sockaddr_in *)sa; + if (prison_check_ip4(cred, &sin->sin_addr) == 0) { + ia = (struct in_ifaddr *)ifa; + break; + } + } + epoch_exit(net_epoch); +} +.Ed +Thread 2: +.Bd -literal +void +ifa_free(struct ifaddr *ifa) +{ + + if (refcount_release(&ifa->ifa_refcnt)) + epoch_call(net_epoch, &ifa->ifa_epoch_ctx, ifa_destroy); +} + +{ + + IF_ADDR_WLOCK(ifp); + CK_STAILQ_REMOVE(&ifp->if_addrhead, ifa, ifaddr, ifa_link); + /* mark as unlinked */ + ifa->ifa_addr->sa_family = AF_UNSPEC; + IF_ADDR_WUNLOCK(ifp); + ifa_free(ifa); +} +.Ed +.Pp +Thread 1 traverses the ifaddr list in an epoch. Thread 2 unlinks +with the corresponding epoch safe macro, marks as logically free, +and then defers deletion. More general mutation or a synchronous +free would have to follow a a call to +.Fn epoch_wait . +.Sh ERRORS +None. +.El +.Sh SEE ALSO +.Xr locking 9 , +.Xr mtx_pool 9 , +.Xr mutex 9 , +.Xr rwlock 9 , +.Xr sema 9 , +.Xr sleep 9 , +.Xr sx 9 , +.Xr timeout 9