summary refs log tree commit diff stats
path: root/lib/system
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2011-05-16 00:27:47 +0200
committerAraq <rumpf_a@web.de>2011-05-16 00:27:47 +0200
commit67a30d837132e8000d1a8b10ce3d32423d149318 (patch)
treeb059b56027b57c45777d15d33e88b3dac9313f14 /lib/system
parentc7b3d828be1bbca81f3576875636ea571e595402 (diff)
downloadNim-67a30d837132e8000d1a8b10ce3d32423d149318.tar.gz
further steps for thread support; bootstrapping should require unzip C sources and ./build.sh
Diffstat (limited to 'lib/system')
-rwxr-xr-xlib/system/cgprocs.nim47
-rwxr-xr-xlib/system/debugger.nim40
-rwxr-xr-xlib/system/dyncalls.nim5
-rwxr-xr-xlib/system/excpt.nim263
-rwxr-xr-xlib/system/gc.nim2
-rwxr-xr-xlib/system/hti.nim2
-rwxr-xr-xlib/system/systhread.nim3
7 files changed, 216 insertions, 146 deletions
diff --git a/lib/system/cgprocs.nim b/lib/system/cgprocs.nim
index 8509fe3a3..d80747671 100755
--- a/lib/system/cgprocs.nim
+++ b/lib/system/cgprocs.nim
@@ -23,50 +23,3 @@ proc nimLoadLibraryError(path: string) {.compilerproc, noinline.}
 
 proc setStackBottom(theStackBottom: pointer) {.compilerRtl, noinline.}
 
-when false:
-  # Support for thread local storage:
-  when defined(windows):
-    type
-      TThreadVarSlot {.compilerproc.} = distinct int32
-
-    proc TlsAlloc(): TThreadVarSlot {.
-      importc: "TlsAlloc", stdcall, dynlib: "kernel32".}
-    proc TlsSetValue(dwTlsIndex: TThreadVarSlot, lpTlsValue: pointer) {.
-      importc: "TlsSetValue", stdcall, dynlib: "kernel32".}
-    proc TlsGetValue(dwTlsIndex: TThreadVarSlot): pointer {.
-      importc: "TlsGetValue", stdcall, dynlib: "kernel32".}
-    
-    proc ThreadVarAlloc(): TThreadVarSlot {.compilerproc, inline.} =
-      result = TlsAlloc()
-    proc ThreadVarSetValue(s: TThreadVarSlot, value: pointer) {.
-                           compilerproc, inline.} =
-      TlsSetValue(s, value)
-    proc ThreadVarGetValue(s: TThreadVarSlot): pointer {.
-                           compilerproc, inline.} =
-      result = TlsGetValue(s)
-    
-  else:
-    type
-      Tpthread_key {.importc: "pthread_key_t", 
-                     header: "<sys/types.h>".} = distinct int
-      TThreadVarSlot {.compilerproc.} = Tpthread_key
-
-    proc pthread_getspecific(a1: Tpthread_key): pointer {.
-      importc: "pthread_getspecific", header: "<pthread.h>".}
-    proc pthread_key_create(a1: ptr Tpthread_key, 
-                            destruct: proc (x: pointer) {.noconv.}): int32 {.
-      importc: "pthread_key_create", header: "<pthread.h>".}
-    proc pthread_key_delete(a1: Tpthread_key): int32 {.
-      importc: "pthread_key_delete", header: "<pthread.h>".}
-
-    proc pthread_setspecific(a1: Tpthread_key, a2: pointer): int32 {.
-      importc: "pthread_setspecific", header: "<pthread.h>".}
-    
-    proc ThreadVarAlloc(): TThreadVarSlot {.compilerproc, inline.} =
-      discard pthread_key_create(addr(result), nil)
-    proc ThreadVarSetValue(s: TThreadVarSlot, value: pointer) {.
-                           compilerproc, inline.} =
-      discard pthread_setspecific(s, value)
-    proc ThreadVarGetValue(s: TThreadVarSlot): pointer {.compilerproc, inline.} =
-      result = pthread_getspecific(s)
-
diff --git a/lib/system/debugger.nim b/lib/system/debugger.nim
index 01d8bd8a2..2dccd8579 100755
--- a/lib/system/debugger.nim
+++ b/lib/system/debugger.nim
@@ -85,8 +85,7 @@ proc openAppend(filename: string): TFile =
     write(result, "----------------------------------------\n")
 
 proc dbgRepr(p: pointer, typ: PNimType): string =
-  var
-    cl: TReprClosure
+  var cl: TReprClosure
   initReprClosure(cl)
   cl.recDepth = maxDisplayRecDepth
   # locks for the GC turned out to be a bad idea...
@@ -139,8 +138,10 @@ proc dbgShowCurrentProc(dbgFramePointer: PFrame) =
     write(stdout, "*** endb| (procedure name not available) ***\n")
 
 proc dbgShowExecutionPoint() =
-  write(stdout, "*** endb| " & $framePtr.filename & "(" & $framePtr.line &
-                ") " & $framePtr.procname & " ***\n")
+  ThreadGlobals()
+  write(stdout, "*** endb| " & $(||framePtr).filename & 
+                "(" & $(||framePtr).line & ") " & 
+                $(||framePtr).procname & " ***\n")
 
 when defined(windows) or defined(dos) or defined(os2):
   {.define: FileSystemCaseInsensitive.}
@@ -171,9 +172,10 @@ proc fileMatches(c, bp: cstring): bool =
   return true
 
 proc dbgBreakpointReached(line: int): int =
+  ThreadGlobals()
   for i in 0..dbgBPlen-1:
     if line >= dbgBP[i].low and line <= dbgBP[i].high and
-        fileMatches(framePtr.filename, dbgBP[i].filename): return i
+        fileMatches((||framePtr).filename, dbgBP[i].filename): return i
   return -1
 
 proc scanAndAppendWord(src: string, a: var string, start: int): int =
@@ -255,6 +257,7 @@ proc hasExt(s: string): bool =
   return false
 
 proc setBreakPoint(s: string, start: int) =
+  ThreadGlobals()
   var dbgTemp: string
   var i = scanWord(s, dbgTemp, start)
   if i <= start:
@@ -269,7 +272,7 @@ proc setBreakPoint(s: string, start: int) =
   i = scanNumber(s, dbgBP[x].low, i)
   if dbgBP[x].low == 0:
     # set to current line:
-    dbgBP[x].low = framePtr.line
+    dbgBP[x].low = (||framePtr).line
   i = scanNumber(s, dbgBP[x].high, i)
   if dbgBP[x].high == 0: # set to low:
     dbgBP[x].high = dbgBP[x].low
@@ -278,7 +281,7 @@ proc setBreakPoint(s: string, start: int) =
     if not hasExt(dbgTemp): add(dbgTemp, ".nim")
     dbgBP[x].filename = dbgTemp
   else: # use current filename
-    dbgBP[x].filename = $framePtr.filename
+    dbgBP[x].filename = $(||framePtr).filename
   # skip whitespace:
   while s[i] in {' ', '\t'}: inc(i)
   if s[i] != '\0':
@@ -347,9 +350,10 @@ proc dbgStackFrame(s: string, start: int, currFrame: PExtendedFrame) =
 
 proc CommandPrompt() =
   # if we return from this routine, user code executes again
+  ThreadGlobals()
   var
     again = True
-    dbgFramePtr = framePtr # for going down and up the stack
+    dbgFramePtr = ||framePtr # for going down and up the stack
     dbgDown = 0 # how often we did go down
 
   while again:
@@ -366,11 +370,11 @@ proc CommandPrompt() =
       again = false
     of "n", "next":
       dbgState = dbStepOver
-      dbgSkipToFrame = framePtr
+      dbgSkipToFrame = ||framePtr
       again = false
     of "f", "skipcurrent":
       dbgState = dbSkipCurrent
-      dbgSkipToFrame = framePtr.prev
+      dbgSkipToFrame = (||framePtr).prev
       again = false
     of "c", "continue":
       dbgState = dbBreakpoints
@@ -401,7 +405,7 @@ proc CommandPrompt() =
       if dbgDown <= 0:
         debugOut("[Warning] cannot go up any further ")
       else:
-        dbgFramePtr = framePtr
+        dbgFramePtr = ||framePtr
         for j in 0 .. dbgDown-2: # BUGFIX
           dbgFramePtr = dbgFramePtr.prev
         dec(dbgDown)
@@ -442,16 +446,17 @@ proc endbStep() =
   CommandPrompt()
 
 proc checkForBreakpoint() =
-  var i = dbgBreakpointReached(framePtr.line)
+  ThreadGlobals()
+  var i = dbgBreakpointReached((||framePtr).line)
   if i >= 0:
     write(stdout, "*** endb| reached ")
     write(stdout, dbgBP[i].name)
     write(stdout, " in ")
-    write(stdout, framePtr.filename)
+    write(stdout, (||framePtr).filename)
     write(stdout, "(")
-    write(stdout, framePtr.line)
+    write(stdout, (||framePtr).line)
     write(stdout, ") ")
-    write(stdout, framePtr.procname)
+    write(stdout, (||framePtr).procname)
     write(stdout, " ***\n")
     CommandPrompt()
 
@@ -482,7 +487,8 @@ proc endb(line: int) {.compilerproc.} =
   # Thus, it must have as few parameters as possible to keep the
   # code size small!
   # Check if we are at an enabled breakpoint or "in the mood"
-  framePtr.line = line # this is done here for smaller code size!
+  ThreadGlobals()
+  (||framePtr).line = line # this is done here for smaller code size!
   if dbgLineHook != nil: dbgLineHook()
   case dbgState
   of dbStepInto:
@@ -490,7 +496,7 @@ proc endb(line: int) {.compilerproc.} =
     dbgShowExecutionPoint()
     CommandPrompt()
   of dbSkipCurrent, dbStepOver: # skip current routine
-    if framePtr == dbgSkipToFrame:
+    if ||framePtr == dbgSkipToFrame:
       dbgShowExecutionPoint()
       CommandPrompt()
     else: # breakpoints are wanted though (I guess)
diff --git a/lib/system/dyncalls.nim b/lib/system/dyncalls.nim
index fb1130938..447ce3f95 100755
--- a/lib/system/dyncalls.nim
+++ b/lib/system/dyncalls.nim
@@ -12,6 +12,8 @@
 # However, the interface has been designed to take platform differences into
 # account and been ported to all major platforms.
 
+{.push stack_trace: off.}
+
 const
   NilLibHandle: TLibHandle = nil
 
@@ -135,3 +137,6 @@ elif defined(mac):
 
 else:
   {.error: "no implementation for dyncalls".}
+  
+{.pop.}
+
diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim
index ed2ec7ff0..9bdc69569 100755
--- a/lib/system/excpt.nim
+++ b/lib/system/excpt.nim
@@ -13,6 +13,7 @@
 var
   stackTraceNewLine* = "\n" ## undocumented feature; it is replaced by ``<br>``
                             ## for CGI applications
+  isMultiThreaded: bool # true when prog created at least 1 thread
 
 when not defined(windows) or not defined(guiapp):
   proc writeToStdErr(msg: CString) = write(stdout, msg)
@@ -36,30 +37,139 @@ type
   TSafePoint {.compilerproc, final.} = object
     prev: PSafePoint # points to next safe point ON THE STACK
     status: int
-    exc: ref E_Base  # XXX only needed for bootstrapping; unused
     context: C_JmpBuf
 
-#when hasThreadSupport: nil
+when hasThreadSupport:
+  # Support for thread local storage:
+  when defined(windows):
+    type
+      TThreadVarSlot {.compilerproc.} = distinct int32
+
+    proc TlsAlloc(): TThreadVarSlot {.
+      importc: "TlsAlloc", stdcall, dynlib: "kernel32".}
+    proc TlsSetValue(dwTlsIndex: TThreadVarSlot, lpTlsValue: pointer) {.
+      importc: "TlsSetValue", stdcall, dynlib: "kernel32".}
+    proc TlsGetValue(dwTlsIndex: TThreadVarSlot): pointer {.
+      importc: "TlsGetValue", stdcall, dynlib: "kernel32".}
+    
+    proc ThreadVarAlloc(): TThreadVarSlot {.compilerproc, inline.} =
+      result = TlsAlloc()
+    proc ThreadVarSetValue(s: TThreadVarSlot, value: pointer) {.
+                           compilerproc, inline.} =
+      TlsSetValue(s, value)
+    proc ThreadVarGetValue(s: TThreadVarSlot): pointer {.
+                           compilerproc, inline.} =
+      result = TlsGetValue(s)
+    
+  else:
+    {.passL: "-pthread".}
+    {.passC: "-pthread".}
+
+    type
+      Tpthread_key {.importc: "pthread_key_t", 
+                     header: "<sys/types.h>".} = distinct int
+      TThreadVarSlot {.compilerproc.} = Tpthread_key
+
+    proc pthread_getspecific(a1: Tpthread_key): pointer {.
+      importc: "pthread_getspecific", header: "<pthread.h>".}
+    proc pthread_key_create(a1: ptr Tpthread_key, 
+                            destruct: proc (x: pointer) {.noconv.}): int32 {.
+      importc: "pthread_key_create", header: "<pthread.h>".}
+    proc pthread_key_delete(a1: Tpthread_key): int32 {.
+      importc: "pthread_key_delete", header: "<pthread.h>".}
+
+    proc pthread_setspecific(a1: Tpthread_key, a2: pointer): int32 {.
+      importc: "pthread_setspecific", header: "<pthread.h>".}
+    
+    proc specificDestroy(mem: pointer) {.noconv.} = dealloc(mem)
+    
+    proc ThreadVarAlloc(): TThreadVarSlot {.compilerproc, inline.} =
+      discard pthread_key_create(addr(result), specificDestroy)
+    proc ThreadVarSetValue(s: TThreadVarSlot, value: pointer) {.
+                           compilerproc, inline.} =
+      discard pthread_setspecific(s, value)
+    proc ThreadVarGetValue(s: TThreadVarSlot): pointer {.compilerproc, inline.} =
+      result = pthread_getspecific(s)
+      
+  type
+    TGlobals {.final, pure.} = object
+      excHandler: PSafePoint
+      currException: ref E_Base
+      framePtr: PFrame
+      buf: string       # cannot be allocated on the stack!
+      assertBuf: string # we need a different buffer for
+                        # assert, as it raises an exception and
+                        # exception handler needs the buffer too
+      gAssertionFailed: ref EAssertionFailed
+      tempFrames: array [0..127, PFrame] # cannot be allocated on the stack!
+      data: float # compiler should add thread local variables here!
+    PGlobals = ptr TGlobals
+
+  var globalsSlot = ThreadVarAlloc()
+  proc CreateThreadLocalStorage*() {.inl.} =
+    isMultiThreaded = true
+    ThreadVarSetValue(globalsSlot, alloc0(sizeof(TGlobals)))
+    
+  proc GetGlobals(): PGlobals {.compilerRtl, inl.} =
+    result = cast[PGlobals](ThreadVarGetValue(globalsSlot))
+
+  # create for the main thread:
+  ThreadVarSetValue(globalsSlot, alloc0(sizeof(TGlobals)))
+
+when hasThreadSupport:
+  template ThreadGlobals = 
+    var globals = GetGlobals()
+  template `||`(varname: expr): expr = globals.varname
+  
+  ThreadGlobals()
+else:
+  template ThreadGlobals = nil # nothing
+  template `||`(varname: expr): expr = varname
 
-var
-  excHandler {.threadvar, compilerproc.}: PSafePoint = nil
-    # list of exception handlers
-    # a global variable for the root of all try blocks
-  currException {.threadvar.}: ref E_Base
+  var
+    framePtr {.compilerproc.}: PFrame # XXX only temporarily a compilerproc
+    excHandler: PSafePoint = nil
+      # list of exception handlers
+      # a global variable for the root of all try blocks
+    currException: ref E_Base
+
+    buf: string       # cannot be allocated on the stack!
+    assertBuf: string # we need a different buffer for
+                      # assert, as it raises an exception and
+                      # exception handler needs the buffer too
+    tempFrames: array [0..127, PFrame] # cannot be allocated on the stack!
+    gAssertionFailed: ref EAssertionFailed
+
+proc pushFrame(s: PFrame) {.compilerRtl, inl.} = 
+  ThreadGlobals()
+  s.prev = ||framePtr
+  ||framePtr = s
+
+proc popFrame {.compilerRtl, inl.} =
+  ThreadGlobals()
+  ||framePtr = (||framePtr).prev
+
+proc setFrame(s: PFrame) {.compilerRtl, inl.} =
+  ThreadGlobals()
+  ||framePtr = s
 
 proc pushSafePoint(s: PSafePoint) {.compilerRtl, inl.} = 
-  s.prev = excHandler
-  excHandler = s
+  ThreadGlobals()
+  s.prev = ||excHandler
+  ||excHandler = s
 
 proc popSafePoint {.compilerRtl, inl.} =
-  excHandler = excHandler.prev
+  ThreadGlobals()
+  ||excHandler = (||excHandler).prev
 
 proc pushCurrentException(e: ref E_Base) {.compilerRtl, inl.} = 
-  e.parent = currException
-  currException = e
+  ThreadGlobals()
+  e.parent = ||currException
+  ||currException = e
 
 proc popCurrentException {.compilerRtl, inl.} =
-  currException = currException.parent
+  ThreadGlobals()
+  ||currException = (||currException).parent
 
 # some platforms have native support for stack traces:
 const
@@ -80,11 +190,16 @@ when defined(nativeStacktrace) and nativeStackTraceSupported:
   proc dladdr(addr1: pointer, info: ptr TDl_info): int {.
     importc: "dladdr", header: "<dlfcn.h>".}
 
-  var
-    tempAddresses: array [0..127, pointer] # cannot be allocated on the stack!
-    tempDlInfo: TDl_info
+  when not hasThreadSupport:
+    var
+      tempAddresses: array [0..127, pointer] # should not be alloc'd on stack
+      tempDlInfo: TDl_info
 
   proc auxWriteStackTraceWithBacktrace(s: var string) =
+    when hasThreadSupport:
+      var
+        tempAddresses: array [0..127, pointer] # but better than a threadvar
+        tempDlInfo: TDl_info
     # This is allowed to be expensive since it only happens during crashes
     # (but this way you don't need manual stack tracing)
     var size = backtrace(cast[ptr pointer](addr(tempAddresses)), 
@@ -108,24 +223,18 @@ when defined(nativeStacktrace) and nativeStackTraceSupported:
           # Once we're past signalHandler, we're at what the user is
           # interested in
           enabled = true
-
-var
-  buf: string       # cannot be allocated on the stack!
-  assertBuf: string # we need a different buffer for
-                    # assert, as it raises an exception and
-                    # exception handler needs the buffer too
-  tempFrames: array [0..127, PFrame] # cannot be allocated on the stack!
   
 proc auxWriteStackTrace(f: PFrame, s: var string) =
   const 
     firstCalls = 32
+  ThreadGlobals()  
   var
     it = f
     i = 0
     total = 0
-  while it != nil and i <= high(tempFrames)-(firstCalls-1):
+  while it != nil and i <= high(||tempFrames)-(firstCalls-1):
     # the (-1) is for a nil entry that marks where the '...' should occur
-    tempFrames[i] = it
+    (||tempFrames)[i] = it
     inc(i)
     inc(total)
     it = it.prev
@@ -136,37 +245,38 @@ proc auxWriteStackTrace(f: PFrame, s: var string) =
   for j in 1..total-i-(firstCalls-1): 
     if b != nil: b = b.prev
   if total != i:
-    tempFrames[i] = nil
+    (||tempFrames)[i] = nil
     inc(i)
-  while b != nil and i <= high(tempFrames):
-    tempFrames[i] = b
+  while b != nil and i <= high(||tempFrames):
+    (||tempFrames)[i] = b
     inc(i)
     b = b.prev
   for j in countdown(i-1, 0):
-    if tempFrames[j] == nil: 
+    if (||tempFrames)[j] == nil: 
       add(s, "(")
       add(s, $(total-i-1))
       add(s, " calls omitted) ...")
     else:
       var oldLen = s.len
-      add(s, tempFrames[j].filename)
-      if tempFrames[j].line > 0:
+      add(s, (||tempFrames)[j].filename)
+      if (||tempFrames)[j].line > 0:
         add(s, '(')
-        add(s, $tempFrames[j].line)
+        add(s, $(||tempFrames)[j].line)
         add(s, ')')
       for k in 1..max(1, 25-(s.len-oldLen)): add(s, ' ')
-      add(s, tempFrames[j].procname)
+      add(s, (||tempFrames)[j].procname)
     add(s, stackTraceNewLine)
 
 proc rawWriteStackTrace(s: var string) =
   when nimrodStackTrace:
-    if framePtr == nil:
+    ThreadGlobals()
+    if ||framePtr == nil:
       add(s, "No stack traceback available")
       add(s, stackTraceNewLine)
     else:
       add(s, "Traceback (most recent call last)")
       add(s, stackTraceNewLine)
-      auxWriteStackTrace(framePtr, s)
+      auxWriteStackTrace(||framePtr, s)
   elif defined(nativeStackTrace) and nativeStackTraceSupported:
     add(s, "Traceback from system (most recent call last)")
     add(s, stackTraceNewLine)
@@ -184,53 +294,53 @@ proc quitOrDebug() {.inline.} =
 proc raiseException(e: ref E_Base, ename: CString) {.compilerRtl.} =
   GC_disable() # a bad thing is an error in the GC while raising an exception
   e.name = ename
-  if excHandler != nil:
+  ThreadGlobals()
+  if ||excHandler != nil:
     pushCurrentException(e)
-    c_longjmp(excHandler.context, 1)
+    c_longjmp((||excHandler).context, 1)
   else:
-    if not isNil(buf):
-      setLen(buf, 0)
-      rawWriteStackTrace(buf)
+    if not isNil(||buf):
+      setLen(||buf, 0)
+      rawWriteStackTrace(||buf)
       if e.msg != nil and e.msg[0] != '\0':
-        add(buf, "Error: unhandled exception: ")
-        add(buf, $e.msg)
+        add(||buf, "Error: unhandled exception: ")
+        add(||buf, $e.msg)
       else:
-        add(buf, "Error: unhandled exception")
-      add(buf, " [")
-      add(buf, $ename)
-      add(buf, "]\n")
-      writeToStdErr(buf)
+        add(||buf, "Error: unhandled exception")
+      add(||buf, " [")
+      add(||buf, $ename)
+      add(||buf, "]\n")
+      writeToStdErr(||buf)
     else:
       writeToStdErr(ename)
     quitOrDebug()
   GC_enable()
 
 proc reraiseException() {.compilerRtl.} =
-  if currException == nil:
+  ThreadGlobals()
+  if ||currException == nil:
     raise newException(ENoExceptionToReraise, "no exception to reraise")
   else:
-    raiseException(currException, currException.name)
-
-var
-  gAssertionFailed: ref EAssertionFailed
+    raiseException(||currException, (||currException).name)
 
 proc internalAssert(file: cstring, line: int, cond: bool) {.compilerproc.} =
   if not cond:
+    ThreadGlobals()    
     #c_fprintf(c_stdout, "Assertion failure: file %s line %ld\n", file, line)
     #quit(1)
     GC_disable() # BUGFIX: `$` allocates a new string object!
-    if not isNil(assertBuf):
+    if not isNil(||assertBuf):
       # BUGFIX: when debugging the GC, assertBuf may be nil
-      setLen(assertBuf, 0)
-      add(assertBuf, "[Assertion failure] file: ")
-      add(assertBuf, file)
-      add(assertBuf, " line: ")
-      add(assertBuf, $line)
-      add(assertBuf, "\n")
-      gAssertionFailed.msg = assertBuf
+      setLen(||assertBuf, 0)
+      add(||assertBuf, "[Assertion failure] file: ")
+      add(||assertBuf, file)
+      add(||assertBuf, " line: ")
+      add(||assertBuf, $line)
+      add(||assertBuf, "\n")
+      (||gAssertionFailed).msg = ||assertBuf
     GC_enable()
-    if gAssertionFailed != nil:
-      raise gAssertionFailed
+    if ||gAssertionFailed != nil:
+      raise ||gAssertionFailed
     else:
       c_fprintf(c_stdout, "Assertion failure: file %s line %ld\n", file, line)
       quit(1)
@@ -245,23 +355,24 @@ var
 
 proc signalHandler(sig: cint) {.exportc: "signalHandler", noconv.} =
   # print stack trace and quit
+  ThreadGlobals()
   var s = sig
   GC_disable()
-  setLen(buf, 0)
-  rawWriteStackTrace(buf)
+  setLen(||buf, 0)
+  rawWriteStackTrace(||buf)
 
-  if s == SIGINT: add(buf, "SIGINT: Interrupted by Ctrl-C.\n")
+  if s == SIGINT: add(||buf, "SIGINT: Interrupted by Ctrl-C.\n")
   elif s == SIGSEGV: 
-    add(buf, "SIGSEGV: Illegal storage access. (Attempt to read from nil?)\n")
+    add(||buf, "SIGSEGV: Illegal storage access. (Attempt to read from nil?)\n")
   elif s == SIGABRT:
     if dbgAborting: return # the debugger wants to abort
-    add(buf, "SIGABRT: Abnormal termination.\n")
-  elif s == SIGFPE: add(buf, "SIGFPE: Arithmetic error.\n")
-  elif s == SIGILL: add(buf, "SIGILL: Illegal operation.\n")
+    add(||buf, "SIGABRT: Abnormal termination.\n")
+  elif s == SIGFPE: add(||buf, "SIGFPE: Arithmetic error.\n")
+  elif s == SIGILL: add(||buf, "SIGILL: Illegal operation.\n")
   elif s == SIGBUS: 
-    add(buf, "SIGBUS: Illegal storage access. (Attempt to read from nil?)\n")
-  else: add(buf, "unknown signal\n")
-  writeToStdErr(buf)
+    add(||buf, "SIGBUS: Illegal storage access. (Attempt to read from nil?)\n")
+  else: add(||buf, "unknown signal\n")
+  writeToStdErr(||buf)
   dbgAborting = True # play safe here...
   GC_enable()
   quit(1) # always quit when SIGABRT
@@ -278,11 +389,9 @@ when not defined(noSignalHandler):
   registerSignalHandler() # call it in initialization section
 # for easier debugging of the GC, this memory is only allocated after the
 # signal handlers have been registered
-new(gAssertionFailed)
-buf = newString(2048)
-assertBuf = newString(2048)
-setLen(buf, 0)
-setLen(assertBuf, 0)
+new(||gAssertionFailed)
+||buf = newStringOfCap(2000)
+||assertBuf = newStringOfCap(2000)
 
 proc raiseRangeError(val: biggestInt) {.compilerproc, noreturn, noinline.} =
   raise newException(EOutOfRange, "value " & $val & " out of range")
diff --git a/lib/system/gc.nim b/lib/system/gc.nim
index 7c70ccf85..52de66d48 100755
--- a/lib/system/gc.nim
+++ b/lib/system/gc.nim
@@ -391,7 +391,7 @@ proc newObj(typ: PNimType, size: int): pointer {.compilerRtl.} =
   assert((cast[TAddress](res) and (MemAlign-1)) == 0)
   # now it is buffered in the ZCT
   res.typ = typ
-  when debugGC:
+  when debugGC and not hasThreadSupport:
     if framePtr != nil and framePtr.prev != nil:
       res.filename = framePtr.prev.filename
       res.line = framePtr.prev.line
diff --git a/lib/system/hti.nim b/lib/system/hti.nim
index d22109061..c6ea0bc44 100755
--- a/lib/system/hti.nim
+++ b/lib/system/hti.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nimrod's Runtime Library
-#        (c) Copyright 2009 Andreas Rumpf
+#        (c) Copyright 2011 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
diff --git a/lib/system/systhread.nim b/lib/system/systhread.nim
index fa2d75704..d9b340ce2 100755
--- a/lib/system/systhread.nim
+++ b/lib/system/systhread.nim
@@ -23,9 +23,6 @@ else:
     inc(p, val)
     result = p
 
-var
-  isMultiThreaded: bool # true when prog created at least 1 thread
-
 proc atomicInc(memLoc: var int, x: int): int =
   when hasThreadSupport:
     result = sync_add_and_fetch(memLoc, x)