summary refs log tree commit diff stats
path: root/lib
diff options
context:
space:
mode:
authorEugene Kabanov <ka@hardcore.kiev.ua>2017-03-23 17:13:38 +0200
committerAndreas Rumpf <rumpf_a@web.de>2017-03-23 16:13:38 +0100
commit254fbcc548247865cf15200a200436024258e647 (patch)
treed72374034135985df44bb7fb1f12327a1cde6079 /lib
parentd508303fadc65bacbf15ada83da37660f5552107 (diff)
downloadNim-254fbcc548247865cf15200a200436024258e647.tar.gz
Fixes #4719. (#5585)
Diffstat (limited to 'lib')
-rw-r--r--lib/system/alloc.nim3
-rw-r--r--lib/system/threads.nim42
2 files changed, 26 insertions, 19 deletions
diff --git a/lib/system/alloc.nim b/lib/system/alloc.nim
index cde17bead..edd8ececb 100644
--- a/lib/system/alloc.nim
+++ b/lib/system/alloc.nim
@@ -763,6 +763,8 @@ proc getOccupiedMem(a: MemRegion): int {.inline.} =
 # ---------------------- thread memory region -------------------------------
 
 template instantiateForRegion(allocator: untyped) =
+  {.push stackTrace: off.}
+
   when defined(fulldebug):
     proc interiorAllocatedPtr*(p: pointer): pointer =
       result = interiorAllocatedPtr(allocator, p)
@@ -850,5 +852,6 @@ template instantiateForRegion(allocator: untyped) =
 
     proc getOccupiedSharedMem(): int =
       sharedMemStatsShared(sharedHeap.currMem - sharedHeap.freeMem)
+  {.pop.}
 
 {.pop.}
diff --git a/lib/system/threads.nim b/lib/system/threads.nim
index 5cdca5470..dc9cc9656 100644
--- a/lib/system/threads.nim
+++ b/lib/system/threads.nim
@@ -242,7 +242,6 @@ type
 
   PGcThread = ptr GcThread
   GcThread {.pure, inheritable.} = object
-    sys: SysThread
     when emulatedThreadVars and not useStackMaskHack:
       tls: ThreadLocalStorage
     else:
@@ -345,18 +344,16 @@ when not defined(useNimRtl):
 # use ``stdcall`` since it is mapped to ``noconv`` on UNIX anyway.
 
 type
-  Thread* {.pure, final.}[TArg] =
-      object of GcThread  ## Nim thread. A thread is a heavy object (~14K)
-                          ## that **must not** be part of a message! Use
-                          ## a ``ThreadId`` for that.
+  Thread* {.pure, final.}[TArg] = object
+    core: PGcThread
+    sys: SysThread
     when TArg is void:
       dataFn: proc () {.nimcall, gcsafe.}
     else:
       dataFn: proc (m: TArg) {.nimcall, gcsafe.}
       data: TArg
-  ThreadId*[TArg] = ptr Thread[TArg]  ## the current implementation uses
-                                       ## a pointer as a thread ID.
-{.deprecated: [TThread: Thread, TThreadId: ThreadId].}
+
+{.deprecated: [TThread: Thread].}
 
 var
   threadDestructionHandlers {.rtlThreadVar.}: seq[proc () {.closure, gcsafe.}]
@@ -423,19 +420,20 @@ proc threadProcWrapStackFrame[TArg](thrd: ptr Thread[TArg]) =
       when declared(threadType):
         threadType = ThreadType.NimThread
     when declared(registerThread):
-      thrd.stackBottom = addr(thrd)
-      registerThread(thrd)
+      thrd.core.stackBottom = addr(thrd)
+      registerThread(thrd.core)
     p(thrd)
-    when declared(registerThread): unregisterThread(thrd)
+    when declared(registerThread): unregisterThread(thrd.core)
     when declared(deallocOsPages): deallocOsPages()
   else:
     threadProcWrapDispatch(thrd)
 
 template threadProcWrapperBody(closure: expr) {.immediate.} =
-  when declared(globalsSlot): threadVarSetValue(globalsSlot, closure)
+  var thrd = cast[ptr Thread[TArg]](closure)
+  var core = thrd.core
+  when declared(globalsSlot): threadVarSetValue(globalsSlot, thrd.core)
   when declared(initAllocator):
     initAllocator()
-  var thrd = cast[ptr Thread[TArg]](closure)
   threadProcWrapStackFrame(thrd)
   # Since an unhandled exception terminates the whole process (!), there is
   # no need for a ``try finally`` here, nor would it be correct: The current
@@ -444,7 +442,9 @@ template threadProcWrapperBody(closure: expr) {.immediate.} =
   # page!
 
   # mark as not running anymore:
+  thrd.core = nil
   thrd.dataFn = nil
+  deallocShared(cast[pointer](core))
 
 {.push stack_trace:off.}
 when defined(windows):
@@ -502,6 +502,10 @@ when false:
       discard pthread_cancel(t.sys)
     when declared(registerThread): unregisterThread(addr(t))
     t.dataFn = nil
+    ## if thread `t` already exited, `t.core` will be `null`.
+    if not isNil(t.core):
+      deallocShared(t.core)
+      t.core = nil
 
 when hostOS == "windows":
   proc createThread*[TArg](t: var Thread[TArg],
@@ -510,9 +514,11 @@ when hostOS == "windows":
     ## creates a new thread `t` and starts its execution. Entry point is the
     ## proc `tp`. `param` is passed to `tp`. `TArg` can be ``void`` if you
     ## don't need to pass any data to the thread.
+    t.core = cast[PGcThread](allocShared0(sizeof(GcThread)))
+
     when TArg isnot void: t.data = param
     t.dataFn = tp
-    when hasSharedHeap: t.stackSize = ThreadStackSize
+    when hasSharedHeap: t.core.stackSize = ThreadStackSize
     var dummyThreadId: int32
     t.sys = createThread(nil, ThreadStackSize, threadProcWrapper[TArg],
                          addr(t), 0'i32, dummyThreadId)
@@ -532,9 +538,11 @@ else:
     ## creates a new thread `t` and starts its execution. Entry point is the
     ## proc `tp`. `param` is passed to `tp`. `TArg` can be ``void`` if you
     ## don't need to pass any data to the thread.
+    t.core = cast[PGcThread](allocShared0(sizeof(GcThread)))
+
     when TArg isnot void: t.data = param
     t.dataFn = tp
-    when hasSharedHeap: t.stackSize = ThreadStackSize
+    when hasSharedHeap: t.core.stackSize = ThreadStackSize
     var a {.noinit.}: PthreadAttr
     pthread_attr_init(a)
     pthread_attr_setstacksize(a, ThreadStackSize)
@@ -554,10 +562,6 @@ else:
 proc createThread*(t: var Thread[void], tp: proc () {.thread, nimcall.}) =
   createThread[void](t, tp)
 
-proc threadId*[TArg](t: var Thread[TArg]): ThreadId[TArg] {.inline.} =
-  ## returns the thread ID of `t`.
-  result = addr(t)
-
 when false:
   proc mainThreadId*[TArg](): ThreadId[TArg] =
     ## returns the thread ID of the main thread.