version 1.13, 2014/02/22 17:08:30 |
version 1.14, 2014/02/24 17:18:27 |
Line 53 __RCSID("$NetBSD$"); |
|
Line 53 __RCSID("$NetBSD$"); |
|
#define I128 I16 I16 I16 I16 I16 I16 I16 I16 |
#define I128 I16 I16 I16 I16 I16 I16 I16 I16 |
|
|
static __cpu_simple_lock_t atomic_locks[128] = { I128 }; |
static __cpu_simple_lock_t atomic_locks[128] = { I128 }; |
|
/* |
|
* Pick a lock out of above array depending on the object address |
|
* passed. Most variables used atomically will not be in the same |
|
* cacheline - and if they are, using the same lock is fine. |
|
*/ |
|
#define HASH(PTR) (((uintptr_t)(PTR) >> 3) & 127) |
|
|
#ifdef __HAVE_ASM_ATOMIC_CAS_UP |
#ifdef __HAVE_ASM_ATOMIC_CAS_UP |
extern uint32_t _atomic_cas_up(volatile uint32_t *, uint32_t, uint32_t); |
extern uint32_t _atomic_cas_up(volatile uint32_t *, uint32_t, uint32_t); |
Line 143 _atomic_cas_mp(volatile uint32_t *ptr, u |
|
Line 149 _atomic_cas_mp(volatile uint32_t *ptr, u |
|
__cpu_simple_lock_t *lock; |
__cpu_simple_lock_t *lock; |
uint32_t ret; |
uint32_t ret; |
|
|
lock = &atomic_locks[((uintptr_t)ptr >> 3) & 127]; |
lock = &atomic_locks[HASH(ptr)]; |
|
__cpu_simple_lock(lock); |
|
ret = *ptr; |
|
if (__predict_true(ret == old)) { |
|
*ptr = new; |
|
} |
|
__cpu_simple_unlock(lock); |
|
|
|
return ret; |
|
} |
|
|
|
static uint16_t |
|
_atomic_cas_16_mp(volatile uint16_t *ptr, uint16_t old, uint16_t new) |
|
{ |
|
__cpu_simple_lock_t *lock; |
|
uint16_t ret; |
|
|
|
lock = &atomic_locks[HASH(ptr)]; |
|
__cpu_simple_lock(lock); |
|
ret = *ptr; |
|
if (__predict_true(ret == old)) { |
|
*ptr = new; |
|
} |
|
__cpu_simple_unlock(lock); |
|
|
|
return ret; |
|
} |
|
|
|
static uint8_t |
|
_atomic_cas_8_mp(volatile uint8_t *ptr, uint8_t old, uint8_t new) |
|
{ |
|
__cpu_simple_lock_t *lock; |
|
uint8_t ret; |
|
|
|
lock = &atomic_locks[HASH(ptr)]; |
__cpu_simple_lock(lock); |
__cpu_simple_lock(lock); |
ret = *ptr; |
ret = *ptr; |
if (__predict_true(ret == old)) { |
if (__predict_true(ret == old)) { |
Line 186 __libc_atomic_init(void) |
|
Line 226 __libc_atomic_init(void) |
|
size_t len; |
size_t len; |
|
|
_atomic_cas_fn = _atomic_cas_mp; |
_atomic_cas_fn = _atomic_cas_mp; |
|
_atomic_cas_16_fn = _atomic_cas_16_mp; |
|
_atomic_cas_8_fn = _atomic_cas_8_mp; |
|
|
mib[0] = CTL_HW; |
mib[0] = CTL_HW; |
mib[1] = HW_NCPU; |
mib[1] = HW_NCPU; |