summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwez <wez@1665872d-e22b-0410-9e5d-a57ad4215e6d>2010-02-19 15:14:55 +0000
committerwez <wez@1665872d-e22b-0410-9e5d-a57ad4215e6d>2010-02-19 15:14:55 +0000
commit0b894d5ac892355b89ef8f74f58075000d83db55 (patch)
treeaca821bcdf013c49d4a5e99d0d74db06beb98676
parentda754bc32079245446178ca175d77afb3508398e (diff)
downloadportableumem-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.c3
-rw-r--r--sol_compat.h55
-rw-r--r--umem.c5
3 files changed, 57 insertions, 6 deletions
diff --git a/misc.c b/misc.c
index 1a2437f..3fe3e94 100644
--- a/misc.c
+++ b/misc.c
@@ -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
diff --git a/umem.c b/umem.c
index 9553417..064db65 100644
--- a/umem.c
+++ b/umem.c
@@ -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