seqlock.h (2043B)
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#include "qemu/lockable.h" 20 21typedef struct QemuSeqLock QemuSeqLock; 22 23struct QemuSeqLock { 24 unsigned sequence; 25}; 26 27static inline void seqlock_init(QemuSeqLock *sl) 28{ 29 sl->sequence = 0; 30} 31 32/* Lock out other writers and update the count. */ 33static inline void seqlock_write_begin(QemuSeqLock *sl) 34{ 35 qatomic_set(&sl->sequence, sl->sequence + 1); 36 37 /* Write sequence before updating other fields. */ 38 smp_wmb(); 39} 40 41static inline void seqlock_write_end(QemuSeqLock *sl) 42{ 43 /* Write other fields before finalizing sequence. */ 44 smp_wmb(); 45 46 qatomic_set(&sl->sequence, sl->sequence + 1); 47} 48 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 58/* Update the count and release the lock. */ 59static inline void seqlock_write_unlock_impl(QemuSeqLock *sl, QemuLockable *lock) 60{ 61 seqlock_write_end(sl); 62 qemu_lockable_unlock(lock); 63} 64#define seqlock_write_unlock(sl, lock) \ 65 seqlock_write_unlock_impl(sl, QEMU_MAKE_LOCKABLE(lock)) 66 67 68static inline unsigned seqlock_read_begin(const QemuSeqLock *sl) 69{ 70 /* Always fail if a write is in progress. */ 71 unsigned ret = qatomic_read(&sl->sequence); 72 73 /* Read sequence before reading other fields. */ 74 smp_rmb(); 75 return ret & ~1; 76} 77 78static inline int seqlock_read_retry(const QemuSeqLock *sl, unsigned start) 79{ 80 /* Read other fields before reading final sequence. */ 81 smp_rmb(); 82 return unlikely(qatomic_read(&sl->sequence) != start); 83} 84 85#endif