diff options
author | Ahmad Fatoum <a.fatoum@pengutronix.de> | 2020-06-02 10:54:03 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2020-06-03 10:03:33 +0200 |
commit | 386db316df56ea65db89335d6523dd4719933586 (patch) | |
tree | 44f6797c668996e5c25051f086b4a29f86224db4 /include | |
parent | 26efcc8e97477b91a8f7fc94545b824a33f0e6cd (diff) | |
download | barebox-386db316df56ea65db89335d6523dd4719933586.tar.gz barebox-386db316df56ea65db89335d6523dd4719933586.tar.xz |
ARM: atomic.h: move generic implementation to asm-generic
For easier code-sharing, the UBIFS code still uses the Linux atomic
accessors. Make porting it to sandbox easier, by providing these
functions for all platforms.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'include')
-rw-r--r-- | include/asm-generic/atomic.h | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/include/asm-generic/atomic.h b/include/asm-generic/atomic.h new file mode 100644 index 0000000000..6357b66a53 --- /dev/null +++ b/include/asm-generic/atomic.h @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * based on linux/include/asm-arm/atomic.h + * + * Copyright (c) 1996 Russell King. + */ + +#ifndef __ASM_GENERIC_ATOMIC_H +#define __ASM_GENERIC_ATOMIC_H + +#ifdef CONFIG_SMP +#error SMP not supported +#endif + +typedef struct { volatile int counter; } atomic_t; + +#define ATOMIC_INIT(i) { (i) } + +#define atomic_read(v) ((v)->counter) +#define atomic_set(v,i) (((v)->counter) = (i)) + +static inline void atomic_add(int i, volatile atomic_t *v) +{ + unsigned long flags = 0; + + local_irq_save(flags); + v->counter += i; + local_irq_restore(flags); +} + +static inline void atomic_sub(int i, volatile atomic_t *v) +{ + unsigned long flags = 0; + + local_irq_save(flags); + v->counter -= i; + local_irq_restore(flags); +} + +static inline void atomic_inc(volatile atomic_t *v) +{ + unsigned long flags = 0; + + local_irq_save(flags); + v->counter += 1; + local_irq_restore(flags); +} + +static inline void atomic_dec(volatile atomic_t *v) +{ + unsigned long flags = 0; + + local_irq_save(flags); + v->counter -= 1; + local_irq_restore(flags); +} + +static inline int atomic_dec_and_test(volatile atomic_t *v) +{ + unsigned long flags = 0; + int val; + + local_irq_save(flags); + val = v->counter; + v->counter = val -= 1; + local_irq_restore(flags); + + return val == 0; +} + +static inline int atomic_add_negative(int i, volatile atomic_t *v) +{ + unsigned long flags = 0; + int val; + + local_irq_save(flags); + val = v->counter; + v->counter = val += i; + local_irq_restore(flags); + + return val < 0; +} + +static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr) +{ + unsigned long flags = 0; + + local_irq_save(flags); + *addr &= ~mask; + local_irq_restore(flags); +} + +/* Atomic operations are already serializing on ARM */ +#define smp_mb__before_atomic_dec() barrier() +#define smp_mb__after_atomic_dec() barrier() +#define smp_mb__before_atomic_inc() barrier() +#define smp_mb__after_atomic_inc() barrier() + +#endif |