]> granicus.if.org Git - pdns/commitdiff
thanks to RHEL5/CENTOS5.. we now have assembly in PowerDNS. "Thanks". Spotted by...
authorBert Hubert <bert.hubert@netherlabs.nl>
Sat, 11 Sep 2010 14:09:05 +0000 (14:09 +0000)
committerBert Hubert <bert.hubert@netherlabs.nl>
Sat, 11 Sep 2010 14:09:05 +0000 (14:09 +0000)
git-svn-id: svn://svn.powerdns.com/pdns/trunk/pdns@1714 d19b8d6e-7fed-0310-83ef-9ca221ded41b

pdns/misc.hh

index 71c8f63904bf857e06be770764b19b7e3be13da8..7a70bde1727d00852f7343cb18edbbe57deca79a 100644 (file)
@@ -350,19 +350,19 @@ public:
 
     explicit AtomicCounter( unsigned int v = 0) : value_( v ) {}
 
-    void operator++()
+    unsigned int operator++()
     {
-        __sync_add_and_fetch( &value_, 1 );
+      return atomic_exchange_and_add( &value_, +1 ) + 1;
     }
 
     unsigned int operator--()
     {
-        return __sync_add_and_fetch( &value_, -1 );
+      return atomic_exchange_and_add( &value_, -1 ) - 1;
     }
 
     operator unsigned int() const
     {
-        return __sync_fetch_and_add( &value_, 0 );
+      return atomic_exchange_and_add( &value_, 0);
     }
 
 private:
@@ -370,6 +370,34 @@ private:
     AtomicCounter &operator=(AtomicCounter const &);
 
     mutable unsigned int value_;
+    
+    // the below is necessary because __sync_fetch_and_add is not universally available on i386.. I 3> RHEL5. 
+    #if defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) )
+    static int atomic_exchange_and_add( unsigned int * pw, int dv )
+    {
+        // int r = *pw;
+        // *pw += dv;
+        // return r;
+
+        int r;
+
+        __asm__ __volatile__
+        (
+            "lock\n\t"
+            "xadd %1, %0":
+            "+m"( *pw ), "=r"( r ): // outputs (%0, %1)
+            "1"( dv ): // inputs (%2 == %1)
+            "memory", "cc" // clobbers
+        );
+
+        return r;
+    }
+    #else 
+    static int atomic_exchange_and_add( unsigned int * pw, int dv )
+    {
+      return __sync_fetch_and_add(pw, dv);
+    }
+    #endif
 };