I'm trying to run an app for android for 64 bits processors using c++ (native) and when I'm executing these functions I'm getting crash issues (Bus Error)
// returns the resulting incremented value
#define InterlockedIncrement(pInt) __sync_add_and_fetch(pInt, 1)
// returns the resulting decremented value
#define InterlockedDecrement(pInt) __sync_sub_and_fetch(pInt, 1)
// returns the initial value
#define InterlockedExchangeAdd(pInt,nAdd) __sync_fetch_and_add(pInt,nAdd)
// returns the initial value of the pInt parameter.
#define InterlockedCompareExchange(pInt,nValue,nOldValue) __sync_val_compare_and_swap(pInt,nOldValue,nValue)
I read some information about these function and it seems only work for 32 bits processors
I tried to change the call in this way
#include <atomic>
#include <iostream>
inline BOOL InterlockedCompareExchange(volatile INT* pInt, INT nValue, INT nOldValue)
{
std::atomic<INT> ai;
ai = *pInt;
return ai.compare_exchange_strong(nOldValue, nValue,
std::memory_order_release,
std::memory_order_relaxed);
}
inline LONG InterlockedExchange(volatile LONG* pInt, LONG nValue)
{
std::atomic<LONG> ai;
LONG nOldValue;
ai = *pInt;
nOldValue = *pInt;
while (!ai.compare_exchange_strong(nOldValue, nValue,
std::memory_order_release,
std::memory_order_relaxed));
*pInt = nValue;
return nValue;
}
inline LONG InterlockedIncrement(volatile LONG* pInt)
{
std::atomic<LONG> ai;
ai = *pInt;
ai.fetch_add(1, std::memory_order_relaxed);
*pInt = ai;
return ai;
}
inline LONG InterlockedDecrement(volatile LONG* pInt)
{
std::atomic<LONG> ai;
ai = *pInt;
ai.fetch_sub(1, std::memory_order_relaxed);
if (ai < 0)
ai = 0;
*pInt = ai;
return ai;
}
inline LONG InterlockedExchangeAdd(volatile LONG* pInt, LONG nValue)
{
std::atomic<LONG> ai;
ai = *pInt;
ai.fetch_add(nValue, std::memory_order_relaxed);
if (ai < 0)
ai = 0;
*pInt = ai;
return ai;
}
Now I'm getting some errors in the references and weird behavior in my app even if I'm getting the same values using my new functions, any idea?
On some platforms, and I'd guess this is the case on arm, bus error often means that you have an unaligned access (in your case, one of your atomic 32-bit or 64-bit integer variables not aligned on a 4 or 8 byte boundary respectively.)
For example, here is explicitly unaligned atomic access:
#include <atomic>
#include <string.h>
int main()
{
char buf[16];
memset( buf, 0, sizeof(buf) );
std::atomic<int> * pi = (std::atomic<int> *)(((intptr_t)buf & ~3) + 5);
pi->fetch_add(1);
return 0;
}
Even if code like this appears to work (i.e. doesn't trap with SIGBUS or SIGSEGV) such an unaligned atomic will not behave in the expected fashion if it is accessed concurrently by different threads.