Date: Wed, 28 Mar 2018 04:38:45 +0000 (UTC) From: Mateusz Guzik <mjg@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r331660 - head/sys/sys Message-ID: <201803280438.w2S4cjRE000655@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: mjg Date: Wed Mar 28 04:38:45 2018 New Revision: 331660 URL: https://svnweb.freebsd.org/changeset/base/331660 Log: seq: provide a comment explaining what seq is for and note 2 caveats Modified: head/sys/sys/seq.h Modified: head/sys/sys/seq.h ============================================================================== --- head/sys/sys/seq.h Wed Mar 28 03:15:42 2018 (r331659) +++ head/sys/sys/seq.h Wed Mar 28 04:38:45 2018 (r331660) @@ -41,26 +41,52 @@ typedef uint32_t seq_t; #ifdef _KERNEL /* - * Typical usage: + * seq allows readers and writers to work with a consistent snapshot. Modifying + * operations must be enclosed within a transaction delineated by + * seq_write_beg/seq_write_end. The trick works by having the writer increment + * the sequence number twice, at the beginning and end of the transaction. + * The reader detects that the sequence number has not changed between its start + * and end, and that the sequence 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); - * seq_write_begin(&obj->seq); - * ..... - * seq_write_end(&obj->seq); - * unlock_exclusive(&obj->unlock); + * lock_exclusive(&obj->lock); + * seq_write_begin(&obj->seq); + * obj->var1 = ...; + * obj->var2 = ...; + * seq_write_end(&obj->seq); + * unlock_exclusive(&obj->lock); * * readers: - * obj_t lobj; - * seq_t seq; + * int var1, var2; + * seq_t seq; * - * for (;;) { - * seq = seq_read(&gobj->seq); - * lobj = gobj; - * if (seq_consistent(&gobj->seq, seq)) - * break; - * } - * foo(lobj); + * for (;;) { + * seq = seq_read(&obj->seq); + * var1 = obj->var1; + * var2 = obj->var2; + * if (seq_consistent(&obj->seq, seq)) + * 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 */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201803280438.w2S4cjRE000655>