summary refs log tree commit diff stats
path: root/lib/system
diff options
context:
space:
mode:
Diffstat (limited to 'lib/system')
-rw-r--r--lib/system/atomics.nim20
-rw-r--r--lib/system/excpt.nim9
-rw-r--r--lib/system/syslocks.nim110
3 files changed, 113 insertions, 26 deletions
diff --git a/lib/system/atomics.nim b/lib/system/atomics.nim
index 3a43729dc..885b01621 100644
--- a/lib/system/atomics.nim
+++ b/lib/system/atomics.nim
@@ -165,8 +165,22 @@ when someGcc and hasThreadSupport:
 
   template fence*() = atomicThreadFence(ATOMIC_SEQ_CST)
 elif defined(vcc) and hasThreadSupport:
-  proc addAndFetch*(p: ptr int, val: int): int {.
-    importc: "_InterlockedExchangeAdd", header: "<intrin.h>".}
+  when defined(cpp):
+    when sizeof(int) == 8:
+      proc addAndFetch*(p: ptr int, val: int): int {.
+        importcpp: "_InterlockedExchangeAdd64(static_cast<NI volatile *>(#), #)",
+        header: "<intrin.h>".}
+    else:
+      proc addAndFetch*(p: ptr int, val: int): int {.
+        importcpp: "_InterlockedExchangeAdd(static_cast<NI volatile *>(#), #)",
+        header: "<intrin.h>".}
+  else:
+    when sizeof(int) == 8:
+      proc addAndFetch*(p: ptr int, val: int): int {.
+        importc: "_InterlockedExchangeAdd64", header: "<intrin.h>".}
+    else:
+      proc addAndFetch*(p: ptr int, val: int): int {.
+        importc: "_InterlockedExchangeAdd", header: "<intrin.h>".}
 
   proc fence*() {.importc: "_ReadWriteBarrier", header: "<intrin.h>".}
 
@@ -180,6 +194,7 @@ proc atomicInc*(memLoc: var int, x: int = 1): int =
     result = atomic_add_fetch(memLoc.addr, x, ATOMIC_RELAXED)
   elif defined(vcc) and hasThreadSupport:
     result = addAndFetch(memLoc.addr, x)
+    inc(result, x)
   else:
     inc(memLoc, x)
     result = memLoc
@@ -192,6 +207,7 @@ proc atomicDec*(memLoc: var int, x: int = 1): int =
       result = atomic_add_fetch(memLoc.addr, -x, ATOMIC_RELAXED)
   elif defined(vcc) and hasThreadSupport:
     result = addAndFetch(memLoc.addr, -x)
+    dec(result, x)
   else:
     dec(memLoc, x)
     result = memLoc
diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim
index bdcb4c1f6..55f283d2d 100644
--- a/lib/system/excpt.nim
+++ b/lib/system/excpt.nim
@@ -299,8 +299,13 @@ proc raiseExceptionAux(e: ref Exception) =
 proc raiseException(e: ref Exception, ename: cstring) {.compilerRtl.} =
   if e.name.isNil: e.name = ename
   when hasSomeStackTrace:
-    e.trace = ""
-    rawWriteStackTrace(e.trace)
+    if e.trace.isNil:
+      e.trace = ""
+      rawWriteStackTrace(e.trace)
+    elif framePtr != nil:
+      e.trace.add "[[reraised from:\n"
+      auxWriteStackTrace(framePtr, e.trace)
+      e.trace.add "]]\n"
   raiseExceptionAux(e)
 
 proc reraiseException() {.compilerRtl.} =
diff --git a/lib/system/syslocks.nim b/lib/system/syslocks.nim
index fb354880f..f61b887ad 100644
--- a/lib/system/syslocks.nim
+++ b/lib/system/syslocks.nim
@@ -99,7 +99,7 @@ elif defined(genode):
 
 else:
   type
-    SysLock {.importc: "pthread_mutex_t", pure, final,
+    SysLockObj {.importc: "pthread_mutex_t", pure, final,
                header: """#include <sys/types.h>
                           #include <pthread.h>""".} = object
       when defined(linux) and defined(amd64):
@@ -111,7 +111,7 @@ else:
       when defined(linux) and defined(amd64):
         abi: array[4 div sizeof(cint), cint]  # actually a cint
 
-    SysCond {.importc: "pthread_cond_t", pure, final,
+    SysCondObj {.importc: "pthread_cond_t", pure, final,
                header: """#include <sys/types.h>
                           #include <pthread.h>""".} = object
       when defined(linux) and defined(amd64):
@@ -119,8 +119,62 @@ else:
 
     SysLockType = distinct cint
 
-  proc initSysLock(L: var SysLock, attr: ptr SysLockAttr = nil) {.
+  proc initSysLockAux(L: var SysLockObj, attr: ptr SysLockAttr) {.
     importc: "pthread_mutex_init", header: "<pthread.h>", noSideEffect.}
+  proc deinitSysAux(L: var SysLockObj) {.noSideEffect,
+    importc: "pthread_mutex_destroy", header: "<pthread.h>".}
+
+  proc acquireSysAux(L: var SysLockObj) {.noSideEffect,
+    importc: "pthread_mutex_lock", header: "<pthread.h>".}
+  proc tryAcquireSysAux(L: var SysLockObj): cint {.noSideEffect,
+    importc: "pthread_mutex_trylock", header: "<pthread.h>".}
+
+  proc releaseSysAux(L: var SysLockObj) {.noSideEffect,
+    importc: "pthread_mutex_unlock", header: "<pthread.h>".}
+
+  when defined(ios):
+    # iOS will behave badly if sync primitives are moved in memory. In order
+    # to prevent this once and for all, we're doing an extra malloc when
+    # initializing the primitive.
+    type
+      SysLock = ptr SysLockObj
+      SysCond = ptr SysCondObj
+
+    when not declared(c_malloc):
+      proc c_malloc(size: csize): pointer {.
+        importc: "malloc", header: "<stdlib.h>".}
+      proc c_free(p: pointer) {.
+        importc: "free", header: "<stdlib.h>".}
+
+    proc initSysLock(L: var SysLock, attr: ptr SysLockAttr = nil) =
+      L = cast[SysLock](c_malloc(sizeof(SysLockObj)))
+      initSysLockAux(L[], attr)
+
+    proc deinitSys(L: var SysLock) =
+      deinitSysAux(L[])
+      c_free(L)
+
+    template acquireSys(L: var SysLock) =
+      acquireSysAux(L[])
+    template tryAcquireSys(L: var SysLock): bool =
+      tryAcquireSysAux(L[]) == 0'i32
+    template releaseSys(L: var SysLock) =
+      releaseSysAux(L[])
+  else:
+    type
+      SysLock = SysLockObj
+      SysCond = SysCondObj
+
+    template initSysLock(L: var SysLock, attr: ptr SysLockAttr = nil) =
+      initSysLockAux(L, attr)
+    template deinitSys(L: var SysLock) =
+      deinitSysAux(L)
+    template acquireSys(L: var SysLock) =
+      acquireSysAux(L)
+    template tryAcquireSys(L: var SysLock): bool =
+      tryAcquireSysAux(L) == 0'i32
+    template releaseSys(L: var SysLock) =
+      releaseSysAux(L)
 
   when insideRLocksModule:
     proc SysLockType_Reentrant: SysLockType =
@@ -130,27 +184,39 @@ else:
     proc setSysLockType(a: var SysLockAttr, t: SysLockType) {.
       importc: "pthread_mutexattr_settype", header: "<pthread.h>", noSideEffect.}
 
-  proc acquireSys(L: var SysLock) {.noSideEffect,
-    importc: "pthread_mutex_lock", header: "<pthread.h>".}
-  proc tryAcquireSysAux(L: var SysLock): cint {.noSideEffect,
-    importc: "pthread_mutex_trylock", header: "<pthread.h>".}
-
-  proc tryAcquireSys(L: var SysLock): bool {.inline.} =
-    result = tryAcquireSysAux(L) == 0'i32
-
-  proc releaseSys(L: var SysLock) {.noSideEffect,
-    importc: "pthread_mutex_unlock", header: "<pthread.h>".}
-  proc deinitSys(L: var SysLock) {.noSideEffect,
-    importc: "pthread_mutex_destroy", header: "<pthread.h>".}
-
-  when not insideRLocksModule:
-    proc initSysCond(cond: var SysCond, cond_attr: pointer = nil) {.
+  else:
+    proc initSysCondAux(cond: var SysCondObj, cond_attr: pointer) {.
       importc: "pthread_cond_init", header: "<pthread.h>", noSideEffect.}
-    proc waitSysCond(cond: var SysCond, lock: var SysLock) {.
+    proc deinitSysCondAux(cond: var SysCondObj) {.noSideEffect,
+      importc: "pthread_cond_destroy", header: "<pthread.h>".}
+
+    proc waitSysCondAux(cond: var SysCondObj, lock: var SysLockObj) {.
       importc: "pthread_cond_wait", header: "<pthread.h>", noSideEffect.}
-    proc signalSysCond(cond: var SysCond) {.
+    proc signalSysCondAux(cond: var SysCondObj) {.
       importc: "pthread_cond_signal", header: "<pthread.h>", noSideEffect.}
-    proc deinitSysCond(cond: var SysCond) {.noSideEffect,
-      importc: "pthread_cond_destroy", header: "<pthread.h>".}
+
+    when defined(ios):
+      proc initSysCond(cond: var SysCond, cond_attr: pointer = nil) =
+        cond = cast[SysCond](c_malloc(sizeof(SysCondObj)))
+        initSysCondAux(cond[], cond_attr)
+
+      proc deinitSysCond(cond: var SysCond) =
+        deinitSysCondAux(cond[])
+        c_free(cond)
+
+      template waitSysCond(cond: var SysCond, lock: var SysLock) =
+        waitSysCondAux(cond[], lock[])
+      template signalSysCond(cond: var SysCond) =
+        signalSysCondAux(cond[])
+    else:
+      template initSysCond(cond: var SysCond, cond_attr: pointer = nil) =
+        initSysCondAux(cond, cond_attr)
+      template deinitSysCond(cond: var SysCond) =
+        deinitSysCondAux(cond)
+
+      template waitSysCond(cond: var SysCond, lock: var SysLock) =
+        waitSysCondAux(cond, lock)
+      template signalSysCond(cond: var SysCond) =
+        signalSysCondAux(cond)
 
 {.pop.}