summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--lib/system/alloc.nim30
-rw-r--r--lib/system/avltree.nim2
-rw-r--r--lib/system/memtracker.nim7
-rw-r--r--lib/system/threads.nim32
-rw-r--r--tests/threads/threadex.nim5
5 files changed, 58 insertions, 18 deletions
diff --git a/lib/system/alloc.nim b/lib/system/alloc.nim
index 95566129d..6f11941a0 100644
--- a/lib/system/alloc.nim
+++ b/lib/system/alloc.nim
@@ -103,19 +103,12 @@ type
     root, deleted, last, freeAvlNodes: PAvlNode
     locked, blockChunkSizeIncrease: bool # if locked, we cannot free pages.
     nextChunkSize: int
-{.deprecated: [TMemRegion: MemRegion].}
+    bottomData: AvlNode
 
-# shared:
-var
-  bottomData {.threadvar.}: AvlNode
-  bottom {.threadvar.}: PAvlNode
+{.deprecated: [TMemRegion: MemRegion].}
 
 {.push stack_trace: off.}
-proc initAllocator() =
-  when not defined(useNimRtl):
-    bottom = addr(bottomData)
-    bottom.link[0] = bottom
-    bottom.link[1] = bottom
+proc initAllocator() = discard "nothing to do anymore"
 {.pop.}
 
 proc incCurrMem(a: var MemRegion, bytes: int) {.inline.} =
@@ -152,6 +145,12 @@ proc llAlloc(a: var MemRegion, size: int): pointer =
   inc(a.llmem.acc, size)
   zeroMem(result, size)
 
+proc getBottom(a: var MemRegion): PAvlNode =
+  result = addr(a.bottomData)
+  if result.link[0] == nil:
+    result.link[0] = result
+    result.link[1] = result
+
 proc allocAvlNode(a: var MemRegion, key, upperBound: int): PAvlNode =
   if a.freeAvlNodes != nil:
     result = a.freeAvlNodes
@@ -162,12 +161,13 @@ proc allocAvlNode(a: var MemRegion, key, upperBound: int): PAvlNode =
       cprintf("tracking location: %p\n", result)
   result.key = key
   result.upperBound = upperBound
+  let bottom = getBottom(a)
   result.link[0] = bottom
   result.link[1] = bottom
   result.level = 1
-  when defined(avlcorruption):
-    track("allocAvlNode", result, sizeof(AvlNode))
-  sysAssert(bottom == addr(bottomData), "bottom data")
+  #when defined(avlcorruption):
+  #  track("allocAvlNode", result, sizeof(AvlNode))
+  sysAssert(bottom == addr(a.bottomData), "bottom data")
   sysAssert(bottom.link[0] == bottom, "bottom link[0]")
   sysAssert(bottom.link[1] == bottom, "bottom link[1]")
 
@@ -565,7 +565,7 @@ proc rawAlloc(a: var MemRegion, requestedSize: int): pointer =
     sysAssert c.size == size, "rawAlloc 12"
     result = addr(c.data)
     sysAssert((cast[ByteAddress](result) and (MemAlign-1)) == 0, "rawAlloc 13")
-    if a.root == nil: a.root = bottom
+    if a.root == nil: a.root = getBottom(a)
     add(a, a.root, cast[ByteAddress](result), cast[ByteAddress](result)+%size)
   sysAssert(isAccessible(a, result), "rawAlloc 14")
   sysAssert(allocInv(a), "rawAlloc: end")
@@ -613,7 +613,7 @@ proc rawDealloc(a: var MemRegion, p: pointer) =
     when overwriteFree: c_memset(p, -1'i32, c.size -% bigChunkOverhead())
     # free big chunk
     var c = cast[PBigChunk](c)
-    a.deleted = bottom
+    a.deleted = getBottom(a)
     del(a, a.root, cast[int](addr(c.data)))
     freeBigChunk(a, c)
   sysAssert(allocInv(a), "rawDealloc: end")
diff --git a/lib/system/avltree.nim b/lib/system/avltree.nim
index 96c187841..8d4b7e897 100644
--- a/lib/system/avltree.nim
+++ b/lib/system/avltree.nim
@@ -81,7 +81,7 @@ proc del(a: var MemRegion, t: var PAvlNode, x: int) {.benign.} =
   if t == a.last and not isBottom(a.deleted) and x == a.deleted.key:
     a.deleted.key = t.key
     a.deleted.upperBound = t.upperBound
-    a.deleted = bottom
+    a.deleted = getBottom(a)
     t = t.link[1]
     deallocAvlNode(a, a.last)
   elif t.link[0].level < t.level-1 or
diff --git a/lib/system/memtracker.nim b/lib/system/memtracker.nim
index 0e33e0ec0..219956012 100644
--- a/lib/system/memtracker.nim
+++ b/lib/system/memtracker.nim
@@ -62,12 +62,17 @@ proc addEntry(entry: LogEntry) =
         interesting = true
         break
     if interesting:
-      cprintf("interesting %s:%ld\n", entry.file, entry.line)
+      gLog.disabled = true
+      cprintf("interesting %s:%ld %s\n", entry.file, entry.line, entry.op)
+      let x = cast[proc() {.nimcall, tags: [], gcsafe, locks: 0.}](writeStackTrace)
+      x()
+      quit 1
       if gLog.count > high(gLog.data):
         gLogger(gLog)
         gLog.count = 0
       gLog.data[gLog.count] = entry
       inc gLog.count
+      gLog.disabled = false
 
 proc memTrackerWrite(address: pointer; size: int; file: cstring; line: int) {.compilerProc.} =
   addEntry LogEntry(op: "write", address: address,
diff --git a/lib/system/threads.nim b/lib/system/threads.nim
index f72395fd2..7886fdcdf 100644
--- a/lib/system/threads.nim
+++ b/lib/system/threads.nim
@@ -53,7 +53,7 @@ when defined(windows):
   type
     SysThread* = Handle
     WinThreadProc = proc (x: pointer): int32 {.stdcall.}
-  {.deprecated: [TSysThread: SysThread, TWinThreadProc: WinThreadProc].}
+  {.deprecated: [TSysThread: SysThread].}
 
   proc createThread(lpThreadAttributes: pointer, dwStackSize: int32,
                      lpStartAddress: WinThreadProc,
@@ -77,6 +77,9 @@ when defined(windows):
   proc terminateThread(hThread: SysThread, dwExitCode: int32): int32 {.
     stdcall, dynlib: "kernel32", importc: "TerminateThread".}
 
+  proc getCurrentThreadId(): int32 {.
+    stdcall, dynlib: "kernel32", importc: "GetCurrentThreadId".}
+
   type
     ThreadVarSlot = distinct int32
 
@@ -108,6 +111,10 @@ when defined(windows):
   proc setThreadAffinityMask(hThread: SysThread, dwThreadAffinityMask: uint) {.
     importc: "SetThreadAffinityMask", stdcall, header: "<windows.h>".}
 
+  proc getThreadId*(): int =
+    ## get the ID of the currently running thread.
+    result = int(getCurrentThreadId())
+
 else:
   when not defined(macosx):
     {.passL: "-pthread".}
@@ -187,6 +194,29 @@ else:
   proc setAffinity(thread: SysThread; setsize: csize; s: var CpuSet) {.
     importc: "pthread_setaffinity_np", header: pthreadh.}
 
+  when defined(linux):
+    type Pid {.importc: "pid_t", header: "<sys/types.h>".} = distinct int
+    proc gettid(): Pid {.importc, header: "<sys/types.h>".}
+
+    proc getThreadId*(): int =
+      ## get the ID of the currently running thread.
+      result = int(gettid())
+  elif defined(macosx) or defined(bsd):
+    proc pthread_main_np(): cint {.importc, header: "pthread.h".}
+
+    proc getThreadId*(): int =
+      ## get the ID of the currently running thread.
+      result = int(pthread_main_np())
+  elif defined(solaris):
+    # just a guess really:
+    type thread_t {.importc: "thread_t", header: "<thread.h>".} = distinct int
+    proc thr_self(): thread_t {.importc, header: "<thread.h>".}
+
+    proc getThreadId*(): int =
+      ## get the ID of the currently running thread.
+      result = int(thr_self())
+
+
 const
   emulatedThreadVars = compileOption("tlsEmulation")
 
diff --git a/tests/threads/threadex.nim b/tests/threads/threadex.nim
index 442e80189..fb03cbfa8 100644
--- a/tests/threads/threadex.nim
+++ b/tests/threads/threadex.nim
@@ -14,8 +14,11 @@ var
   producer, consumer: Thread[void]
   chan: Channel[TMsg]
   printedLines = 0
+  prodId: int
+  consId: int
 
 proc consume() {.thread.} =
+  consId = getThreadId()
   while true:
     var x = recv(chan)
     if x.k == mEof: break
@@ -23,6 +26,7 @@ proc consume() {.thread.} =
     atomicInc(printedLines)
 
 proc produce() {.thread.} =
+  prodId = getThreadId()
   var m: TMsg
   var input = open("readme.txt")
   var line = ""
@@ -40,5 +44,6 @@ joinThread(consumer)
 joinThread(producer)
 
 close(chan)
+doAssert prodId != consId
 echo printedLines