blob: 2804815eea5f3eb2a08bfb29753dd447ab1d3b09 [file] [log] [blame]
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2011 RedHat, Inc.
* All Rights Reserved.
*/
#ifndef __ATOMIC_H__
#define __ATOMIC_H__
/*
* Atomics are provided by liburcu.
*
* API and guidelines for which operations provide memory barriers is here:
*
* https://github.com/urcu/userspace-rcu/blob/master/doc/uatomic-api.md
*
* Unlike the kernel, the same interface supports 32 and 64 bit atomic integers.
*/
#include <urcu/uatomic.h>
#include "spinlock.h"
typedef int32_t atomic_t;
typedef int64_t atomic64_t;
#define atomic_read(a) uatomic_read(a)
#define atomic_set(a, v) uatomic_set(a, v)
#define atomic_add(v, a) uatomic_add(a, v)
#define atomic_sub(v, a) uatomic_sub(a, v)
#define atomic_inc(a) uatomic_inc(a)
#define atomic_dec(a) uatomic_dec(a)
#define atomic_inc_return(a) uatomic_add_return(a, 1)
#define atomic_dec_return(a) uatomic_sub_return(a, 1)
#define atomic_dec_and_test(a) (atomic_dec_return(a) == 0)
#define cmpxchg(a, o, n) uatomic_cmpxchg(a, o, n);
static inline bool atomic_add_unless(atomic_t *a, int v, int u)
{
int r = atomic_read(a);
int n, o;
do {
o = r;
if (o == u)
break;
n = o + v;
r = uatomic_cmpxchg(a, o, n);
} while (r != o);
return o != u;
}
static inline bool atomic_dec_and_lock(atomic_t *a, spinlock_t *lock)
{
if (atomic_add_unless(a, -1, 1))
return 0;
spin_lock(lock);
if (atomic_dec_and_test(a))
return 1;
spin_unlock(lock);
return 0;
}
#define atomic64_read(a) uatomic_read(a)
#define atomic64_set(a, v) uatomic_set(a, v)
#define atomic64_add(v, a) uatomic_add(a, v)
#define atomic64_sub(v, a) uatomic_sub(a, v)
#define atomic64_inc(a) uatomic_inc(a)
#define atomic64_dec(a) uatomic_dec(a)
#endif /* __ATOMIC_H__ */