mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-02-02 09:20:39 +01:00
Implementation of atomic counter using libatomic_ops. Useful at least for s390/linux.
This commit is contained in:
parent
e83e33a0a2
commit
ae4855b4b3
@ -562,6 +562,7 @@ AC_CHECK_HEADERS(sys/sem.h)
|
||||
AC_CHECK_HEADERS(semaphore.h)
|
||||
AC_CHECK_HEADERS(float.h)
|
||||
AC_CHECK_HEADERS(atomic.h)
|
||||
AC_CHECK_HEADERS(atomic_ops.h)
|
||||
|
||||
dnl Check for libraries
|
||||
AC_CHECK_LIB(dl, main)
|
||||
@ -579,6 +580,7 @@ if test "$RT_LIB_CHECK" = "true"; then
|
||||
AC_CHECK_LIB(rt, main)
|
||||
AC_CHECK_LIB(resolv, inet_aton)
|
||||
fi
|
||||
AC_CHECK_LIB(atomic_ops, main)
|
||||
|
||||
dnl Check for libraries for static C++ runtime linking
|
||||
AC_CHECK_LIB(supc++, main, XE_APPEND(-lsupc++, STATIC_CXXSUPPORT_LIB))
|
||||
@ -675,6 +677,10 @@ AC_CHECK_FUNCS(fchmod)
|
||||
AC_CHECK_FUNCS(semtimedop)
|
||||
AC_CHECK_FUNCS(fegetenv)
|
||||
AC_CHECK_FUNCS(strerror_r)
|
||||
dnl AC_CHECK_FUNCS(AO_compare_and_swap_full)
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_PROGRAM([[#include <atomic_ops.h>]], [[AO_T x; AO_compare_and_swap_full(&x, 0, 0); return 0;]])],
|
||||
AC_DEFINE(HAVE_AO_COMPARE_AND_SWAP_FULL, 1, [Define this if AO_compare_and_swap_full() is defined in atomic_ops.h]))
|
||||
|
||||
# Checks for pthread functions
|
||||
savedFlags="$CFLAGS"
|
||||
|
@ -86,67 +86,6 @@ private:
|
||||
|
||||
} // namespace Firebird
|
||||
|
||||
#elif defined(__GNUC__) && (defined(i386) || defined(I386) || defined(_M_IX86) || defined(AMD64) || defined(__x86_64__))
|
||||
|
||||
namespace Firebird {
|
||||
|
||||
// Assembler version for x86 and AMD64. Note it uses xaddl thus it requires i486
|
||||
class AtomicCounter
|
||||
{
|
||||
public:
|
||||
typedef int counter_type;
|
||||
|
||||
explicit AtomicCounter(counter_type value = 0) : counter(value) {}
|
||||
~AtomicCounter() {}
|
||||
|
||||
counter_type exchangeAdd(counter_type value)
|
||||
{
|
||||
register counter_type result;
|
||||
__asm __volatile (
|
||||
"lock; xaddl %0, %1"
|
||||
: "=r" (result), "=m" (counter)
|
||||
: "0" (value), "m" (counter));
|
||||
return result;
|
||||
}
|
||||
|
||||
counter_type operator +=(counter_type value)
|
||||
{
|
||||
return exchangeAdd(value) + value;
|
||||
}
|
||||
|
||||
counter_type operator -=(counter_type value)
|
||||
{
|
||||
return exchangeAdd(-value) - value;
|
||||
}
|
||||
|
||||
counter_type operator ++()
|
||||
{
|
||||
return exchangeAdd(1) + 1;
|
||||
}
|
||||
|
||||
counter_type operator --()
|
||||
{
|
||||
return exchangeAdd(-1) - 1;
|
||||
}
|
||||
|
||||
counter_type value() const { return counter; }
|
||||
|
||||
counter_type setValue(counter_type val)
|
||||
{
|
||||
register counter_type result;
|
||||
__asm __volatile (
|
||||
"lock; xchg %0, %1"
|
||||
: "=r" (result), "=m" (counter)
|
||||
: "0" (val), "m" (counter));
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
volatile counter_type counter;
|
||||
};
|
||||
|
||||
} // namespace Firebird
|
||||
|
||||
#elif defined(AIX)
|
||||
|
||||
#include <sys/atomic_op.h>
|
||||
@ -388,6 +327,137 @@ private:
|
||||
|
||||
} // namespace Firebird
|
||||
|
||||
#elif defined(__GNUC__) && (defined(i386) || defined(I386) || defined(_M_IX86) || defined(AMD64) || defined(__x86_64__))
|
||||
|
||||
namespace Firebird {
|
||||
|
||||
// Assembler version for x86 and AMD64. Note it uses xaddl thus it requires i486
|
||||
class AtomicCounter
|
||||
{
|
||||
public:
|
||||
typedef int counter_type;
|
||||
|
||||
explicit AtomicCounter(counter_type value = 0) : counter(value) {}
|
||||
~AtomicCounter() {}
|
||||
|
||||
counter_type exchangeAdd(counter_type value)
|
||||
{
|
||||
register counter_type result;
|
||||
__asm __volatile (
|
||||
"lock; xaddl %0, %1"
|
||||
: "=r" (result), "=m" (counter)
|
||||
: "0" (value), "m" (counter));
|
||||
return result;
|
||||
}
|
||||
|
||||
counter_type operator +=(counter_type value)
|
||||
{
|
||||
return exchangeAdd(value) + value;
|
||||
}
|
||||
|
||||
counter_type operator -=(counter_type value)
|
||||
{
|
||||
return exchangeAdd(-value) - value;
|
||||
}
|
||||
|
||||
counter_type operator ++()
|
||||
{
|
||||
return exchangeAdd(1) + 1;
|
||||
}
|
||||
|
||||
counter_type operator --()
|
||||
{
|
||||
return exchangeAdd(-1) - 1;
|
||||
}
|
||||
|
||||
counter_type value() const { return counter; }
|
||||
|
||||
counter_type setValue(counter_type val)
|
||||
{
|
||||
register counter_type result;
|
||||
__asm __volatile (
|
||||
"lock; xchg %0, %1"
|
||||
: "=r" (result), "=m" (counter)
|
||||
: "0" (val), "m" (counter));
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
volatile counter_type counter;
|
||||
};
|
||||
|
||||
} // namespace Firebird
|
||||
|
||||
#elif defined(HAVE_AO_COMPARE_AND_SWAP_FULL)
|
||||
|
||||
// Sometimes in the future it can become the best choice for all platforms.
|
||||
// Currently far not CPUs/OSs/compilers are supported well.
|
||||
// Therefore use it as lsct chance to build successfully.
|
||||
|
||||
#include <atomic_ops.h>
|
||||
|
||||
namespace Firebird {
|
||||
|
||||
class AtomicCounter
|
||||
{
|
||||
public:
|
||||
typedef AO_t counter_type;
|
||||
|
||||
explicit AtomicCounter(counter_type value = 0) : counter(value) {}
|
||||
~AtomicCounter() {}
|
||||
|
||||
/* counter_type exchangeAdd(counter_type value)
|
||||
{
|
||||
return AO_fetch_and_add_full(&counter, value);
|
||||
} */
|
||||
counter_type exchangeAdd(counter_type value)
|
||||
{
|
||||
counter_type old;
|
||||
do
|
||||
{
|
||||
old = counter;
|
||||
} while (!AO_compare_and_swap_full(&counter, old, old + value));
|
||||
return old;
|
||||
}
|
||||
|
||||
counter_type operator +=(counter_type value)
|
||||
{
|
||||
return exchangeAdd(value) + value;
|
||||
}
|
||||
|
||||
counter_type operator -=(counter_type value)
|
||||
{
|
||||
return exchangeAdd(-value) - value;
|
||||
}
|
||||
|
||||
counter_type operator ++()
|
||||
{
|
||||
return exchangeAdd(1) + 1;
|
||||
}
|
||||
|
||||
counter_type operator --()
|
||||
{
|
||||
return exchangeAdd(-1) - 1;
|
||||
}
|
||||
|
||||
counter_type value() const { return counter; }
|
||||
|
||||
counter_type setValue(counter_type val)
|
||||
{
|
||||
counter_type old;
|
||||
do
|
||||
{
|
||||
old = counter;
|
||||
} while (!AO_compare_and_swap_full(&counter, old, val));
|
||||
return old;
|
||||
}
|
||||
|
||||
private:
|
||||
counter_type counter;
|
||||
};
|
||||
|
||||
} // namespace Firebird
|
||||
|
||||
#else
|
||||
|
||||
#error AtomicCounter: implement appropriate code for your platform!
|
||||
|
Loading…
Reference in New Issue
Block a user