From owner-svn-src-all@freebsd.org Wed Feb 27 22:56:57 2019 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id DEF8E15081CC; Wed, 27 Feb 2019 22:56:56 +0000 (UTC) (envelope-from mjg@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 8389294EA7; Wed, 27 Feb 2019 22:56:56 +0000 (UTC) (envelope-from mjg@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 573EC23868; Wed, 27 Feb 2019 22:56:56 +0000 (UTC) (envelope-from mjg@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id x1RMuuF6085220; Wed, 27 Feb 2019 22:56:56 GMT (envelope-from mjg@FreeBSD.org) Received: (from mjg@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id x1RMutdK085216; Wed, 27 Feb 2019 22:56:55 GMT (envelope-from mjg@FreeBSD.org) Message-Id: <201902272256.x1RMutdK085216@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: mjg set sender to mjg@FreeBSD.org using -f From: Mateusz Guzik Date: Wed, 27 Feb 2019 22:56:55 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r344648 - in head: . sys/kern sys/sys X-SVN-Group: head X-SVN-Commit-Author: mjg X-SVN-Commit-Paths: in head: . sys/kern sys/sys X-SVN-Commit-Revision: 344648 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Rspamd-Queue-Id: 8389294EA7 X-Spamd-Bar: -- Authentication-Results: mx1.freebsd.org X-Spamd-Result: default: False [-2.96 / 15.00]; local_wl_from(0.00)[FreeBSD.org]; NEURAL_HAM_SHORT(-0.96)[-0.962,0]; ASN(0.00)[asn:11403, ipnet:2610:1c1:1::/48, country:US]; NEURAL_HAM_MEDIUM(-1.00)[-0.999,0]; NEURAL_HAM_LONG(-1.00)[-0.999,0] X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 27 Feb 2019 22:56:57 -0000 Author: mjg Date: Wed Feb 27 22:56:55 2019 New Revision: 344648 URL: https://svnweb.freebsd.org/changeset/base/344648 Log: Rename seq to seqc to avoid namespace clashes with Linux Linux generates the content of procfs files using a mechanism prefixed with seq_*. This in particular came up with recent gcov import. Sponsored by: The FreeBSD Foundation Added: head/sys/sys/seqc.h (contents, props changed) Deleted: head/sys/sys/seq.h Modified: head/ObsoleteFiles.inc head/sys/kern/kern_descrip.c head/sys/sys/filedesc.h Modified: head/ObsoleteFiles.inc ============================================================================== --- head/ObsoleteFiles.inc Wed Feb 27 22:42:29 2019 (r344647) +++ head/ObsoleteFiles.inc Wed Feb 27 22:56:55 2019 (r344648) @@ -38,6 +38,8 @@ # xargs -n1 | sort | uniq -d; # done +# 20190227: rename seq.h to seqc.h +OLD_FILES+=usr/include/sys/seq.h # 20190222: libifconfig made INTERNALLIB OLD_FILES+=usr/lib/libprivateifconfig.a OLD_FILES+=usr/lib/libprivateifconfig_p.a Modified: head/sys/kern/kern_descrip.c ============================================================================== --- head/sys/kern/kern_descrip.c Wed Feb 27 22:42:29 2019 (r344647) +++ head/sys/kern/kern_descrip.c Wed Feb 27 22:56:55 2019 (r344648) @@ -304,11 +304,11 @@ fdfree(struct filedesc *fdp, int fd) fde = &fdp->fd_ofiles[fd]; #ifdef CAPABILITIES - seq_write_begin(&fde->fde_seq); + seqc_write_begin(&fde->fde_seqc); #endif fde->fde_file = NULL; #ifdef CAPABILITIES - seq_write_end(&fde->fde_seq); + seqc_write_end(&fde->fde_seqc); #endif fdefree_last(fde); fdunused(fdp, fd); @@ -908,7 +908,7 @@ kern_dup(struct thread *td, u_int mode, int flags, int * Duplicate the source descriptor. */ #ifdef CAPABILITIES - seq_write_begin(&newfde->fde_seq); + seqc_write_begin(&newfde->fde_seqc); #endif memcpy(newfde, oldfde, fde_change_size); filecaps_copy_finish(&oldfde->fde_caps, &newfde->fde_caps, @@ -918,7 +918,7 @@ kern_dup(struct thread *td, u_int mode, int flags, int else newfde->fde_flags = oldfde->fde_flags & ~UF_EXCLOSE; #ifdef CAPABILITIES - seq_write_end(&newfde->fde_seq); + seqc_write_end(&newfde->fde_seqc); #endif td->td_retval[0] = new; @@ -1876,7 +1876,7 @@ _finstall(struct filedesc *fdp, struct file *fp, int f fde = &fdp->fd_ofiles[fd]; #ifdef CAPABILITIES - seq_write_begin(&fde->fde_seq); + seqc_write_begin(&fde->fde_seqc); #endif fde->fde_file = fp; fde->fde_flags = (flags & O_CLOEXEC) != 0 ? UF_EXCLOSE : 0; @@ -1885,7 +1885,7 @@ _finstall(struct filedesc *fdp, struct file *fp, int f else filecaps_fill(&fde->fde_caps); #ifdef CAPABILITIES - seq_write_end(&fde->fde_seq); + seqc_write_end(&fde->fde_seqc); #endif } @@ -2567,7 +2567,7 @@ fget_cap(struct thread *td, int fd, cap_rights_t *need filecaps_fill(havecapsp); #else struct file *fp; - seq_t seq; + seqc_t seq; for (;;) { error = fget_unlocked(fdp, fd, needrightsp, &fp, &seq); @@ -2602,7 +2602,7 @@ get_locked: int fget_unlocked(struct filedesc *fdp, int fd, cap_rights_t *needrightsp, - struct file **fpp, seq_t *seqp) + struct file **fpp, seqc_t *seqp) { #ifdef CAPABILITIES const struct filedescent *fde; @@ -2611,7 +2611,7 @@ fget_unlocked(struct filedesc *fdp, int fd, cap_rights struct file *fp; u_int count; #ifdef CAPABILITIES - seq_t seq; + seqc_t seq; cap_rights_t haverights; int error; #endif @@ -2629,11 +2629,11 @@ fget_unlocked(struct filedesc *fdp, int fd, cap_rights */ for (;;) { #ifdef CAPABILITIES - seq = seq_load(fd_seq(fdt, fd)); + seq = seqc_read(fd_seqc(fdt, fd)); fde = &fdt->fdt_ofiles[fd]; haverights = *cap_rights_fde_inline(fde); fp = fde->fde_file; - if (!seq_consistent(fd_seq(fdt, fd), seq)) + if (!seqc_consistent(fd_seqc(fdt, fd), seq)) continue; #else fp = fdt->fdt_ofiles[fd].fde_file; @@ -2664,7 +2664,7 @@ fget_unlocked(struct filedesc *fdp, int fd, cap_rights goto retry; fdt = fdp->fd_files; #ifdef CAPABILITIES - if (seq_consistent_nomb(fd_seq(fdt, fd), seq)) + if (seqc_consistent_nomb(fd_seqc(fdt, fd), seq)) #else if (fp == fdt->fdt_ofiles[fd].fde_file) #endif @@ -2695,7 +2695,7 @@ fget_unlocked(struct filedesc *fdp, int fd, cap_rights */ static __inline int _fget(struct thread *td, int fd, struct file **fpp, int flags, - cap_rights_t *needrightsp, seq_t *seqp) + cap_rights_t *needrightsp, seqc_t *seqp) { struct filedesc *fdp; struct file *fp; @@ -2759,7 +2759,7 @@ fget_mmap(struct thread *td, int fd, cap_rights_t *rig *maxprotp = VM_PROT_ALL; #else struct filedesc *fdp = td->td_proc->p_fd; - seq_t seq; + seqc_t seq; MPASS(cap_rights_is_set(rightsp, CAP_MMAP)); for (;;) { @@ -2802,7 +2802,7 @@ fget_fcntl(struct thread *td, int fd, cap_rights_t *ri return (fget_unlocked(fdp, fd, rightsp, fpp, NULL)); #else int error; - seq_t seq; + seqc_t seq; MPASS(cap_rights_is_set(rightsp, CAP_FCNTL)); for (;;) { @@ -3046,13 +3046,13 @@ dupfdopen(struct thread *td, struct filedesc *fdp, int oldfde = &fdp->fd_ofiles[dfd]; ioctls = filecaps_copy_prep(&oldfde->fde_caps); #ifdef CAPABILITIES - seq_write_begin(&newfde->fde_seq); + seqc_write_begin(&newfde->fde_seqc); #endif memcpy(newfde, oldfde, fde_change_size); filecaps_copy_finish(&oldfde->fde_caps, &newfde->fde_caps, ioctls); #ifdef CAPABILITIES - seq_write_end(&newfde->fde_seq); + seqc_write_end(&newfde->fde_seqc); #endif break; case ENXIO: @@ -3062,13 +3062,13 @@ dupfdopen(struct thread *td, struct filedesc *fdp, int newfde = &fdp->fd_ofiles[indx]; oldfde = &fdp->fd_ofiles[dfd]; #ifdef CAPABILITIES - seq_write_begin(&newfde->fde_seq); + seqc_write_begin(&newfde->fde_seqc); #endif memcpy(newfde, oldfde, fde_change_size); oldfde->fde_file = NULL; fdunused(fdp, dfd); #ifdef CAPABILITIES - seq_write_end(&newfde->fde_seq); + seqc_write_end(&newfde->fde_seqc); #endif break; } Modified: head/sys/sys/filedesc.h ============================================================================== --- head/sys/sys/filedesc.h Wed Feb 27 22:42:29 2019 (r344647) +++ head/sys/sys/filedesc.h Wed Feb 27 22:56:55 2019 (r344648) @@ -40,7 +40,7 @@ #include #include #include -#include +#include #include #include @@ -56,19 +56,19 @@ struct filedescent { struct file *fde_file; /* file structure for open file */ struct filecaps fde_caps; /* per-descriptor rights */ uint8_t fde_flags; /* per-process open file flags */ - seq_t fde_seq; /* keep file and caps in sync */ + seqc_t fde_seqc; /* keep file and caps in sync */ }; #define fde_rights fde_caps.fc_rights #define fde_fcntls fde_caps.fc_fcntls #define fde_ioctls fde_caps.fc_ioctls #define fde_nioctls fde_caps.fc_nioctls -#define fde_change_size (offsetof(struct filedescent, fde_seq)) +#define fde_change_size (offsetof(struct filedescent, fde_seqc)) struct fdescenttbl { int fdt_nfiles; /* number of open files allocated */ struct filedescent fdt_ofiles[0]; /* open files */ }; -#define fd_seq(fdt, fd) (&(fdt)->fdt_ofiles[(fd)].fde_seq) +#define fd_seqc(fdt, fd) (&(fdt)->fdt_ofiles[(fd)].fde_seqc) /* * This structure is used for the management of descriptors. It may be @@ -205,7 +205,7 @@ int fget_cap(struct thread *td, int fd, cap_rights_t * /* Return a referenced file from an unlocked descriptor. */ int fget_unlocked(struct filedesc *fdp, int fd, cap_rights_t *needrightsp, - struct file **fpp, seq_t *seqp); + struct file **fpp, seqc_t *seqp); /* Requires a FILEDESC_{S,X}LOCK held and returns without a ref. */ static __inline struct file * @@ -239,10 +239,10 @@ fdeget_locked(struct filedesc *fdp, int fd) #ifdef CAPABILITIES static __inline bool -fd_modified(struct filedesc *fdp, int fd, seq_t seq) +fd_modified(struct filedesc *fdp, int fd, seqc_t seqc) { - return (!seq_consistent(fd_seq(fdp->fd_files, fd), seq)); + return (!seqc_consistent(fd_seqc(fdp->fd_files, fd), seqc)); } #endif Added: head/sys/sys/seqc.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/sys/seqc.h Wed Feb 27 22:56:55 2019 (r344648) @@ -0,0 +1,156 @@ +/*- + * Copyright (c) 2014 Mateusz Guzik + * + * 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, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, 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 AUTHOR AND CONTRIBUTORS ``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 AUTHOR OR CONTRIBUTORS 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$ + */ + +#ifndef _SYS_SEQC_H_ +#define _SYS_SEQC_H_ + +#ifdef _KERNEL +#include +#endif +#include + +/* + * seqc_t may be included in structs visible to userspace + */ +typedef uint32_t seqc_t; + +#ifdef _KERNEL + +/* + * seqc allows readers and writers to work with a consistent snapshot. Modifying + * operations must be enclosed within a transaction delineated by + * seqc_write_beg/seqc_write_end. The trick works by having the writer increment + * the seqcuence number twice, at the beginning and end of the transaction. + * The reader detects that the seqcuence number has not changed between its start + * and end, and that the seqcuence number is even, to validate consistency. + * + * Some fencing (both hard fencing and compiler barriers) may be needed, + * depending on the cpu. Modern AMD cpus provide strong enough guarantees to not + * require any fencing by the reader or writer. + * + * Example usage: + * + * writers: + * lock_exclusive(&obj->lock); + * seqc_write_begin(&obj->seqc); + * obj->var1 = ...; + * obj->var2 = ...; + * seqc_write_end(&obj->seqc); + * unlock_exclusive(&obj->lock); + * + * readers: + * int var1, var2; + * seqc_t seqc; + * + * for (;;) { + * seqc = seqc_read(&obj->seqc); + * var1 = obj->var1; + * var2 = obj->var2; + * if (seqc_consistent(&obj->seqc, seqc)) + * break; + * } + * ..... + * + * Writers may not block or sleep in any way. + * + * There are 2 minor caveats in this implementation: + * + * 1. There is no guarantee of progress. That is, a large number of writers can + * interfere with the execution of the readers and cause the code to live-lock + * in a loop trying to acquire a consistent snapshot. + * + * 2. If the reader loops long enough, the counter may overflow and eventually + * wrap back to its initial value, fooling the reader into accepting the + * snapshot. Given that this needs 4 billion transactional writes across a + * single contended reader, it is unlikely to ever happen. + */ + +/* A hack to get MPASS macro */ +#include + +#include + +static __inline bool +seqc_in_modify(seqc_t seqcp) +{ + + return (seqcp & 1); +} + +static __inline void +seqc_write_begin(seqc_t *seqcp) +{ + + critical_enter(); + MPASS(!seqc_in_modify(*seqcp)); + *seqcp += 1; + atomic_thread_fence_rel(); +} + +static __inline void +seqc_write_end(seqc_t *seqcp) +{ + + atomic_store_rel_int(seqcp, *seqcp + 1); + MPASS(!seqc_in_modify(*seqcp)); + critical_exit(); +} + +static __inline seqc_t +seqc_read(const seqc_t *seqcp) +{ + seqc_t ret; + + for (;;) { + ret = atomic_load_acq_int(__DECONST(seqc_t *, seqcp)); + if (seqc_in_modify(ret)) { + cpu_spinwait(); + continue; + } + break; + } + + return (ret); +} + +static __inline seqc_t +seqc_consistent_nomb(const seqc_t *seqcp, seqc_t oldseqc) +{ + + return (*seqcp == oldseqc); +} + +static __inline seqc_t +seqc_consistent(const seqc_t *seqcp, seqc_t oldseqc) +{ + + atomic_thread_fence_acq(); + return (seqc_consistent_nomb(seqcp, oldseqc)); +} + +#endif /* _KERNEL */ +#endif /* _SYS_SEQC_H_ */