Add qemu 2.4.0
[kvmfornfv.git] / qemu / 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     QemuMutex *mutex;
23     unsigned sequence;
24 };
25
26 static inline void seqlock_init(QemuSeqLock *sl, QemuMutex *mutex)
27 {
28     sl->mutex = mutex;
29     sl->sequence = 0;
30 }
31
32 /* Lock out other writers and update the count.  */
33 static inline void seqlock_write_lock(QemuSeqLock *sl)
34 {
35     if (sl->mutex) {
36         qemu_mutex_lock(sl->mutex);
37     }
38     ++sl->sequence;
39
40     /* Write sequence before updating other fields.  */
41     smp_wmb();
42 }
43
44 static inline void seqlock_write_unlock(QemuSeqLock *sl)
45 {
46     /* Write other fields before finalizing sequence.  */
47     smp_wmb();
48
49     ++sl->sequence;
50     if (sl->mutex) {
51         qemu_mutex_unlock(sl->mutex);
52     }
53 }
54
55 static inline unsigned seqlock_read_begin(QemuSeqLock *sl)
56 {
57     /* Always fail if a write is in progress.  */
58     unsigned ret = sl->sequence & ~1;
59
60     /* Read sequence before reading other fields.  */
61     smp_rmb();
62     return ret;
63 }
64
65 static int seqlock_read_retry(const QemuSeqLock *sl, unsigned start)
66 {
67     /* Read other fields before reading final sequence.  */
68     smp_rmb();
69     return unlikely(sl->sequence != start);
70 }
71
72 #endif