]> git.proxmox.com Git - mirror_qemu.git/blob - include/qemu/seqlock.h
seqlock: remove optional mutex
[mirror_qemu.git] / include / qemu / seqlock.h
1 /*
2 * Seqlock implementation for QEMU
3 *
4 * Copyright Red Hat, Inc. 2013
5 *
6 * Author:
7 * Paolo Bonzini <pbonzini@redhat.com>
8 *
9 * This work is licensed under the terms of the GNU GPL, version 2 or later.
10 * See the COPYING file in the top-level directory.
11 *
12 */
13 #ifndef QEMU_SEQLOCK_H
14 #define QEMU_SEQLOCK_H 1
15
16 #include <qemu/atomic.h>
17 #include <qemu/thread.h>
18
19 typedef struct QemuSeqLock QemuSeqLock;
20
21 struct QemuSeqLock {
22 unsigned sequence;
23 };
24
25 static inline void seqlock_init(QemuSeqLock *sl)
26 {
27 sl->sequence = 0;
28 }
29
30 /* Lock out other writers and update the count. */
31 static inline void seqlock_write_lock(QemuSeqLock *sl)
32 {
33 ++sl->sequence;
34
35 /* Write sequence before updating other fields. */
36 smp_wmb();
37 }
38
39 static inline void seqlock_write_unlock(QemuSeqLock *sl)
40 {
41 /* Write other fields before finalizing sequence. */
42 smp_wmb();
43
44 ++sl->sequence;
45 }
46
47 static inline unsigned seqlock_read_begin(QemuSeqLock *sl)
48 {
49 /* Always fail if a write is in progress. */
50 unsigned ret = atomic_read(&sl->sequence);
51
52 /* Read sequence before reading other fields. */
53 smp_rmb();
54 return ret & ~1;
55 }
56
57 static inline int seqlock_read_retry(const QemuSeqLock *sl, unsigned start)
58 {
59 /* Read other fields before reading final sequence. */
60 smp_rmb();
61 return unlikely(atomic_read(&sl->sequence) != start);
62 }
63
64 #endif