diff options
author | jhb <jhb@FreeBSD.org> | 2005-09-27 17:39:11 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2005-09-27 17:39:11 +0000 |
commit | 89caa56972d968272278a67fe10affb38d9e88eb (patch) | |
tree | 368df1c62ea6aa397797927efbf9c7ccc4b3b92e /sys/arm/include/atomic.h | |
parent | aa790ae8700e7fed7ef83f2549c6bc53d6ae7f8f (diff) | |
download | FreeBSD-src-89caa56972d968272278a67fe10affb38d9e88eb.zip FreeBSD-src-89caa56972d968272278a67fe10affb38d9e88eb.tar.gz |
Add a new atomic_fetchadd() primitive that atomically adds a value to a
variable and returns the previous value of the variable.
Tested on: i386, alpha, sparc64, arm (cognet)
Reviewed by: arch@
Submitted by: cognet (arm)
MFC after: 1 week
Diffstat (limited to 'sys/arm/include/atomic.h')
-rw-r--r-- | sys/arm/include/atomic.h | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/sys/arm/include/atomic.h b/sys/arm/include/atomic.h index 1170847..40288cf 100644 --- a/sys/arm/include/atomic.h +++ b/sys/arm/include/atomic.h @@ -127,6 +127,19 @@ atomic_subtract_32(volatile u_int32_t *p, u_int32_t val) __with_interrupts_disabled(*p -= val); } +static __inline uint32_t +atomic_fetchadd_32(volatile uint32_t *p, uint32_t v) +{ + uint32_t value; + + __with_interrupts_disabled( + { + value = *p; + *p += v; + }); + return (value); +} + #else /* !_KERNEL */ static __inline u_int32_t @@ -240,6 +253,30 @@ atomic_clear_32(volatile uint32_t *address, uint32_t clearmask) : "=r" (ras_start), "=r" (start), "+r" (address), "+r" (clearmask)); } + +static __inline uint32_t +atomic_fetchadd_32(volatile uint32_t *p, uint32_t v) +{ + uint32_t ras_start, start; + + __asm __volatile("1:\n" + "mov %0, #0xe0000008\n" + "adr %1, 2f\n" + "str %1, [%0]\n" + "adr %1, 1b\n" + "mov %0, #0xe0000004\n" + "str %1, [%0]\n" + "ldr %1, %2\n" + "add %3, %1, %3\n" + "str %3, %2\n" + "2:\n" + "mov %3, #0\n" + "str %3, [%0]\n" + : "=r" (ras_start), "=r" (start), "=m" (*p), "+r" (v)); + return (start); +} + + #endif /* _KERNEL */ static __inline int @@ -291,5 +328,6 @@ atomic_readandclear_32(volatile u_int32_t *p) #define atomic_store_ptr atomic_store_32 #define atomic_cmpset_ptr atomic_cmpset_32 #define atomic_set_ptr atomic_set_32 +#define atomic_fetchadd_int atomic_fetchadd_32 #endif /* _MACHINE_ATOMIC_H_ */ |