Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

[libcmyth/refmem] Pull across upstream changes to support other archi…

…tectures.
  • Loading branch information...
commit 09e173e18b17f945b83220cb18800f3f4a0b93d7 1 parent beb2664
David Teirney authored
View
96 lib/cmyth/include/refmem/atomic.h
@@ -24,15 +24,30 @@
#pragma GCC optimization_level 0
#endif
-#ifdef _MSC_VER
+#if defined(_MSC_VER)
#include <windows.h>
+#define inline __inline
#endif
+
+#if defined __mips__
+#include <atomic.h>
+#endif
+
+#if defined(__APPLE__)
+#include <libkern/OSAtomic.h>
+
+typedef volatile int32_t mvp_atomic_t;
+
+#define __mvp_atomic_increment(x) OSAtomicIncrement32(x)
+#define __mvp_atomic_decrement(x) OSAtomicDecrement32(x)
+#else
+typedef volatile unsigned int mvp_atomic_t;
+
/**
* Atomically incremente a reference count variable.
* \param valp address of atomic variable
* \return incremented reference count
*/
-typedef unsigned mvp_atomic_t;
static inline unsigned
__mvp_atomic_increment(mvp_atomic_t *valp)
{
@@ -45,8 +60,8 @@ __mvp_atomic_increment(mvp_atomic_t *valp)
: "r" (valp), "0" (0x1)
: "cc", "memory"
);
-#elif defined __i386__
- asm volatile (".byte 0xf0, 0x0f, 0xc1, 0x02" /*lock; xaddl %eax, (%edx) */
+#elif defined __i386__ || defined __x86_64__
+ __asm__ volatile (".byte 0xf0, 0x0f, 0xc1, 0x02" /*lock; xaddl %eax, (%edx) */
: "=a" (__val)
: "0" (1), "m" (*valp), "d" (valp)
: "memory");
@@ -63,16 +78,35 @@ __mvp_atomic_increment(mvp_atomic_t *valp)
: "r" (valp)
: "cc", "memory");
#elif defined _MSC_VER
- __val = InterlockedIncrement(valp);
-#else
+ __val = InterlockedIncrement(valp);
+#elif defined ANDROID
+ __val = __atomic_inc(valp) + 1;
+#elif defined __arm__ && !defined __thumb__
+ int tmp1, tmp2;
+ int inc = 1;
+ __asm__ __volatile__ (
+ "\n"
+ "0:"
+ "ldr %0, [%3]\n"
+ "add %1, %0, %4\n"
+ "swp %2, %1, [%3]\n"
+ "cmp %0, %2\n"
+ "swpne %0, %2, [%3]\n"
+ "bne 0b\n"
+ : "=&r"(tmp1), "=&r"(__val), "=&r"(tmp2)
+ : "r" (valp), "r"(inc)
+ : "cc", "memory");
+#elif defined __mips__
+ __val = atomic_increment_val(valp);
+#elif defined __GNUC__
/*
* Don't know how to atomic increment for a generic architecture
- * so punt and just increment the value.
+ * so try to use GCC builtin
*/
-#ifdef _WIN32
- #pragma message("unknown architecture, atomic increment is not...");
+ __val = __sync_add_and_fetch(valp,1);
#else
- #warning unknown architecture, atomic increment is not...
+#if !defined(_MSC_VER)
+#warning unknown architecture, atomic increment is not...
#endif
__val = ++(*valp);
#endif
@@ -96,8 +130,8 @@ __mvp_atomic_decrement(mvp_atomic_t *valp)
: "r" (valp), "0" (0x1)
: "cc", "memory"
);
-#elif defined __i386__
- asm volatile (".byte 0xf0, 0x0f, 0xc1, 0x02" /*lock; xaddl %eax, (%edx) */
+#elif defined __i386__ || defined __x86_64__
+ __asm__ volatile (".byte 0xf0, 0x0f, 0xc1, 0x02" /*lock; xaddl %eax, (%edx) */
: "=a" (__val)
: "0" (-1), "m" (*valp), "d" (valp)
: "memory");
@@ -113,6 +147,25 @@ __mvp_atomic_decrement(mvp_atomic_t *valp)
: "=&r" (__val)
: "r" (valp)
: "cc", "memory");
+#elif defined ANDROID
+ __val = __atomic_dec(valp) - 1;
+#elif defined __arm__ && !defined __thumb__
+ int tmp1, tmp2;
+ int inc = -1;
+ __asm__ __volatile__ (
+ "\n"
+ "0:"
+ "ldr %0, [%3]\n"
+ "add %1, %0, %4\n"
+ "swp %2, %1, [%3]\n"
+ "cmp %0, %2\n"
+ "swpne %0, %2, [%3]\n"
+ "bne 0b\n"
+ : "=&r"(tmp1), "=&r"(__val), "=&r"(tmp2)
+ : "r" (valp), "r"(inc)
+ : "cc", "memory");
+#elif defined __mips__
+ __val = atomic_decrement_val(valp);
#elif defined __sparcv9__
mvp_atomic_t __newval, __oldval = (*valp);
do
@@ -126,17 +179,23 @@ __mvp_atomic_decrement(mvp_atomic_t *valp)
/* The value for __val is in '__oldval' */
__val = __oldval;
#elif defined _MSC_VER
- __val = InterlockedDecrement(valp);
-#else
+ __val = InterlockedDecrement(valp);
+#elif defined __GNUC__
/*
* Don't know how to atomic decrement for a generic architecture
- * so punt and just decrement the value.
+ * so use GCC builtin
*/
-//#warning unknown architecture, atomic decrement is not...
+ __val = __sync_sub_and_fetch(valp,1);
+#else
+#if !defined(_MSC_VER)
+#warning unknown architecture, atomic deccrement is not...
+#endif
__val = --(*valp);
#endif
return __val;
}
+#endif
+
#define mvp_atomic_inc __mvp_atomic_inc
static inline int mvp_atomic_inc(mvp_atomic_t *a) {
return __mvp_atomic_increment(a);
@@ -157,6 +216,11 @@ static inline void mvp_atomic_set(mvp_atomic_t *a, unsigned val) {
*a = val;
};
+#define mvp_atomic_val __mvp_atomic_val
+static inline int mvp_atomic_val(mvp_atomic_t *a) {
+ return *a;
+};
+
#ifdef __APPLE__
#pragma GCC optimization_level reset
#endif
View
32 lib/cmyth/include/refmem/refmem.h
@@ -24,12 +24,17 @@
#ifndef __REFMEM_H
#define __REFMEM_H
+#include "atomic.h"
+
/*
* -----------------------------------------------------------------
* Types
* -----------------------------------------------------------------
*/
+/* Return current number of references outstanding for everything */
+extern int ref_get_refcount();
+
/**
* Release a reference to allocated memory.
* \param p allocated memory
@@ -95,4 +100,31 @@ extern void ref_set_destroy(void *block, ref_destroy_t func);
*/
extern void ref_alloc_show(void);
+/*
+ * Debug level constants used to determine the level of debug tracing
+ * to be done and the debug level of any given message.
+ */
+
+#define REF_DBG_NONE -1
+#define REF_DBG_ERRORS 0
+#define REF_DBG_COUNTERS 1
+#define REF_DBG_DEBUG 2
+#define REF_DBG_ALL 3
+
+/**
+ * Set librefmem debug level.
+ * \param l debugging level (-1 for none, 3 for all)
+ */
+void refmem_dbg_level(int l);
+
+/**
+ * Enable all librefmem debugging.
+ */
+void refmem_dbg_all();
+
+/**
+ * Disable all librefmem debugging.
+ */
+void refmem_dbg_none();
+
#endif /* __REFMEM_H */
View
84 lib/cmyth/librefmem/alloc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2006, Eric Lund, Jon Gettler
+ * Copyright (C) 2005-2010, Eric Lund, Jon Gettler
* http://www.mvpmc.org/
*
* This library is free software; you can redistribute it and/or
@@ -40,9 +40,6 @@
*/
#include <sys/types.h>
#include <stdlib.h>
-#ifndef _MSC_VER
-#include <unistd.h>
-#endif
#include <errno.h>
#include <refmem/refmem.h>
#include <refmem/atomic.h>
@@ -52,9 +49,14 @@
#include <stdio.h>
#ifdef DEBUG
+#include <inttypes.h>
#include <assert.h>
#define ALLOC_MAGIC 0xef37a45d
#define GUARD_MAGIC 0xe3
+#define GUARD_BYTES 1
+#if defined(ANDROID)
+#include <android/log.h>
+#endif
#endif /* DEBUG */
/* Disable optimization on OSX ppc
@@ -63,6 +65,8 @@
#pragma GCC optimization_level 0
#endif
+static mvp_atomic_t total_refcount = 0;
+static mvp_atomic_t total_bytecount = 0;
/*
* struct refcounter
*
@@ -98,7 +102,7 @@ typedef struct refcounter {
#ifdef DEBUG
typedef struct {
- unsigned char magic;
+ unsigned char magic[GUARD_BYTES];
} guard_t;
#endif /* DEBUG */
@@ -110,6 +114,32 @@ typedef struct {
static refcounter_t *ref_list[REF_ALLOC_BINS];
#endif /* DEBUG */
+#ifdef DEBUG
+static inline void
+guard_set(guard_t *guard, unsigned char val)
+{
+ memset(&(guard->magic[0]), val, GUARD_BYTES);
+}
+
+static inline void
+guard_check(guard_t *guard)
+{
+ int i;
+
+ for (i=0; i<GUARD_BYTES; i++) {
+ assert(guard->magic[i] == GUARD_MAGIC);
+ }
+}
+#endif /* DEBUG */
+
+int ref_get_refcount(char *loc)
+{
+ refmem_dbg(REF_DBG_COUNTERS,
+ "%40.40s Refs: %7d Bytes: %8d\n",
+ loc,total_refcount,total_bytecount);
+ return(total_refcount);
+}
+
#if defined(DEBUG)
static inline void
ref_remove(refcounter_t *ref)
@@ -186,6 +216,21 @@ ref_alloc_show(void)
}
}
+#if defined(ANDROID)
+ {
+ char buf[512];
+
+ snprintf(buf, sizeof(buf),
+ "refmem allocation count: %d\n", count);
+ __android_log_print(ANDROID_LOG_DEBUG, "refmem", buf);
+ snprintf(buf, sizeof(buf),
+ "refmem allocation bytes: %d\n", bytes);
+ __android_log_print(ANDROID_LOG_DEBUG, "refmem", buf);
+ snprintf(buf, sizeof(buf),
+ "refmem unique allocation types: %d\n", types);
+ __android_log_print(ANDROID_LOG_DEBUG, "refmem", buf);
+ }
+#else
printf("refmem allocation count: %d\n", count);
printf("refmem allocation bytes: %d\n", bytes);
printf("refmem unique allocation types: %d\n", types);
@@ -194,6 +239,7 @@ ref_alloc_show(void)
alloc_list[i].file, alloc_list[i].func,
alloc_list[i].line, alloc_list[i].count);
}
+#endif
}
#else
void
@@ -236,6 +282,9 @@ __ref_alloc(size_t len, const char *file, const char *func, int line)
if (block) {
memset(block, 0, sizeof(refcounter_t) + len);
mvp_atomic_set(&ref->refcount, 1);
+ mvp_atomic_inc(&total_refcount);
+ total_bytecount += sizeof(refcounter_t) + len;
+
#ifdef DEBUG
ref->magic = ALLOC_MAGIC;
ref->file = file;
@@ -243,7 +292,7 @@ __ref_alloc(size_t len, const char *file, const char *func, int line)
ref->line = line;
guard = (guard_t*)((uintptr_t)block +
sizeof(refcounter_t) + len);
- guard->magic = GUARD_MAGIC;
+ guard_set(guard, GUARD_MAGIC);
ref_add(ref);
#endif /* DEBUG */
ref->destroy = NULL;
@@ -409,9 +458,10 @@ ref_hold(void *p)
assert(ref->magic == ALLOC_MAGIC);
guard = (guard_t*)((uintptr_t)block +
sizeof(refcounter_t) + ref->length);
- assert(guard->magic == GUARD_MAGIC);
+ guard_check(guard);
#endif /* DEBUG */
mvp_atomic_inc(&ref->refcount);
+ mvp_atomic_inc(&total_refcount);
}
refmem_dbg(REF_DBG_DEBUG, "%s(%p) }\n", __FUNCTION__, p);
return p;
@@ -441,6 +491,7 @@ ref_release(void *p)
#ifdef DEBUG
guard_t *guard;
#endif /* DEBUG */
+ int refcount;
refmem_dbg(REF_DBG_DEBUG, "%s(%p) {\n", __FUNCTION__, p);
if (p) {
@@ -452,8 +503,14 @@ ref_release(void *p)
assert(ref->magic == ALLOC_MAGIC);
guard = (guard_t*)((uintptr_t)block +
sizeof(refcounter_t) + ref->length);
- assert(guard->magic == GUARD_MAGIC);
+ guard_check(guard);
#endif /* DEBUG */
+
+ /* Remove a refcount */
+ mvp_atomic_dec(&total_refcount);
+
+ refcount = ((int)ref->refcount) - 1;
+
if (mvp_atomic_dec_and_test(&ref->refcount)) {
/*
* Last reference, destroy the structure (if
@@ -468,14 +525,17 @@ ref_release(void *p)
__FILE__, __LINE__, __FUNCTION__);
#ifdef DEBUG
ref->magic = 0;
- guard->magic = 0;
-#ifndef _WIN32
- refmem_ref_remove(ref);
-#endif
+ guard_set(guard, 0);
+ ref_remove(ref);
ref->next = NULL;
#endif /* DEBUG */
+ /* Remove its bytes */
+ total_bytecount -= ( sizeof(refcounter_t) + ref->length);
free(block);
}
+ if (refcount < 0)
+ fprintf(stderr, "*** %s(): %p refcount %d ***\n",
+ __FUNCTION__, p, ref->refcount);
}
refmem_dbg(REF_DBG_DEBUG, "%s(%p) }\n", __FUNCTION__, p);
}
View
33 lib/cmyth/librefmem/refmem_local.h
@@ -1,20 +1,25 @@
-#ifndef __REFMEM_LOCAL_H
-#define __REFMEM_LOCAL_H
-
/*
- * Debug level constants used to determine the level of debug tracing
- * to be done and the debug level of any given message.
+ * Copyright (C) 2004-2012, Eric Lund, Jon Gettler
+ * http://www.mvpmc.org/
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#define REF_DBG_NONE -1
-#define REF_DBG_DEBUG 0
-#define REF_DBG_ALL 0
-
-void refmem_dbg_level(int l);
-
-void refmem_dbg_all();
-
-void refmem_dbg_none();
+#ifndef __REFMEM_LOCAL_H
+#define __REFMEM_LOCAL_H
void refmem_dbg(int level, char *fmt, ...);
+
#endif /* __REFMEM_LOCAL_H */
Please sign in to comment.
Something went wrong with that request. Please try again.