2009-04-10 Zoltan Varga <vargaz@gmail.com>
[mono.git] / libgc / include / private / gc_locks.h
index d1ccf0ed0da550eb4061b8998ea6a1a5d4d7ce87..83fe57d917d70ad2a20a5b3b4452610ba86c263c 100644 (file)
 #      define GC_TEST_AND_SET_DEFINED
 #    endif
 #    if defined(POWERPC)
-#     if CPP_WORDSZ == 64
-        inline static int GC_test_and_set(volatile unsigned int *addr) {
-          unsigned long oldval;
-          unsigned long temp = 1; /* locked value */
-
-          __asm__ __volatile__(
-               "1:\tldarx %0,0,%3\n"   /* load and reserve               */
-               "\tcmpdi %0, 0\n"       /* if load is                     */
-               "\tbne 2f\n"            /*   non-zero, return already set */
-               "\tstdcx. %2,0,%1\n"    /* else store conditional         */
-               "\tbne- 1b\n"           /* retry if lost reservation      */
-               "\tsync\n"              /* import barrier                 */
-               "2:\t\n"                /* oldval is zero if we set       */
-              : "=&r"(oldval), "=p"(addr)
-              : "r"(temp), "1"(addr)
-              : "cr0","memory");
-          return (int)oldval;
-        }
-#     else
         inline static int GC_test_and_set(volatile unsigned int *addr) {
           int oldval;
           int temp = 1; /* locked value */
 
           __asm__ __volatile__(
-               "1:\tlwarx %0,0,%3\n"   /* load and reserve               */
+               "1:\tlwarx %0,0,%1\n"   /* load and reserve               */
                "\tcmpwi %0, 0\n"       /* if load is                     */
                "\tbne 2f\n"            /*   non-zero, return already set */
                "\tstwcx. %2,0,%1\n"    /* else store conditional         */
                "\tbne- 1b\n"           /* retry if lost reservation      */
                "\tsync\n"              /* import barrier                 */
                "2:\t\n"                /* oldval is zero if we set       */
-              : "=&r"(oldval), "=p"(addr)
-              : "r"(temp), "1"(addr)
+              : "=&r"(oldval)
+              : "r"(addr), "r"(temp)
               : "cr0","memory");
           return oldval;
         }
-#     endif
 #     define GC_TEST_AND_SET_DEFINED
       inline static void GC_clear(volatile unsigned int *addr) {
        __asm__ __volatile__("lwsync" : : : "memory");
        }
 #     endif /* I386 */
 
+#     if defined(X86_64)
+#      if !defined(GENERIC_COMPARE_AND_SWAP)
+         /* Returns TRUE if the comparison succeeded. */
+         inline static GC_bool GC_compare_and_exchange(volatile GC_word *addr,
+                                                      GC_word old,
+                                                      GC_word new_val) 
+         {
+          char result;
+          __asm__ __volatile__("lock; cmpxchgq %2, %0; setz %1"
+               : "+m"(*(addr)), "=r"(result)
+               : "r" (new_val), "a"(old) : "memory");
+          return (GC_bool) result;
+         }
+#      endif /* !GENERIC_COMPARE_AND_SWAP */
+       inline static void GC_memory_barrier()
+       {
+        /* We believe the processor ensures at least processor */
+        /* consistent ordering.  Thus a compiler barrier       */
+        /* should suffice.                                     */
+         __asm__ __volatile__("" : : : "memory");
+       }
+#     endif /* X86_64 */
+
 #     if defined(POWERPC)
 #      if !defined(GENERIC_COMPARE_AND_SWAP)
 #       if CPP_WORDSZ == 64