]>
Commit | Line | Data |
---|---|---|
ea753d81 PB |
1 | /* |
2 | * Seqlock implementation for QEMU | |
3 | * | |
4 | * Copyright Red Hat, Inc. 2013 | |
5 | * | |
6 | * Author: | |
7 | * Paolo Bonzini <[email protected]> | |
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 | */ | |
175de524 | 13 | |
ea753d81 | 14 | #ifndef QEMU_SEQLOCK_H |
175de524 | 15 | #define QEMU_SEQLOCK_H |
ea753d81 | 16 | |
a9c94277 MA |
17 | #include "qemu/atomic.h" |
18 | #include "qemu/thread.h" | |
ea753d81 PB |
19 | |
20 | typedef struct QemuSeqLock QemuSeqLock; | |
21 | ||
22 | struct QemuSeqLock { | |
ea753d81 PB |
23 | unsigned sequence; |
24 | }; | |
25 | ||
ccdb3c1f | 26 | static inline void seqlock_init(QemuSeqLock *sl) |
ea753d81 | 27 | { |
ea753d81 PB |
28 | sl->sequence = 0; |
29 | } | |
30 | ||
31 | /* Lock out other writers and update the count. */ | |
03719e44 | 32 | static inline void seqlock_write_begin(QemuSeqLock *sl) |
ea753d81 | 33 | { |
f96a8cc3 | 34 | atomic_set(&sl->sequence, sl->sequence + 1); |
ea753d81 PB |
35 | |
36 | /* Write sequence before updating other fields. */ | |
37 | smp_wmb(); | |
38 | } | |
39 | ||
03719e44 | 40 | static inline void seqlock_write_end(QemuSeqLock *sl) |
ea753d81 PB |
41 | { |
42 | /* Write other fields before finalizing sequence. */ | |
43 | smp_wmb(); | |
44 | ||
f96a8cc3 | 45 | atomic_set(&sl->sequence, sl->sequence + 1); |
ea753d81 PB |
46 | } |
47 | ||
48 | static inline unsigned seqlock_read_begin(QemuSeqLock *sl) | |
49 | { | |
50 | /* Always fail if a write is in progress. */ | |
d12f7309 | 51 | unsigned ret = atomic_read(&sl->sequence); |
ea753d81 PB |
52 | |
53 | /* Read sequence before reading other fields. */ | |
54 | smp_rmb(); | |
d12f7309 | 55 | return ret & ~1; |
ea753d81 PB |
56 | } |
57 | ||
123fdbac | 58 | static inline int seqlock_read_retry(const QemuSeqLock *sl, unsigned start) |
ea753d81 PB |
59 | { |
60 | /* Read other fields before reading final sequence. */ | |
61 | smp_rmb(); | |
d12f7309 | 62 | return unlikely(atomic_read(&sl->sequence) != start); |
ea753d81 PB |
63 | } |
64 | ||
65 | #endif |