diff options
Diffstat (limited to 'sol_compat.h')
-rw-r--r-- | sol_compat.h | 55 |
1 files changed, 53 insertions, 2 deletions
diff --git a/sol_compat.h b/sol_compat.h index 215296a..b2e3e25 100644 --- a/sol_compat.h +++ b/sol_compat.h @@ -59,7 +59,7 @@ static INLINE hrtime_t gethrtime(void) { static INLINE thread_t _thr_self(void) { return thr_self(); } -#if defined(_MACH_PORT_T) +#if defined(__MACH__) #define CPUHINT() (pthread_mach_thread_np(pthread_self())) #endif # define thr_sigsetmask pthread_sigmask @@ -114,6 +114,12 @@ static INLINE int thr_create(void *stack_base, # ifdef _WIN32 # define ec_atomic_inc(a) InterlockedIncrement(a) # define ec_atomic_inc64(a) InterlockedIncrement64(a) +# elif defined(__MACH__) +# include <libkern/OSAtomic.h> +# define ec_atomic_inc(x) OSAtomicIncrement32Barrier((int32_t*)x) +# if !defined(__ppc__) +# define ec_atomic_inc64(x) OSAtomicIncrement64Barrier((int64_t*)x) +# endif # elif (defined(__i386__) || defined(__x86_64__)) && defined(__GNUC__) static INLINE uint_t ec_atomic_cas(uint_t *mem, uint_t with, uint_t cmp) { @@ -124,6 +130,40 @@ static INLINE uint_t ec_atomic_cas(uint_t *mem, uint_t with, uint_t cmp) : "memory"); return prev; } +static INLINE uint64_t ec_atomic_cas64(uint64_t *mem, uint64_t with, + uint64_t cmp) +{ + uint64_t prev; +# if defined(__x86_64__) + __asm__ volatile ("lock; cmpxchgq %1, %2" + : "=a" (prev) + : "r" (with), "m" (*(mem)), "0" (cmp) + : "memory"); +# else + __asm__ volatile ( + "pushl %%ebx;" + "mov 4+%1,%%ecx;" + "mov %1,%%ebx;" + "lock;" + "cmpxchg8b (%3);" + "popl %%ebx" + : "=A" (prev) + : "m" (with), "A" (cmp), "r" (mem) + : "%ecx", "memory"); +# endif + return prev; +} +static INLINE uint64_t ec_atomic_inc64(uint64_t *mem) +{ + register uint64_t last; + do { + last = *mem; + } while (ec_atomic_cas64(mem, last+1, last) != last); + return ++last; +} +# define ec_atomic_inc64 ec_atomic_inc64 +# else +# error no atomic solution for your platform # endif # ifndef ec_atomic_inc @@ -139,7 +179,18 @@ static INLINE uint_t ec_atomic_inc(uint_t *mem) # ifndef ec_atomic_inc64 /* yeah, it's not great. It's only used to bump failed allocation * counts, so it is not critical right now. */ -# define ec_atomic_inc64(a) (*a)++ +extern pthread_mutex_t umem_ppc_64inc_lock; +static INLINE uint64_t ec_atomic_inc64(uint64_t *val) +{ + uint64_t rval; + pthread_mutex_lock(&umem_ppc_64inc_lock); + rval = *val + 1; + *val = rval; + pthread_mutex_unlock(&umem_ppc_64inc_lock); + return rval; +} +# define ec_atomic_inc64 ec_atomic_inc64 +# define NEED_64_LOCK 1 # endif #endif |