summary refs log tree commit diff stats
path: root/lib/system
diff options
context:
space:
mode:
authorAnatoly Galiulin <galiulin.anatoly@gmail.com>2016-03-04 13:01:17 +0600
committerAnatoly Galiulin <galiulin.anatoly@gmail.com>2016-03-10 17:45:11 +0600
commit09687717857ee2c30661aed63e3bac2fc44cf388 (patch)
tree1ca7c5feff3fb1a71be9107e42f716ffdaba35fb /lib/system
parent7281b66a4f91ec7f8124353835c627362dac23c1 (diff)
downloadNim-09687717857ee2c30661aed63e3bac2fc44cf388.tar.gz
Fixed threading issues for tcc backend
Diffstat (limited to 'lib/system')
-rw-r--r--lib/system/atomics.nim47
1 files changed, 46 insertions, 1 deletions
diff --git a/lib/system/atomics.nim b/lib/system/atomics.nim
index 158fe91bc..a79dcb152 100644
--- a/lib/system/atomics.nim
+++ b/lib/system/atomics.nim
@@ -197,6 +197,51 @@ when defined(windows) and not someGcc:
   proc cas*[T: bool|int|ptr](p: ptr T; oldValue, newValue: T): bool =
     interlockedCompareExchange(p, cast[int](newValue), cast[int](oldValue)) != 0
   # XXX fix for 64 bit build
+elif defined(tcc) and not defined(windows):
+  when defined(amd64):
+    {.emit:"""
+static int __tcc_cas(int *ptr, int oldVal, int newVal)
+{
+    unsigned char ret;
+    __asm__ __volatile__ (
+            "  lock\n"
+            "  cmpxchgq %2,%1\n"
+            "  sete %0\n"
+            : "=q" (ret), "=m" (*ptr)
+            : "r" (newVal), "m" (*ptr), "a" (oldVal)
+            : "memory");
+
+    if (ret)
+      return 0;
+    else
+      return 1;
+}
+""".}
+  else:
+    assert sizeof(int) == 4
+    {.emit:"""
+static int __tcc_cas(int *ptr, int oldVal, int newVal)
+{
+    unsigned char ret;
+    __asm__ __volatile__ (
+            "  lock\n"
+            "  cmpxchgl %2,%1\n"
+            "  sete %0\n"
+            : "=q" (ret), "=m" (*ptr)
+            : "r" (newVal), "m" (*ptr), "a" (oldVal)
+            : "memory");
+
+    if (ret)
+      return 0;
+    else
+      return 1;
+}
+""".}
+    
+  proc tcc_cas(p: ptr int; oldValue, newValue: int): bool
+    {.importc: "__tcc_cas", nodecl.}
+  proc cas*[T: bool|int|ptr](p: ptr T; oldValue, newValue: T): bool =
+    tcc_cas(cast[ptr int](p), cast[int](oldValue), cast[int](newValue))
 else:
   # this is valid for GCC and Intel C++
   proc cas*[T: bool|int|ptr](p: ptr T; oldValue, newValue: T): bool
@@ -207,7 +252,7 @@ else:
 when (defined(x86) or defined(amd64)) and someGcc:
   proc cpuRelax* {.inline.} =
     {.emit: """asm volatile("pause" ::: "memory");""".}
-elif someGcc:
+elif someGcc or defined(tcc):
   proc cpuRelax* {.inline.} =
     {.emit: """asm volatile("" ::: "memory");""".}
 elif (defined(x86) or defined(amd64)) and defined(vcc):