blob: 54af031a31bc901622e997f336f11066bbb8554b [file] [log] [blame]
/*=========================================================================
* Copyright (c) 2010-2014 Pivotal Software, Inc. All Rights Reserved.
* This product is protected by U.S. and international copyright
* and intellectual property laws. Pivotal products are covered by
* one or more patents listed at http://www.pivotal.io/patents.
*=========================================================================
*/
#include "HostAsm.hpp"
#include <ace/Atomic_Op_T.h>
#include <ace/Recursive_Thread_Mutex.h>
using namespace gemfire;
int32_t HostAsm::m_SpinCount = 0;
// TODO jbarrett - why do we have our own atomic methods? why not use ACE?
#if defined(_LINUX) || defined(_X86_SOLARIS)
typedef long LONG;
inline uint32_t InterlockedCompareExchange(volatile LONG *dest,
uint32_t exch, uint32_t comp)
{
#if defined(_LINUX)
uint32_t old;
__asm__ __volatile__ ("lock; cmpxchgl %2, %0"
: "=m" (*dest), "=a" (old)
: "r" (exch), "m" (*dest), "a" (comp));
return(old);
#endif
#if defined(_X86_SOLARIS)
uint32_t old;
old = atomic_cas_32((volatile uint32_t *)dest, comp, exch);
return (old);
#endif
}
#endif
#ifdef _SPARC_SOLARIS
typedef long LONG;
extern "C" {
int32_t InterlockedCompareExchange(volatile LONG*, int32_t, int32_t);
}
#endif
void HostAsm::atomicAnd(volatile uint32_t& ctr, uint32_t mask)
{
#if defined(_MACOSX)
OSAtomicAnd32Barrier(mask, &ctr);
#else
bool success = false;
while( ! success ) {
uint32_t oldValue = ctr;
uint32_t newValue = oldValue & mask;
volatile LONG *signedctr = (volatile LONG*) &ctr;
if ( InterlockedCompareExchange( signedctr, newValue, oldValue ) == oldValue ) {
return;
}
}
#endif
}
//if return value is same as valuetoCompare that means you succeed, otherwise some other thread change this value
uint32_t HostAsm::atomicCompareAndExchange(volatile uint32_t& oldValue, uint32_t newValue, uint32_t valueToCompare)
{
#if defined(_MACOSX)
if (OSAtomicCompareAndSwap32Barrier(valueToCompare, newValue, (volatile int32_t *) &oldValue)) {
return valueToCompare;
} else {
return oldValue;
}
#else
volatile LONG *signedctr = (volatile LONG*) &oldValue;
uint32_t retVal = InterlockedCompareExchange( signedctr, newValue, valueToCompare );
return retVal;
#endif
}
void HostAsm::atomicOr(volatile uint32_t& ctr, uint32_t mask)
{
#if defined(_MACOSX)
OSAtomicOr32Barrier(mask, &ctr);
#else
bool success = false;
while( ! success ) {
uint32_t oldValue = ctr;
uint32_t newValue = oldValue | mask;
volatile LONG* signedctr = (volatile LONG*) &ctr;
if ( InterlockedCompareExchange( signedctr, newValue, oldValue ) == oldValue ) {
return;
}
}
#endif
}
void HostAsm::atomicSet(volatile uint32_t& data, uint32_t newValue)
{
// TODO MACOSX this entire function makes no sense unless it is just to force memory barriers
#if defined(_MACOSX)
uint32_t oldValue;
do {
oldValue = data;
} while(!OSAtomicCompareAndSwap32Barrier(oldValue, newValue, (volatile int32_t *) &data));
#else
bool success = false;
while (!success) {
uint32_t oldValue = data;
volatile LONG* longData = (volatile LONG*)&data;
if (InterlockedCompareExchange(longData, newValue, oldValue) == oldValue) {
return;
}
}
#endif
}