]> git.proxmox.com Git - mirror_qemu.git/blob - include/qemu/seqlock.h
parallels: wrong call to bdrv_truncate
[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
14 #ifndef QEMU_SEQLOCK_H
15 #define QEMU_SEQLOCK_H
16
17 #include "qemu/atomic.h"
18 #include "qemu/thread.h"
19
20 typedef struct QemuSeqLock QemuSeqLock;
21
22 struct QemuSeqLock {
23 unsigned sequence;
24 };
25
26 static inline void seqlock_init(QemuSeqLock *sl)
27 {
28 sl->sequence = 0;
29 }
30
31 /* Lock out other writers and update the count. */
32 static inline void seqlock_write_begin(QemuSeqLock *sl)
33 {
34 atomic_set(&sl->sequence, sl->sequence + 1);
35
36 /* Write sequence before updating other fields. */
37 smp_wmb();
38 }
39
40 static inline void seqlock_write_end(QemuSeqLock *sl)
41 {
42 /* Write other fields before finalizing sequence. */
43 smp_wmb();
44
45 atomic_set(&sl->sequence, sl->sequence + 1);
46 }
47
48 static inline unsigned seqlock_read_begin(QemuSeqLock *sl)
49 {
50 /* Always fail if a write is in progress. */
51 unsigned ret = atomic_read(&sl->sequence);
52
53 /* Read sequence before reading other fields. */
54 smp_rmb();
55 return ret & ~1;
56 }
57
58 static inline int seqlock_read_retry(const QemuSeqLock *sl, unsigned start)
59 {
60 /* Read other fields before reading final sequence. */
61 smp_rmb();
62 return unlikely(atomic_read(&sl->sequence) != start);
63 }
64
65 #endif