seq: provide a comment explaining what seq is for and note 2 caveats
This commit is contained in:
parent
2110fd5f63
commit
3281e3d75c
@ -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);
|
||||
* .....
|
||||
* obj->var1 = ...;
|
||||
* obj->var2 = ...;
|
||||
* seq_write_end(&obj->seq);
|
||||
* unlock_exclusive(&obj->unlock);
|
||||
* unlock_exclusive(&obj->lock);
|
||||
*
|
||||
* readers:
|
||||
* obj_t lobj;
|
||||
* int var1, var2;
|
||||
* seq_t seq;
|
||||
*
|
||||
* for (;;) {
|
||||
* seq = seq_read(&gobj->seq);
|
||||
* lobj = gobj;
|
||||
* if (seq_consistent(&gobj->seq, seq))
|
||||
* seq = seq_read(&obj->seq);
|
||||
* var1 = obj->var1;
|
||||
* var2 = obj->var2;
|
||||
* if (seq_consistent(&obj->seq, seq))
|
||||
* break;
|
||||
* }
|
||||
* foo(lobj);
|
||||
* .....
|
||||
*
|
||||
* 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 */
|
||||
|
Loading…
x
Reference in New Issue
Block a user