2014-01-06 09:49:34 +04:00
|
|
|
/*
|
|
|
|
* Copyright 2014, Paweł Dziepak, pdziepak@quarnos.org.
|
|
|
|
* Distributed under the terms of the MIT License.
|
|
|
|
*/
|
|
|
|
#ifndef _KERNEL_ARCH_X86_32_ATOMIC_H
|
|
|
|
#define _KERNEL_ARCH_X86_32_ATOMIC_H
|
|
|
|
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
memory_read_barrier_inline(void)
|
|
|
|
{
|
|
|
|
asm volatile("lock; addl $0, (%%esp)" : : : "memory");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
memory_write_barrier_inline(void)
|
|
|
|
{
|
|
|
|
asm volatile("lock; addl $0, (%%esp)" : : : "memory");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
memory_full_barrier_inline(void)
|
|
|
|
{
|
|
|
|
asm volatile("lock; addl $0, (%%esp)" : : : "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
|
|
|
|
|
|
|
|
|
2014-08-25 16:55:55 +04:00
|
|
|
#if __GNUC__ < 4
|
|
|
|
|
|
|
|
|
2014-01-06 09:49:34 +04:00
|
|
|
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)
|
|
|
|
{
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
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
|
2014-08-25 16:55:55 +04:00
|
|
|
#define atomic_test_and_set atomic_test_and_set_inline
|
|
|
|
#define atomic_add atomic_add_inline
|
2014-01-06 09:49:34 +04:00
|
|
|
#define atomic_get atomic_get_inline
|
|
|
|
|
|
|
|
|
2014-08-25 16:55:55 +04:00
|
|
|
#endif // dark ages
|
|
|
|
|
|
|
|
|
2014-01-06 09:49:34 +04:00
|
|
|
#endif // _KERNEL_ARCH_X86_32_ATOMIC_H
|
|
|
|
|