qemu/include/qemu/seqlock.h
<<
>>
Prefs
   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
  20typedef struct QemuSeqLock QemuSeqLock;
  21
  22struct QemuSeqLock {
  23    unsigned sequence;
  24};
  25
  26static inline void seqlock_init(QemuSeqLock *sl)
  27{
  28    sl->sequence = 0;
  29}
  30
  31/* Lock out other writers and update the count.  */
  32static inline void seqlock_write_begin(QemuSeqLock *sl)
  33{
  34    atomic_set(&sl->sequence, sl->sequence + 1);
  35
  36    /* Write sequence before updating other fields.  */
  37    smp_wmb();
  38}
  39
  40static inline void seqlock_write_end(QemuSeqLock *sl)
  41{
  42    /* Write other fields before finalizing sequence.  */
  43    smp_wmb();
  44
  45    atomic_set(&sl->sequence, sl->sequence + 1);
  46}
  47
  48static inline unsigned seqlock_read_begin(QemuSeqLock *sl)
  49{
  50    /* Always fail if a write is in progress.  */
  51    unsigned ret = atomic_read(&sl->sequence);
  52
  53    /* Read sequence before reading other fields.  */
  54    smp_rmb();
  55    return ret & ~1;
  56}
  57
  58static inline int seqlock_read_retry(const QemuSeqLock *sl, unsigned start)
  59{
  60    /* Read other fields before reading final sequence.  */
  61    smp_rmb();
  62    return unlikely(atomic_read(&sl->sequence) != start);
  63}
  64
  65#endif
  66