From 09687717857ee2c30661aed63e3bac2fc44cf388 Mon Sep 17 00:00:00 2001 From: Anatoly Galiulin Date: Fri, 4 Mar 2016 13:01:17 +0600 Subject: [PATCH] Fixed threading issues for tcc backend --- lib/nimbase.h | 2 ++ lib/system.nim | 4 ++++ lib/system/atomics.nim | 47 +++++++++++++++++++++++++++++++++++++++++- 3 files changed, 52 insertions(+), 1 deletion(-) diff --git a/lib/nimbase.h b/lib/nimbase.h index 266b84b09d..4249014ad3 100644 --- a/lib/nimbase.h +++ b/lib/nimbase.h @@ -108,6 +108,8 @@ __clang__ defined __SUNPRO_C || \ defined __xlC__ # define NIM_THREADVAR __thread +#elif defined __TINYC__ +# defined NIM_THREADVAR #else # error "Cannot define NIM_THREADVAR" #endif diff --git a/lib/system.nim b/lib/system.nim index 241f552246..fefabe53f3 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -1288,6 +1288,10 @@ const hasSharedHeap = defined(boehmgc) or defined(gogc) # don't share heaps; every thread has its own taintMode = compileOption("taintmode") +when hasThreadSupport and defined(tcc) and not compileOption("tlsEmulation"): + # tcc doesn't support TLS + {.error: "``--tlsEmulation:on`` must be used when using threads with tcc backend".} + when defined(boehmgc): when defined(windows): const boehmLib = "boehmgc.dll" diff --git a/lib/system/atomics.nim b/lib/system/atomics.nim index 158fe91bc1..a79dcb1529 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):