implement atomicCompareAndSwap on x86_32 for GCC versions prior to 4.1 and for MSVC

This commit is contained in:
Joel Dice 2009-11-20 10:40:01 -07:00
parent e91157a390
commit 15eada93ed
5 changed files with 59 additions and 16 deletions

View File

@ -101,7 +101,7 @@ warnings = -Wall -Wextra -Werror -Wunused-parameter -Winit-self \
common-cflags = $(warnings) -fno-rtti -fno-exceptions -fno-omit-frame-pointer \ common-cflags = $(warnings) -fno-rtti -fno-exceptions -fno-omit-frame-pointer \
"-I$(JAVA_HOME)/include" -idirafter $(src) -I$(native-build) \ "-I$(JAVA_HOME)/include" -idirafter $(src) -I$(native-build) \
-D__STDC_LIMIT_MACROS -D_JNI_IMPLEMENTATION_ -DAVIAN_VERSION=\"$(version)\" \ -D__STDC_LIMIT_MACROS -D_JNI_IMPLEMENTATION_ -DAVIAN_VERSION=\"$(version)\" \
$(gnu-cflags) -DUSE_ATOMIC_OPERATIONS $(gnu-cflags)
build-cflags = $(common-cflags) -fPIC -fvisibility=hidden \ build-cflags = $(common-cflags) -fPIC -fvisibility=hidden \
"-I$(JAVA_HOME)/include/linux" -I$(src) -pthread "-I$(JAVA_HOME)/include/linux" -I$(src) -pthread

View File

@ -63,11 +63,6 @@ typedef uint64_t uintptr_t;
# include "stdint.h" # include "stdint.h"
# if (__GNUC__ >= 4) && (__GNUC_MINOR__ >= 1)
# define USE_ATOMIC_OPERATIONS
# define COMPARE_AND_SWAP __sync_bool_compare_and_swap
# endif
# define LIKELY(v) __builtin_expect((v) != 0, true) # define LIKELY(v) __builtin_expect((v) != 0, true)
# define UNLIKELY(v) __builtin_expect((v) != 0, false) # define UNLIKELY(v) __builtin_expect((v) != 0, false)
@ -330,16 +325,6 @@ markBit(uintptr_t* map, unsigned i)
map[wordOf(i)] |= static_cast<uintptr_t>(1) << bitOf(i); map[wordOf(i)] |= static_cast<uintptr_t>(1) << bitOf(i);
} }
#ifdef USE_ATOMIC_OPERATIONS
inline void
markBitAtomic(uintptr_t* map, unsigned i)
{
uintptr_t* p = map + wordOf(i);
uintptr_t v = static_cast<uintptr_t>(1) << bitOf(i);
while (not COMPARE_AND_SWAP(p, *p, *p | v)) { }
}
#endif
inline void inline void
clearBit(uintptr_t* map, unsigned i) clearBit(uintptr_t* map, unsigned i)
{ {

View File

@ -11,6 +11,7 @@
#include "heap.h" #include "heap.h"
#include "system.h" #include "system.h"
#include "common.h" #include "common.h"
#include "arch.h"
using namespace vm; using namespace vm;
@ -69,6 +70,16 @@ System* system(Context*);
void* tryAllocate(Context* c, unsigned size); void* tryAllocate(Context* c, unsigned size);
void free(Context* c, const void* p, unsigned size); void free(Context* c, const void* p, unsigned size);
#ifdef USE_ATOMIC_OPERATIONS
inline void
markBitAtomic(uintptr_t* map, unsigned i)
{
uintptr_t* p = map + wordOf(i);
uintptr_t v = static_cast<uintptr_t>(1) << bitOf(i);
while (not atomicCompareAndSwap(p, *p, *p | v)) { }
}
#endif // USE_ATOMIC_OPERATIONS
inline void* inline void*
get(void* o, unsigned offsetInWords) get(void* o, unsigned offsetInWords)
{ {

View File

@ -90,6 +90,19 @@ syncInstructionCache(const void* start, unsigned size)
__asm__ __volatile__("isync"); __asm__ __volatile__("isync");
} }
#ifdef USE_ATOMIC_OPERATIONS
inline bool
atomicCompareAndSwap(uintptr_t* p, uintptr_t old, uintptr_t new_)
{
#if (__GNUC__ >= 4) && (__GNUC_MINOR__ >= 1)
return __sync_bool_compare_and_swap(p, old, new_);
#else // not GCC >= 4.1
// todo: implement using inline assembly
# undef USE_ATOMIC_OPERATIONS
#endif // not GCC >= 4.1
}
#endif // USE_ATOMIC_OPERATIONS
inline uint64_t inline uint64_t
dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes, dynamicCall(void* function, uintptr_t* arguments, uint8_t* argumentTypes,
unsigned argumentCount, unsigned argumentsSize, unsigned argumentCount, unsigned argumentsSize,

View File

@ -188,6 +188,40 @@ syncInstructionCache(const void*, unsigned)
// ignore // ignore
} }
#ifdef USE_ATOMIC_OPERATIONS
inline bool
atomicCompareAndSwap(uintptr_t* p, uintptr_t old, uintptr_t new_)
{
#ifdef _MSC_VER
# ifdef ARCH_x86_32
InterlockedCompareExchange(p, new_, old);
# elif defined ARCH_x86_64
InterlockedCompareExchange64(p, new_, old);
# endif // ARCH_x86_64
#elif (__GNUC__ >= 4) && (__GNUC_MINOR__ >= 1)
return __sync_bool_compare_and_swap(p, old, new_);
#elif defined ARCH_x86_32
uint8_t result;
__asm__ __volatile__("lock; cmpxchgl %2, %0; setz %1"
: "=m"(*p), "=q"(result)
: "r"(new_), "a"(old), "m"(*p)
: "memory");
return result != 0;
#elif defined ARCH_x86_64
uint8_t result;
__asm__ __volatile__("lock; cmpxchg1 %2, %0; setz %1"
: "=m"(*p), "=q"(result)
: "r"(new_), "a"(old), "m"(*p)
: "memory");
return result != 0;
#endif // ARCH_x86_64
}
#endif // USE_ATOMIC_OPERATIONS
} // namespace vm } // namespace vm
#endif//X86_H #endif//X86_H