[U-Boot] [RFC PATCH v1] mips: add atomic operations

Add mips version of atomic.h and basic atomic operations. These aren't the optimised versions from the Linux kernel, just basic stubs that satisfy users that need something to define atomic_inc() etc.
Signed-off-by: Chris Packham judge.packham@gmail.com
--- At $dayjob we have a mips target that we want to run UBIFS on. UBIFS requires atomic.h. This is my naive attempt to supply enough of atomic.h to satisfy UBIFS.
It's no coincidence that this looks like the arm version. I am wondering if it's worth a asm-generic version leaving architectures that actually need true atomic operations able to define them.
arch/mips/include/asm/atomic.h | 151 +++++++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 arch/mips/include/asm/atomic.h
diff --git a/arch/mips/include/asm/atomic.h b/arch/mips/include/asm/atomic.h new file mode 100644 index 000000000000..3ab5684fdef4 --- /dev/null +++ b/arch/mips/include/asm/atomic.h @@ -0,0 +1,151 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +#ifndef _ASM_ATOMIC_H +#define _ASM_ATOMIC_H + +#include <asm/system.h> + +typedef struct { volatile int counter; } atomic_t; +#if BITS_PER_LONG == 32 +typedef struct { volatile long long counter; } atomic64_t; +#else /* BIT_PER_LONG == 32 */ +typedef struct { volatile long counter; } atomic64_t; +#endif + +#define ATOMIC_INIT(i) { (i) } + +#define atomic_read(v) ((v)->counter) +#define atomic_set(v, i) (((v)->counter) = (i)) +#define atomic64_read(v) atomic_read(v) +#define atomic64_set(v, i) atomic_set(v, 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); +} + +#if BITS_PER_LONG == 32 + +static inline void atomic64_add(long long i, volatile atomic64_t *v) +{ + unsigned long flags = 0; + + local_irq_save(flags); + v->counter += i; + local_irq_restore(flags); +} + +static inline void atomic64_sub(long long i, volatile atomic64_t *v) +{ + unsigned long flags = 0; + + local_irq_save(flags); + v->counter -= i; + local_irq_restore(flags); +} + +#else /* BIT_PER_LONG == 32 */ + +static inline void atomic64_add(long i, volatile atomic64_t *v) +{ + unsigned long flags = 0; + + local_irq_save(flags); + v->counter += i; + local_irq_restore(flags); +} + +static inline void atomic64_sub(long i, volatile atomic64_t *v) +{ + unsigned long flags = 0; + + local_irq_save(flags); + v->counter -= i; + local_irq_restore(flags); +} +#endif /* BIT_PER_LONG == 32 */ + +static inline void atomic64_inc(volatile atomic64_t *v) +{ + unsigned long flags = 0; + + local_irq_save(flags); + v->counter += 1; + local_irq_restore(flags); +} + +static inline void atomic64_dec(volatile atomic64_t *v) +{ + unsigned long flags = 0; + + local_irq_save(flags); + v->counter -= 1; + local_irq_restore(flags); +} + +#endif

Hi Chris,
(added Daniel)
On 07.09.2018 10:24, Chris Packham wrote:
Add mips version of atomic.h and basic atomic operations. These aren't the optimised versions from the Linux kernel, just basic stubs that satisfy users that need something to define atomic_inc() etc.
Signed-off-by: Chris Packham judge.packham@gmail.com
At $dayjob we have a mips target that we want to run UBIFS on. UBIFS requires atomic.h. This is my naive attempt to supply enough of atomic.h to satisfy UBIFS.
It's no coincidence that this looks like the arm version. I am wondering if it's worth a asm-generic version leaving architectures that actually need true atomic operations able to define them.
I did a pretty similar job and copied the files from xtensa a few weeks ago:
https://patchwork.ozlabs.org/patch/958286/
It would be better of course, to have some generic version of this file. But frankly, I don't have the time right now for this.
Thanks, Stefan
arch/mips/include/asm/atomic.h | 151 +++++++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 arch/mips/include/asm/atomic.h
diff --git a/arch/mips/include/asm/atomic.h b/arch/mips/include/asm/atomic.h new file mode 100644 index 000000000000..3ab5684fdef4 --- /dev/null +++ b/arch/mips/include/asm/atomic.h @@ -0,0 +1,151 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +#ifndef _ASM_ATOMIC_H +#define _ASM_ATOMIC_H
+#include <asm/system.h>
+typedef struct { volatile int counter; } atomic_t; +#if BITS_PER_LONG == 32 +typedef struct { volatile long long counter; } atomic64_t; +#else /* BIT_PER_LONG == 32 */ +typedef struct { volatile long counter; } atomic64_t; +#endif
+#define ATOMIC_INIT(i) { (i) }
+#define atomic_read(v) ((v)->counter) +#define atomic_set(v, i) (((v)->counter) = (i)) +#define atomic64_read(v) atomic_read(v) +#define atomic64_set(v, i) atomic_set(v, 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);
+}
+#if BITS_PER_LONG == 32
+static inline void atomic64_add(long long i, volatile atomic64_t *v) +{
- unsigned long flags = 0;
- local_irq_save(flags);
- v->counter += i;
- local_irq_restore(flags);
+}
+static inline void atomic64_sub(long long i, volatile atomic64_t *v) +{
- unsigned long flags = 0;
- local_irq_save(flags);
- v->counter -= i;
- local_irq_restore(flags);
+}
+#else /* BIT_PER_LONG == 32 */
+static inline void atomic64_add(long i, volatile atomic64_t *v) +{
- unsigned long flags = 0;
- local_irq_save(flags);
- v->counter += i;
- local_irq_restore(flags);
+}
+static inline void atomic64_sub(long i, volatile atomic64_t *v) +{
- unsigned long flags = 0;
- local_irq_save(flags);
- v->counter -= i;
- local_irq_restore(flags);
+} +#endif /* BIT_PER_LONG == 32 */
+static inline void atomic64_inc(volatile atomic64_t *v) +{
- unsigned long flags = 0;
- local_irq_save(flags);
- v->counter += 1;
- local_irq_restore(flags);
+}
+static inline void atomic64_dec(volatile atomic64_t *v) +{
- unsigned long flags = 0;
- local_irq_save(flags);
- v->counter -= 1;
- local_irq_restore(flags);
+}
+#endif

On Fri, 7 Sep 2018, 10:24 PM Stefan, sr@denx.de wrote:
Hi Chris,
(added Daniel)
On 07.09.2018 10:24, Chris Packham wrote:
Add mips version of atomic.h and basic atomic operations. These aren't the optimised versions from the Linux kernel, just basic stubs that satisfy users that need something to define atomic_inc() etc.
Signed-off-by: Chris Packham judge.packham@gmail.com
At $dayjob we have a mips target that we want to run UBIFS on. UBIFS requires atomic.h. This is my naive attempt to supply enough of atomic.h to satisfy UBIFS.
It's no coincidence that this looks like the arm version. I am wondering if it's worth a asm-generic version leaving architectures that actually need true atomic operations able to define them.
I did a pretty similar job and copied the files from xtensa a few weeks ago:
Weird coincidence. I figured noone had needed ubifs on mips since the need for atomic.h has been there for a while.
I'm more than happy for your version to go in since it's part of a bigger series. The only thing missing is 64 bit support (our platform happens to be mips64) but i don't think ubifs cares.
It would be better of course, to have some generic version of this file. But frankly, I don't have the time right now for this.
Given that the arm, xtensa and now mips are so similar it's probably worth it. I'll see if i can find some cycles to spend on it.
participants (2)
-
Chris Packham
-
Stefan