atomic.h 2.4 KB
Newer Older
Y
Yoshinori Sato 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13
#ifndef __ARCH_H8300_ATOMIC__
#define __ARCH_H8300_ATOMIC__

#include <linux/types.h>
#include <asm/cmpxchg.h>

/*
 * Atomic operations that C can't guarantee us.  Useful for
 * resource counting etc..
 */

#define ATOMIC_INIT(i)	{ (i) }

14 15
#define atomic_read(v)		READ_ONCE((v)->counter)
#define atomic_set(v, i)	WRITE_ONCE(((v)->counter), (i))
Y
Yoshinori Sato 已提交
16 17 18

#include <linux/kernel.h>

19 20 21 22 23 24 25 26 27 28
#define ATOMIC_OP_RETURN(op, c_op)				\
static inline int atomic_##op##_return(int i, atomic_t *v)	\
{								\
	h8300flags flags;					\
	int ret;						\
								\
	flags = arch_local_irq_save();				\
	ret = v->counter c_op i;				\
	arch_local_irq_restore(flags);				\
	return ret;						\
Y
Yoshinori Sato 已提交
29 30
}

31 32 33 34 35 36 37 38 39 40 41 42 43
#define ATOMIC_FETCH_OP(op, c_op)				\
static inline int atomic_fetch_##op(int i, atomic_t *v)		\
{								\
	h8300flags flags;					\
	int ret;						\
								\
	flags = arch_local_irq_save();				\
	ret = v->counter;					\
	v->counter c_op i;					\
	arch_local_irq_restore(flags);				\
	return ret;						\
}

44 45 46 47 48 49 50 51
#define ATOMIC_OP(op, c_op)					\
static inline void atomic_##op(int i, atomic_t *v)		\
{								\
	h8300flags flags;					\
								\
	flags = arch_local_irq_save();				\
	v->counter c_op i;					\
	arch_local_irq_restore(flags);				\
Y
Yoshinori Sato 已提交
52 53
}

54 55
ATOMIC_OP_RETURN(add, +=)
ATOMIC_OP_RETURN(sub, -=)
Y
Yoshinori Sato 已提交
56

57 58 59 60 61 62 63 64 65 66 67
#define ATOMIC_OPS(op, c_op)					\
	ATOMIC_OP(op, c_op)					\
	ATOMIC_FETCH_OP(op, c_op)

ATOMIC_OPS(and, &=)
ATOMIC_OPS(or,  |=)
ATOMIC_OPS(xor, ^=)
ATOMIC_OPS(add, +=)
ATOMIC_OPS(sub, -=)

#undef ATOMIC_OPS
68 69
#undef ATOMIC_OP_RETURN
#undef ATOMIC_OP
Y
Yoshinori Sato 已提交
70

71 72
#define atomic_add_negative(a, v)	(atomic_add_return((a), (v)) < 0)
#define atomic_sub_and_test(i, v)	(atomic_sub_return(i, v) == 0)
Y
Yoshinori Sato 已提交
73

74 75
#define atomic_inc_return(v)		atomic_add_return(1, v)
#define atomic_dec_return(v)		atomic_sub_return(1, v)
Y
Yoshinori Sato 已提交
76

77 78
#define atomic_inc(v)			(void)atomic_inc_return(v)
#define atomic_inc_and_test(v)		(atomic_inc_return(v) == 0)
Y
Yoshinori Sato 已提交
79

80 81
#define atomic_dec(v)			(void)atomic_dec_return(v)
#define atomic_dec_and_test(v)		(atomic_dec_return(v) == 0)
Y
Yoshinori Sato 已提交
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109

static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
{
	int ret;
	h8300flags flags;

	flags = arch_local_irq_save();
	ret = v->counter;
	if (likely(ret == old))
		v->counter = new;
	arch_local_irq_restore(flags);
	return ret;
}

static inline int __atomic_add_unless(atomic_t *v, int a, int u)
{
	int ret;
	h8300flags flags;

	flags = arch_local_irq_save();
	ret = v->counter;
	if (ret != u)
		v->counter += a;
	arch_local_irq_restore(flags);
	return ret;
}

#endif /* __ARCH_H8300_ATOMIC __ */