| 1 |
/* |
|---|
| 2 |
* Copyright (c) 2007, OmniTI Computer Consulting, Inc. |
|---|
| 3 |
* All rights reserved. |
|---|
| 4 |
*/ |
|---|
| 5 |
|
|---|
| 6 |
#ifndef UTILS_NOIT_ATOMIC_H |
|---|
| 7 |
#define UTILS_NOIT_ATOMIC_H |
|---|
| 8 |
|
|---|
| 9 |
#include "noit_config.h" |
|---|
| 10 |
|
|---|
| 11 |
typedef int32_t noit_atomic_t; |
|---|
| 12 |
typedef int64_t noit_atomic64_t; |
|---|
| 13 |
|
|---|
| 14 |
#ifdef HAVE_LIBKERN_OSATOMIC_H |
|---|
| 15 |
/* |
|---|
| 16 |
* This secion is for Darwin. |
|---|
| 17 |
* And we simply don't run on 32bit PPC. Life's a bitch. |
|---|
| 18 |
*/ |
|---|
| 19 |
#include <libkern/OSAtomic.h> |
|---|
| 20 |
typedef OSSpinLock noit_spinlock_t; |
|---|
| 21 |
#define noit_atomic_cas32 OSAtomicCompareAndSwap32 |
|---|
| 22 |
#define noit_atomic_cas64 OSAtomicCompareAndSwap64 |
|---|
| 23 |
#define noit_atomic_inc32 OSAtomicIncrement32 |
|---|
| 24 |
#define noit_atomic_inc64 OSAtomicIncrement64 |
|---|
| 25 |
#define noit_atomic_dec32 OSAtomicDecrement32 |
|---|
| 26 |
#define noit_atomic_dec64 OSAtomicDecrement64 |
|---|
| 27 |
#define noit_spinlock_lock OSSpinLockLock |
|---|
| 28 |
#define noit_spinlock_unlock OSSpinLockUnlock |
|---|
| 29 |
#define noit_spinlock_trylock OSSpinLockTry |
|---|
| 30 |
#elif defined(__GNUC__) |
|---|
| 31 |
|
|---|
| 32 |
typedef u_int32_t noit_atomic32_t |
|---|
| 33 |
typedef u_int64_t noit_atomic64_t |
|---|
| 34 |
|
|---|
| 35 |
#if (SIZEOF_VOID_P == 4) |
|---|
| 36 |
#define noit_atomic_casptr(a,b,c) noit_atomic_cas32((a),(void *)(b),(void *)(c)) |
|---|
| 37 |
#elif (SIZEOF_VOID_P == 8) |
|---|
| 38 |
#define noit_atomic_casptr(a,b,c) noit_atomic_cas64((a),(void *)(b),(void *)(c)) |
|---|
| 39 |
#else |
|---|
| 40 |
#error unsupported pointer width |
|---|
| 41 |
#endif |
|---|
| 42 |
|
|---|
| 43 |
static inline noit_atomic32_t |
|---|
| 44 |
noit_atomic_cas32(volatile noit_atomic32_t *ptr |
|---|
| 45 |
volatile noit_atomic32_t rpl, |
|---|
| 46 |
volatile noit_atomic32_t curr) { |
|---|
| 47 |
noit_atomic32_t prev; |
|---|
| 48 |
__asm__ volatile ( |
|---|
| 49 |
"lock; cmpxchgl %1, %2" |
|---|
| 50 |
: "=a" (prev) |
|---|
| 51 |
: "r" (rpl), "m" (*(ptr)), "0" (curr) |
|---|
| 52 |
: "memory"); |
|---|
| 53 |
return prev; |
|---|
| 54 |
} |
|---|
| 55 |
|
|---|
| 56 |
#ifdef __x86_64__ |
|---|
| 57 |
static inline noit_atomic64_t |
|---|
| 58 |
noit_atomic_cas64(volatile noit_atomic64_t *ptr |
|---|
| 59 |
volatile noit_atomic64_t rpl, |
|---|
| 60 |
volatile noit_atomic64_t curr) { |
|---|
| 61 |
noit_atomic64_t prev; |
|---|
| 62 |
__asm__ volatile ( |
|---|
| 63 |
"lock; cmpxchgq %1, %2" |
|---|
| 64 |
: "=a" (prev) |
|---|
| 65 |
: "r" (rpl), "m" (*(ptr)), "0" (curr) |
|---|
| 66 |
: "memory"); |
|---|
| 67 |
return prev; |
|---|
| 68 |
} |
|---|
| 69 |
#else |
|---|
| 70 |
static inline noit_atomic64_t |
|---|
| 71 |
noit_atomic_cas64(volatile noit_atomic64_t *ptr |
|---|
| 72 |
volatile noit_atomic64_t rpl, |
|---|
| 73 |
volatile noit_atomic64_t curr) { |
|---|
| 74 |
noit_atomic64_t prev; |
|---|
| 75 |
__asm__ volatile ( |
|---|
| 76 |
"pushl %%ebx;" |
|---|
| 77 |
"mov 4+%1,%%ecx;" |
|---|
| 78 |
"mov %1,%%ebx;" |
|---|
| 79 |
"lock;" |
|---|
| 80 |
"cmpxchg8b (%3);" |
|---|
| 81 |
"popl %%ebx" |
|---|
| 82 |
: "=A" (prev) |
|---|
| 83 |
: "m" (rpl), "A" (curr), "r" (ptr) |
|---|
| 84 |
: "%ebx", "%ecx", "memory"); |
|---|
| 85 |
return prev; |
|---|
| 86 |
}; |
|---|
| 87 |
#endif |
|---|
| 88 |
|
|---|
| 89 |
#else |
|---|
| 90 |
#error Please stub out the atomics section for your platform |
|---|
| 91 |
#endif |
|---|
| 92 |
|
|---|
| 93 |
#endif |
|---|