Sophie

Sophie

distrib > Fedora > 14 > i386 > by-pkgid > 57315bb5f4056a496a54c5914b9130ad > files > 2

crystalspace-1.2.1-8.fc14.src.rpm

--- crystalspace-src-1.2/include/csutil/threading/atomicops_gcc_ppc.h~	2007-10-04 12:25:05.000000000 +0100
+++ crystalspace-src-1.2/include/csutil/threading/atomicops_gcc_ppc.h	2008-06-13 10:53:34.000000000 +0100
@@ -47,7 +47,23 @@ namespace Threading
 
     inline static void* Set (void** target, void* value)
     {
+#if CS_PROCESSOR_SIZE == 32
       return (void*)Set ((int32*)target, (int32)value);
+#elif CS_PROCESSOR_SIZE == 64
+      __asm__ __volatile__
+        (
+        "       lwsync \n"
+        "1:     ldarx   %0,0,%2 \n"
+        "       dcbt     0,%2 \n"
+        "       stdcx.  %3,0,%2 \n"
+        "       bne-    1b\n"
+        "       isync \n"
+        : "=&r" (value), "=m" (*(unsigned int *)target)
+        : "r" (target), "r" (value), "m" (*(unsigned int *)target)
+        : "cc", "memory"
+        );
+      return value;
+#endif
     }
 
     inline static int32 CompareAndSet (int32* target, int32 value,
@@ -74,21 +90,47 @@ namespace Threading
     inline static void* CompareAndSet (void** target, void* value,
       void* comparand)
     {
+#if CS_PROCESSOR_SIZE == 32
       return (void*)CompareAndSet ((int32*)target, (int32)value, 
         (int32)comparand);
+#elif CS_PROCESSOR_SIZE == 64
+      void *prev;
+
+      __asm__ __volatile__ (
+      "       lwsync \n"
+      "1:     ldarx   %0,0,%2\n"
+      "       cmpd    0,%0,%3\n"
+      "       bne-    2f\n"
+      "       dcbt     0,%2 \n"
+      "       stdcx.  %4,0,%2\n"
+      "       bne-    1b\n"
+      "       isync     \n"
+      "2:"
+      : "=&r" (prev), "=m" (*target)
+      : "r" (target), "r" (comparand), "r" (value), "m" (*target)
+      : "cc", "memory");
+      return prev;
+#endif
     }
 
     inline static int32 Increment (int32* target, int32 incr = 1)
     {
-      //@@Potentially dangerous code, needs to be revisited
-      int32 prevValue, currValue, nextValue;
-      do 
-      {
-        currValue = *target;
-        nextValue = currValue + incr;
-        prevValue = CompareAndSet (target, nextValue, currValue);
-      } while(prevValue == currValue);
-      return nextValue;
+      int32 value;
+
+      __asm__ __volatile__
+        (
+        "       lwsync \n"
+        "1:     lwarx   %0,0,%2 \n"
+        "       addw    %0,%0,%3 \n"
+        "       dcbt     0,%2 \n"
+        "       stwcx.  %0,0,%2 \n"
+        "       bne-    1b\n"
+        "       isync \n"
+        : "=&r" (value), "=m" (*(unsigned int *)target)
+        : "r" (target), "r" (incr), "m" (*(unsigned int *)target)
+        : "cc", "memory"
+        );
+      return value;
     }
 
     inline static int32 Decrement (int32* target)