2 * Seqlock implementation for QEMU
4 * Copyright Red Hat, Inc. 2013
7 * Paolo Bonzini <pbonzini@redhat.com>
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.
14 #ifndef QEMU_SEQLOCK_H
15 #define QEMU_SEQLOCK_H
17 #include "qemu/atomic.h"
18 #include "qemu/thread.h"
19 #include "qemu/lockable.h"
21 typedef struct QemuSeqLock QemuSeqLock
;
27 static inline void seqlock_init(QemuSeqLock
*sl
)
32 /* Lock out other writers and update the count. */
33 static inline void seqlock_write_begin(QemuSeqLock
*sl
)
35 qatomic_set(&sl
->sequence
, sl
->sequence
+ 1);
37 /* Write sequence before updating other fields. */
41 static inline void seqlock_write_end(QemuSeqLock
*sl
)
43 /* Write other fields before finalizing sequence. */
46 qatomic_set(&sl
->sequence
, sl
->sequence
+ 1);
49 /* Lock out other writers and update the count. */
50 static inline void seqlock_write_lock_impl(QemuSeqLock
*sl
, QemuLockable
*lock
)
52 qemu_lockable_lock(lock
);
53 seqlock_write_begin(sl
);
55 #define seqlock_write_lock(sl, lock) \
56 seqlock_write_lock_impl(sl, QEMU_MAKE_LOCKABLE(lock))
58 /* Update the count and release the lock. */
59 static inline void seqlock_write_unlock_impl(QemuSeqLock
*sl
, QemuLockable
*lock
)
61 seqlock_write_end(sl
);
62 qemu_lockable_unlock(lock
);
64 #define seqlock_write_unlock(sl, lock) \
65 seqlock_write_unlock_impl(sl, QEMU_MAKE_LOCKABLE(lock))
68 static inline unsigned seqlock_read_begin(const QemuSeqLock
*sl
)
70 /* Always fail if a write is in progress. */
71 unsigned ret
= qatomic_read(&sl
->sequence
);
73 /* Read sequence before reading other fields. */
78 static inline int seqlock_read_retry(const QemuSeqLock
*sl
, unsigned start
)
80 /* Read other fields before reading final sequence. */
82 return unlikely(qatomic_read(&sl
->sequence
) != start
);