atomic functions moved into separete header; added atomic function InterlockedExchang...
authorVictor Kirhenshtein <victor@netxms.org>
Mon, 18 Sep 2017 13:09:11 +0000 (16:09 +0300)
committerVictor Kirhenshtein <victor@netxms.org>
Mon, 18 Sep 2017 13:09:11 +0000 (16:09 +0300)
configure.ac
include/Makefile.am
include/nms_common.h
include/nms_threads.h
include/nms_util.h
include/nxatomic.h [new file with mode: 0644]
src/libnetxms/solaris9_atomic.c

index 7fdf2d6..8410b7c 100644 (file)
@@ -2317,7 +2317,7 @@ fi
 
 if test "x$PLATFORM" = "xAIX"; then
        AC_CHECK_HEADERS([procinfo.h],,,[[ ]])
-       AC_CHECK_DECLS([getkerninfo, getprocs, getprocs64, __sync_add_and_fetch, __sync_sub_and_fetch],,,[
+       AC_CHECK_DECLS([getkerninfo, getprocs, getprocs64, __sync_add_and_fetch, __sync_sub_and_fetch, __sync_lock_test_and_set],,,[
 #if HAVE_PROCINFO_H
 #include <procinfo.h>
 #endif
@@ -2335,7 +2335,7 @@ fi
 #--------------------------------------------------------------------
 
 if test "x$PLATFORM" = "xSunOS"; then
-       AC_CHECK_FUNCS([atomic_inc_32_nv atomic_dec_32_nv],,,[
+       AC_CHECK_FUNCS([atomic_inc_32_nv atomic_dec_32_nv atomic_swap_ptr],,,[
 #include <sys/atomic.h>
        ])
 fi
index 63cea6d..609b06f 100644 (file)
@@ -29,6 +29,7 @@ include_HEADERS = \
        nms_cscp.h \
        nms_threads.h \
        nms_util.h \
+       nxatomic.h \
        nxcc.h \
        nxcldefs.h \
        nxclient.h \
index 0d64629..783b03f 100644 (file)
@@ -490,14 +490,6 @@ using std::wcsncasecmp;
 #include <pthread.h>
 #endif
 
-#ifdef __sun
-#include <sys/atomic.h>
-#endif
-
-#if defined(__HP_aCC) && HAVE_ATOMIC_H
-#include <atomic.h>
-#endif
-
 #ifdef __IBMCPP__
 #include <builtins.h>
 #endif
index f15fc48..346bd29 100644 (file)
@@ -979,142 +979,6 @@ template <typename T, typename B, typename R> inline void ThreadPoolExecute(Thre
    ThreadPoolExecute(p, __ThreadPoolExecute_Wrapper<B,R>, new __ThreadPoolExecute_WrapperData<B, R>(object, f, arg));
 }
 
-/* Interlocked increment/decrement functions */
-#ifdef _WIN32
-
-typedef volatile LONG VolatileCounter;
-
-#else
-
-#if defined(__sun)
-
-typedef volatile uint32_t VolatileCounter;
-
-#if !HAVE_ATOMIC_INC_32_NV
-extern "C" volatile uint32_t solaris9_atomic_inc32(volatile uint32_t *v);
-#endif
-
-#if !HAVE_ATOMIC_DEC_32_NV
-extern "C" volatile uint32_t solaris9_atomic_dec32(volatile uint32_t *v);
-#endif
-
-/**
- * Atomically increment 32-bit value by 1
- */
-inline VolatileCounter InterlockedIncrement(VolatileCounter *v)
-{
-#if HAVE_ATOMIC_INC_32_NV
-   return atomic_inc_32_nv(v);
-#else
-   return solaris9_atomic_inc32(v);
-#endif
-}
-
-/**
- * Atomically decrement 32-bit value by 1
- */
-inline VolatileCounter InterlockedDecrement(VolatileCounter *v)
-{
-#if HAVE_ATOMIC_DEC_32_NV
-   return atomic_dec_32_nv(v);
-#else
-   return solaris9_atomic_dec32(v);
-#endif
-}
-
-#elif defined(__HP_aCC)
-
-typedef volatile uint32_t VolatileCounter;
-
-#if defined(__hppa) && !HAVE_ATOMIC_H
-VolatileCounter parisc_atomic_inc(VolatileCounter *v);
-VolatileCounter parisc_atomic_dec(VolatileCounter *v);
-#endif
-
-/**
- * Atomically increment 32-bit value by 1
- */
-inline VolatileCounter InterlockedIncrement(VolatileCounter *v)
-{
-#if HAVE_ATOMIC_H
-   return atomic_inc_32(v) + 1;
-#else
-#ifdef __hppa
-   return parisc_atomic_inc(v);
-#else
-   _Asm_mf(_DFLT_FENCE);
-   return (uint32_t)_Asm_fetchadd(_FASZ_W, _SEM_ACQ, (void *)v, +1, _LDHINT_NONE) + 1;
-#endif
-#endif
-}
-
-/**
- * Atomically decrement 32-bit value by 1
- */
-inline VolatileCounter InterlockedDecrement(VolatileCounter *v)
-{
-#if HAVE_ATOMIC_H
-   return atomic_dec_32(v) - 1;
-#else
-#ifdef __hppa
-   return parisc_atomic_inc(v);
-#else
-   _Asm_mf(_DFLT_FENCE);
-   return (uint32_t)_Asm_fetchadd(_FASZ_W, _SEM_ACQ, (void *)v, -1, _LDHINT_NONE) - 1;
-#endif
-#endif
-}
-
-#else /* not Solaris nor HP-UX */
-
-typedef volatile INT32 VolatileCounter;
-
-/**
- * Atomically increment 32-bit value by 1
- */
-inline VolatileCounter InterlockedIncrement(VolatileCounter *v)
-{
-#if (defined(__IBMC__) || defined(__IBMCPP__)) && !HAVE_DECL___SYNC_ADD_AND_FETCH
-   VolatileCounter oldval;
-   do
-   {
-      oldval = __lwarx(v);
-   } while(__stwcx(v, oldval + 1) == 0);
-   return oldval + 1;
-#elif defined(__GNUC__) && ((__GNUC__ < 4) || (__GNUC_MINOR__ < 1)) && (defined(__i386__) || defined(__x86_64__))
-   VolatileCounter temp = 1;
-   __asm__ __volatile__("lock; xaddl %0,%1" : "+r" (temp), "+m" (*v) : : "memory");
-   return temp + 1;
-#else
-   return __sync_add_and_fetch(v, 1);
-#endif
-}
-
-/**
- * Atomically decrement 32-bit value by 1
- */
-inline VolatileCounter InterlockedDecrement(VolatileCounter *v)
-{
-#if (defined(__IBMC__) || defined(__IBMCPP__)) && !HAVE_DECL___SYNC_SUB_AND_FETCH
-   VolatileCounter oldval;
-   do
-   {
-      oldval = __lwarx(v);
-   } while(__stwcx(v, oldval - 1) == 0);
-   return oldval - 1;
-#elif defined(__GNUC__) && ((__GNUC__ < 4) || (__GNUC_MINOR__ < 1)) && (defined(__i386__) || defined(__x86_64__))
-   VolatileCounter temp = -1;
-   __asm__ __volatile__("lock; xaddl %0,%1" : "+r" (temp), "+m" (*v) : : "memory");
-   return temp - 1;
-#else
-   return __sync_sub_and_fetch(v, 1);
-#endif
-}
-
-#endif   /* __sun */
-
-#endif   /* _WIN32 */
-
 /**
  * Wrappers for mutex
  */
index 68476df..bc2c2d3 100644 (file)
@@ -34,6 +34,7 @@
 #endif
 
 #include <nms_common.h>
+#include <nxatomic.h>
 #include <nms_cscp.h>
 #include <nms_threads.h>
 #include <time.h>
diff --git a/include/nxatomic.h b/include/nxatomic.h
new file mode 100644 (file)
index 0000000..6681d43
--- /dev/null
@@ -0,0 +1,251 @@
+/*
+** NetXMS - Network Management System
+** Copyright (C) 2003-2017 Victor Kirhenshtein
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU Lesser General Public License as published
+** by the Free Software Foundation; either version 3 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU Lesser General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+** File: nxatomic.h
+**
+**/
+
+#ifndef _nxatomic_h_
+#define _nxatomic_h_
+
+#include <nms_common.h>
+
+#ifdef __sun
+#include <sys/atomic.h>
+#endif
+
+#if defined(__HP_aCC) && HAVE_ATOMIC_H
+#include <atomic.h>
+#endif
+
+#ifdef _WIN32
+
+typedef volatile LONG VolatileCounter;
+
+#else
+
+#if defined(__sun)
+
+typedef volatile uint32_t VolatileCounter;
+
+#if !HAVE_ATOMIC_INC_32_NV
+extern "C" volatile uint32_t solaris9_atomic_inc32(volatile uint32_t *v);
+#endif
+
+#if !HAVE_ATOMIC_DEC_32_NV
+extern "C" volatile uint32_t solaris9_atomic_dec32(volatile uint32_t *v);
+#endif
+
+#if !HAVE_ATOMIC_SWAP_PTR
+extern "C" void *solaris9_atomic_swap_ptr(volatile *void *target, void *value);
+#endif
+
+/**
+ * Atomically increment 32-bit value by 1
+ */
+inline VolatileCounter InterlockedIncrement(VolatileCounter *v)
+{
+#if HAVE_ATOMIC_INC_32_NV
+   return atomic_inc_32_nv(v);
+#else
+   return solaris9_atomic_inc32(v);
+#endif
+}
+
+/**
+ * Atomically decrement 32-bit value by 1
+ */
+inline VolatileCounter InterlockedDecrement(VolatileCounter *v)
+{
+#if HAVE_ATOMIC_DEC_32_NV
+   return atomic_dec_32_nv(v);
+#else
+   return solaris9_atomic_dec32(v);
+#endif
+}
+
+/**
+ * Atomically set pointer
+ */
+inline void *InterlockedExchangePointer(void *volatile *target, void *value)
+{
+#if HAVE_ATOMIC_SWAP_PTR
+   return atomic_swap_ptr(target, value);
+#else
+   return solaris9_atomic_swap_ptr(target, value);
+#endif
+}
+
+#elif defined(__HP_aCC)
+
+typedef volatile uint32_t VolatileCounter;
+
+#if defined(__hppa) && !HAVE_ATOMIC_H
+VolatileCounter parisc_atomic_inc(VolatileCounter *v);
+VolatileCounter parisc_atomic_dec(VolatileCounter *v);
+#endif
+
+/**
+ * Atomically increment 32-bit value by 1
+ */
+inline VolatileCounter InterlockedIncrement(VolatileCounter *v)
+{
+#if HAVE_ATOMIC_H
+   return atomic_inc_32(v) + 1;
+#else
+#ifdef __hppa
+   return parisc_atomic_inc(v);
+#else
+   _Asm_mf(_DFLT_FENCE);
+   return (uint32_t)_Asm_fetchadd(_FASZ_W, _SEM_ACQ, (void *)v, +1, _LDHINT_NONE) + 1;
+#endif
+#endif
+}
+
+/**
+ * Atomically decrement 32-bit value by 1
+ */
+inline VolatileCounter InterlockedDecrement(VolatileCounter *v)
+{
+#if HAVE_ATOMIC_H
+   return atomic_dec_32(v) - 1;
+#else
+#ifdef __hppa
+   return parisc_atomic_inc(v);
+#else
+   _Asm_mf(_DFLT_FENCE);
+   return (uint32_t)_Asm_fetchadd(_FASZ_W, _SEM_ACQ, (void *)v, -1, _LDHINT_NONE) - 1;
+#endif
+#endif
+}
+
+#elif defined(__IBMC__) || defined(__IBMCPP__)
+
+typedef volatile INT32 VolatileCounter;
+
+/**
+ * Atomically increment 32-bit value by 1
+ */
+inline VolatileCounter InterlockedIncrement(VolatileCounter *v)
+{
+#if !HAVE_DECL___SYNC_ADD_AND_FETCH
+   VolatileCounter oldval;
+   do
+   {
+      oldval = __lwarx(v);
+   } while(__stwcx(v, oldval + 1) == 0);
+   return oldval + 1;
+#else
+   return __sync_add_and_fetch(v, 1);
+#endif
+}
+
+/**
+ * Atomically decrement 32-bit value by 1
+ */
+inline VolatileCounter InterlockedDecrement(VolatileCounter *v)
+{
+#if !HAVE_DECL___SYNC_SUB_AND_FETCH
+   VolatileCounter oldval;
+   do
+   {
+      oldval = __lwarx(v);
+   } while(__stwcx(v, oldval - 1) == 0);
+   return oldval - 1;
+#else
+   return __sync_sub_and_fetch(v, 1);
+#endif
+}
+
+/**
+ * Atomically set pointer
+ */
+inline void *InterlockedExchangePointer(void *volatile *target, void *value)
+{
+   void *oldval;
+   do
+   {
+#ifdef __64BIT__
+      oldval = (void *)__ldarx((long *)target);
+#else
+      oldval = (void *)__lwarx((int *)target);
+#endif
+#ifdef __64BIT__
+   } while(__stdcx((long *)target, (long)value) == 0);
+#else
+   } while(__stwcx((int *)target, (int)value) == 0);
+#endif
+   return oldval;
+}
+
+#else /* not Solaris nor HP-UX nor AIX */
+
+typedef volatile INT32 VolatileCounter;
+
+/**
+ * Atomically increment 32-bit value by 1
+ */
+inline VolatileCounter InterlockedIncrement(VolatileCounter *v)
+{
+#if defined(__GNUC__) && ((__GNUC__ < 4) || (__GNUC_MINOR__ < 1)) && (defined(__i386__) || defined(__x86_64__))
+   VolatileCounter temp = 1;
+   __asm__ __volatile__("lock; xaddl %0,%1" : "+r" (temp), "+m" (*v) : : "memory");
+   return temp + 1;
+#else
+   return __sync_add_and_fetch(v, 1);
+#endif
+}
+
+/**
+ * Atomically decrement 32-bit value by 1
+ */
+inline VolatileCounter InterlockedDecrement(VolatileCounter *v)
+{
+#if defined(__GNUC__) && ((__GNUC__ < 4) || (__GNUC_MINOR__ < 1)) && (defined(__i386__) || defined(__x86_64__))
+   VolatileCounter temp = -1;
+   __asm__ __volatile__("lock; xaddl %0,%1" : "+r" (temp), "+m" (*v) : : "memory");
+   return temp - 1;
+#else
+   return __sync_sub_and_fetch(v, 1);
+#endif
+}
+
+/**
+ * Atomically set pointer
+ */
+inline void *InterlockedExchangePointer(void *volatile *target, void *value)
+{
+#if defined(__GNUC__) && ((__GNUC__ < 4) || (__GNUC_MINOR__ < 1)) && (defined(__i386__) || defined(__x86_64__))
+   void *oldval;
+#ifdef __64BIT__
+   __asm__ __volatile__("xchgq %q2, %1" : "=a" (oldval), "+m" (*target) : "0" (value));
+#else
+   __asm__ __volatile__("xchgl %2, %1" : "=a" (oldval), "+m" (*target) : "0" (value));
+#endif
+   return oldval;
+#else
+   __sync_synchronize();
+   return __sync_lock_test_and_set(target, value);
+#endif
+}
+
+#endif   /* __sun */
+
+#endif   /* _WIN32 */
+
+#endif
index c43be07..5119c5f 100644 (file)
@@ -61,4 +61,21 @@ volatile uint32_t solaris9_atomic_dec32(volatile uint32_t *v)
 
 #endif
 
+#if !HAVE_ATOMIC_SWAP_PTR
+
+void *solaris9_atomic_swap_ptr(volatile *void *target, void *value)
+{
+   volatile void *t;
+   asm(
+      "       ld       [%2], %0;"
+      "1:     cas      [%2], %0, %1;"
+      "       cmp      %0, %1;"
+      "       bne,a,pn %icc,1b;"
+      "       mov      %1, %0;"
+         : "=&r" (value), "=&r" (t) : "r" (target) : "memory");
+   return t;
+}
+
+#endif
+
 #endif /* __sun */