8
0
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:
alexpeshkoff 2009-07-28 11:16:31 +00:00
parent e83e33a0a2
commit ae4855b4b3
2 changed files with 137 additions and 61 deletions

View File

@ -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"

View File

@ -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!