diff options
author | wez <wez@1665872d-e22b-0410-9e5d-a57ad4215e6d> | 2010-02-19 15:14:55 +0000 |
---|---|---|
committer | wez <wez@1665872d-e22b-0410-9e5d-a57ad4215e6d> | 2010-02-19 15:14:55 +0000 |
commit | 0b894d5ac892355b89ef8f74f58075000d83db55 (patch) | |
tree | aca821bcdf013c49d4a5e99d0d74db06beb98676 | |
parent | da754bc32079245446178ca175d77afb3508398e (diff) | |
download | portableumem-0b894d5ac892355b89ef8f74f58075000d83db55.tar.gz |
improve compatibility with PPC platforms.
git-svn-id: https://labs.omniti.com/portableumem/trunk@52 1665872d-e22b-0410-9e5d-a57ad4215e6d
-rw-r--r-- | misc.c | 3 | ||||
-rw-r--r-- | sol_compat.h | 55 | ||||
-rw-r--r-- | umem.c | 5 |
3 files changed, 57 insertions, 6 deletions
@@ -66,6 +66,9 @@ #define ERR_SIZE 8192 /* must be a power of 2 */ static mutex_t umem_error_lock = DEFAULTMUTEX; +#ifdef NEED_64_LOCK +pthread_mutex_t umem_ppc_64inc_lock = PTHREAD_MUTEX_INITIALIZER; +#endif static char umem_error_buffer[ERR_SIZE] = ""; static uint_t umem_error_begin = 0; 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 @@ -518,13 +518,10 @@ umem_log_header_t *umem_failure_log; umem_log_header_t *umem_slab_log; extern thread_t _thr_self(void); -#if defined(__MACH__) || defined(__FreeBSD__) +#ifndef CPUHINT # define CPUHINT() ((int)(_thr_self())) #endif -#ifndef CPUHINT -#define CPUHINT() (_thr_self()) -#endif #define CPUHINT_MAX() INT_MAX |