arm: Add initial memory barrier functions

* These likely need reviewed by someone better
  at arm assembly. (#10537)
This commit is contained in:
Alexander von Gluck IV 2014-02-12 23:11:11 -06:00
parent fca8407a2a
commit 92b2e03d0d
1 changed files with 105 additions and 0 deletions

View File

@ -0,0 +1,105 @@
/*
* Copyright 2014, Paweł Dziepak, pdziepak@quarnos.org.
* Distributed under the terms of the MIT License.
*
* Authors:
* Alexander von Gluck IV <kallisti5@unixzen.com>
*/
#ifndef _KERNEL_ARCH_ARM_ATOMIC_H
#define _KERNEL_ARCH_ARM_ATOMIC_H
static inline void
memory_read_barrier_inline(void)
{
// TODO Only ArmV7+?
asm volatile("dsb sy" : : : "memory");
}
static inline void
memory_write_barrier_inline(void)
{
// TODO Only ArmV7+?
asm volatile("dsb sy" : : : "memory");
}
static inline void
memory_full_barrier_inline(void)
{
// TODO Only ArmV7+?
asm volatile("dsb sy" : : : "memory");
}
#define memory_read_barrier memory_read_barrier_inline
#define memory_write_barrier memory_write_barrier_inline
#define memory_full_barrier memory_full_barrier_inline
static inline void
atomic_set_inline(int32* value, int32 newValue)
{
memory_write_barrier();
*(volatile int32*)value = newValue;
}
static inline int32
atomic_get_and_set_inline(int32* value, int32 newValue)
{
// BIG TODO: ARM Atomic get and set
// asm volatile("xchgl %0, (%1)"
// : "+r" (newValue)
// : "r" (value)
// : "memory");
return newValue;
}
static inline int32
atomic_test_and_set_inline(int32* value, int32 newValue, int32 testAgainst)
{
// BIG TODO: ARM Atomic test and set inline
// asm volatile("lock; cmpxchgl %2, (%3)"
// : "=a" (newValue)
// : "0" (testAgainst), "r" (newValue), "r" (value)
// : "memory");
return newValue;
}
static inline int32
atomic_add_inline(int32* value, int32 newValue)
{
// BIG TODO: ARM Atomic add inline
// asm volatile("lock; xaddl %0, (%1)"
// : "+r" (newValue)
// : "r" (value)
// : "memory");
return newValue;
}
static inline int32
atomic_get_inline(int32* value)
{
int32 newValue = *(volatile int32*)value;
memory_read_barrier();
return newValue;
}
#define atomic_set atomic_set_inline
#define atomic_get_and_set atomic_get_and_set_inline
#ifndef atomic_test_and_set
# define atomic_test_and_set atomic_test_and_set_inline
#endif
#ifndef atomic_add
# define atomic_add atomic_add_inline
#endif
#define atomic_get atomic_get_inline
#endif // _KERNEL_ARCH_ARM_ATOMIC_H