summary refs log tree commit diff stats
path: root/lib/system
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2016-01-25 03:14:22 +0100
committerAndreas Rumpf <rumpf_a@web.de>2016-03-28 02:15:08 +0200
commitc11487b339018f01e72ff17fc919f2e3974de658 (patch)
tree7bbb82180da26dd9174b79c07899d345f8b3f9e0 /lib/system
parent3a95a0bba4e9251f8ce4ff08678af368345e9218 (diff)
downloadNim-c11487b339018f01e72ff17fc919f2e3974de658.tar.gz
GCs support ForeignCells
Diffstat (limited to 'lib/system')
-rw-r--r--lib/system/gc.nim11
-rw-r--r--lib/system/gc_common.nim25
-rw-r--r--lib/system/gc_ms.nim7
-rw-r--r--lib/system/syslocks.nim4
4 files changed, 47 insertions, 0 deletions
diff --git a/lib/system/gc.nim b/lib/system/gc.nim
index d8390ca14..4f461b5c3 100644
--- a/lib/system/gc.nim
+++ b/lib/system/gc.nim
@@ -39,6 +39,9 @@ when withRealTime and not declared(getTicks):
 when defined(memProfiler):
   proc nimProfile(requestedSize: int) {.benign.}
 
+when hasThreadSupport:
+  import sharedlist
+
 const
   rcIncrement = 0b1000 # so that lowest 3 bits are not touched
   rcBlack = 0b000  # cell is colored black; in use or free
@@ -93,6 +96,9 @@ type
     stat: GcStat
     when useMarkForDebug or useBackupGc:
       marked: CellSet
+    when hasThreadSupport:
+      toDispose: SharedList[pointer]
+
 {.deprecated: [TWalkOp: WalkOp, TFinalizer: Finalizer, TGcHeap: GcHeap,
               TGcStat: GcStat].}
 var
@@ -304,6 +310,8 @@ proc initGC() =
     init(gch.decStack)
     when useMarkForDebug or useBackupGc:
       init(gch.marked)
+    when hasThreadSupport:
+      gch.toDispose = initSharedList[pointer]()
 
 when useMarkForDebug or useBackupGc:
   type
@@ -749,6 +757,9 @@ proc collectRoots(gch: var GcHeap) =
     collectWhite(s)
 
 proc collectCycles(gch: var GcHeap) =
+  when hasThreadSupport:
+    for c in gch.toDispose:
+      nimGCunref(c)
   # ensure the ZCT 'color' is not used:
   while gch.zct.len > 0: discard collectZCT(gch)
   when useBackupGc:
diff --git a/lib/system/gc_common.nim b/lib/system/gc_common.nim
index a4676d26e..4807bb6f8 100644
--- a/lib/system/gc_common.nim
+++ b/lib/system/gc_common.nim
@@ -7,6 +7,31 @@
 #    distribution, for details about the copyright.
 #
 
+type
+  ForeignCell* = object
+    data*: pointer
+    owner: ptr GcHeap
+
+proc protect*(x: pointer): ForeignCell =
+  nimGCref(x)
+  result.data = x
+  result.owner = addr(gch)
+
+proc dispose*(x: ForeignCell) =
+  when hasThreadSupport:
+    # if we own it we can free it directly:
+    if x.owner == addr(gch):
+      nimGCunref(x.data)
+    else:
+      x.owner.toDispose.add(x.data)
+  else:
+    nimGCunref(x.data)
+
+proc isNotForeign*(x: ForeignCell): bool =
+  ## returns true if 'x' belongs to the calling thread.
+  ## No deep copy has to be performed then.
+  x.owner == addr(gch)
+
 proc len(stack: ptr GcStack): int =
   if stack == nil:
     return 0
diff --git a/lib/system/gc_ms.nim b/lib/system/gc_ms.nim
index d1aecb7a2..c764571b1 100644
--- a/lib/system/gc_ms.nim
+++ b/lib/system/gc_ms.nim
@@ -68,6 +68,8 @@ type
     recGcLock: int           # prevent recursion via finalizers; no thread lock
     region: MemRegion        # garbage collected region
     stat: GcStat
+    when hasThreadSupport:
+      toDispose: SharedList[pointer]
     additionalRoots: CellSeq # dummy roots for GC_ref/unref
 {.deprecated: [TWalkOp: WalkOp, TFinalizer: Finalizer, TGcStat: GcStat,
               TGlobalMarkerProc: GlobalMarkerProc, TGcHeap: GcHeap].}
@@ -179,6 +181,8 @@ proc initGC() =
     when withBitvectors:
       init(gch.allocated)
       init(gch.marked)
+    when hasThreadSupport:
+      gch.toDispose = initSharedList[pointer]()
 
 proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: WalkOp) {.benign.} =
   var d = cast[ByteAddress](dest)
@@ -321,6 +325,9 @@ proc growObj(old: pointer, newsize: int): pointer {.rtl.} =
 # ----------------- collector -----------------------------------------------
 
 proc mark(gch: var GcHeap, c: PCell) =
+  when hasThreadSupport:
+    for c in gch.toDispose:
+      nimGCunref(c)
   when withBitvectors:
     incl(gch.marked, c)
     gcAssert gch.tempStack.len == 0, "stack not empty!"
diff --git a/lib/system/syslocks.nim b/lib/system/syslocks.nim
index 1551a4121..6dcdfff0d 100644
--- a/lib/system/syslocks.nim
+++ b/lib/system/syslocks.nim
@@ -9,6 +9,8 @@
 
 # Low level system locks and condition vars.
 
+{.push stackTrace: off.}
+
 when defined(Windows):
   type
     Handle = int
@@ -118,3 +120,5 @@ else:
 
   proc deinitSysCond(cond: var SysCond) {.noSideEffect,
     importc: "pthread_cond_destroy", header: "<pthread.h>".}
+
+{.pop.}