]> git.proxmox.com Git - mirror_qemu.git/blame - include/qemu/seqlock.h
Merge tag 'pull-riscv-to-apply-20240110' of https://github.com/alistair23/qemu into...
[mirror_qemu.git] / include / qemu / seqlock.h
CommitLineData
ea753d81
PB
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 */
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"
988fcafc 19#include "qemu/lockable.h"
ea753d81
PB
20
21typedef struct QemuSeqLock QemuSeqLock;
22
23struct QemuSeqLock {
ea753d81
PB
24 unsigned sequence;
25};
26
ccdb3c1f 27static inline void seqlock_init(QemuSeqLock *sl)
ea753d81 28{
ea753d81
PB
29 sl->sequence = 0;
30}
31
32/* Lock out other writers and update the count. */
03719e44 33static inline void seqlock_write_begin(QemuSeqLock *sl)
ea753d81 34{
d73415a3 35 qatomic_set(&sl->sequence, sl->sequence + 1);
ea753d81
PB
36
37 /* Write sequence before updating other fields. */
38 smp_wmb();
39}
40
03719e44 41static inline void seqlock_write_end(QemuSeqLock *sl)
ea753d81
PB
42{
43 /* Write other fields before finalizing sequence. */
44 smp_wmb();
45
d73415a3 46 qatomic_set(&sl->sequence, sl->sequence + 1);
ea753d81
PB
47}
48
988fcafc
PB
49/* Lock out other writers and update the count. */
50static inline void seqlock_write_lock_impl(QemuSeqLock *sl, QemuLockable *lock)
51{
52 qemu_lockable_lock(lock);
53 seqlock_write_begin(sl);
54}
55#define seqlock_write_lock(sl, lock) \
56 seqlock_write_lock_impl(sl, QEMU_MAKE_LOCKABLE(lock))
57
e261b368 58/* Update the count and release the lock. */
988fcafc
PB
59static inline void seqlock_write_unlock_impl(QemuSeqLock *sl, QemuLockable *lock)
60{
e261b368 61 seqlock_write_end(sl);
988fcafc 62 qemu_lockable_unlock(lock);
988fcafc
PB
63}
64#define seqlock_write_unlock(sl, lock) \
65 seqlock_write_unlock_impl(sl, QEMU_MAKE_LOCKABLE(lock))
66
67
c04649ee 68static inline unsigned seqlock_read_begin(const QemuSeqLock *sl)
ea753d81
PB
69{
70 /* Always fail if a write is in progress. */
d73415a3 71 unsigned ret = qatomic_read(&sl->sequence);
ea753d81
PB
72
73 /* Read sequence before reading other fields. */
74 smp_rmb();
d12f7309 75 return ret & ~1;
ea753d81
PB
76}
77
123fdbac 78static inline int seqlock_read_retry(const QemuSeqLock *sl, unsigned start)
ea753d81
PB
79{
80 /* Read other fields before reading final sequence. */
81 smp_rmb();
d73415a3 82 return unlikely(qatomic_read(&sl->sequence) != start);
ea753d81
PB
83}
84
85#endif