/*
* Copyright (C) Igor Sysoev
* Copyright (C) Nginx, Inc.
*/
/*
* "casa [r1] 0x80, r2, r0" and
* "casxa [r1] 0x80, r2, r0" do the following:
*
* if ([r1] == r2) {
* swap(r0, [r1]);
* } else {
* r0 = [r1];
* }
*
* so "r0 == r2" means that the operation was successful.
*
*
* The "r" means the general register.
* The "+r" means the general register used for both input and output.
*/
#if (NGX_PTR_SIZE == 4)
#define NGX_CASA "casa"
#else
#define NGX_CASA "casxa"
#endif
static ngx_inline ngx_atomic_uint_t
ngx_atomic_cmp_set(ngx_atomic_t *lock, ngx_atomic_uint_t old,
ngx_atomic_uint_t set)
{
__asm__ volatile (
NGX_CASA " [%1] 0x80, %2, %0"
: "+r" (set) : "r" (lock), "r" (old) : "memory");
return (set == old);
}
static ngx_inline ngx_atomic_int_t
ngx_atomic_fetch_add(ngx_atomic_t *value, ngx_atomic_int_t add)
{
ngx_atomic_uint_t old, res;
old = *value;
for ( ;; ) {
res = old + add;
__asm__ volatile (
NGX_CASA " [%1] 0x80, %2, %0"
: "+r" (res) : "r" (value), "r" (old) : "memory");
if (res == old) {
return res;
}
old = res;
}
}
#if (NGX_SMP)
#define ngx_memory_barrier() \
__asm__ volatile ( \
"membar #LoadLoad | #LoadStore | #StoreStore | #StoreLoad" \
::: "memory")
#else
#define ngx_memory_barrier() __asm__ volatile ("" ::: "memory")
#endif
#define ngx_cpu_pause()