summary refs log tree commit diff stats
path: root/lib/system
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2010-09-19 21:35:44 +0200
committerAraq <rumpf_a@web.de>2010-09-19 21:35:44 +0200
commit93b3c03dbd104786a2aaa46f924e1c2c479c1fa1 (patch)
treecd95778c0581a2c0897b41269db2be08ec3db982 /lib/system
parentc06569459819a2aba1a287c7f38904c40c5152d4 (diff)
downloadNim-93b3c03dbd104786a2aaa46f924e1c2c479c1fa1.tar.gz
threading code deactivated; tiny C bugfix: don't report warnings to error callback
Diffstat (limited to 'lib/system')
-rwxr-xr-xlib/system/ecmasys.nim77
-rwxr-xr-xlib/system/excpt.nim72
-rwxr-xr-xlib/system/gc.nim28
-rwxr-xr-xlib/system/systhread.nim21
4 files changed, 119 insertions, 79 deletions
diff --git a/lib/system/ecmasys.nim b/lib/system/ecmasys.nim
index c0d0a5fd6..e2ecb370a 100755
--- a/lib/system/ecmasys.nim
+++ b/lib/system/ecmasys.nim
@@ -1,26 +1,12 @@
 #
 #
 #            Nimrod's Runtime Library
-#        (c) Copyright 2008 Andreas Rumpf
+#        (c) Copyright 2010 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
 #
 
-## Stubs for the GC interface:
-
-proc GC_disable() = nil
-proc GC_enable() = nil
-proc GC_fullCollect() = nil
-proc GC_setStrategy(strategy: TGC_Strategy) = nil
-proc GC_enableMarkAndSweep() = nil
-proc GC_disableMarkAndSweep() = nil
-proc GC_getStatistics(): string = return ""
-
-proc getOccupiedMem(): int = return -1
-proc getFreeMem(): int = return -1
-proc getTotalMem(): int = return -1
-
 proc alert(s: cstring) {.importc, nodecl.}
 
 type
@@ -130,8 +116,6 @@ proc raiseIndexError() {.compilerproc, noreturn.} =
 proc raiseFieldError(f: string) {.compilerproc, noreturn.} =
   raise newException(EInvalidField, f & " is not accessible")
 
-
-
 proc SetConstr() {.varargs, pure, compilerproc.} =
   asm """
     var result = {};
@@ -317,61 +301,58 @@ proc ewriteln(x: cstring) =
   else: 
     raise newException(EInvalidValue, "<body> element does not exist yet!")
 
-proc echo*(x: int) = ewriteln($x)
-proc echo*(x: float) = ewriteln($x)
-proc echo*(x: bool) = ewriteln(if x: cstring("true") else: cstring("false"))
-proc echo*(x: string) = ewriteln(x)
-proc echo*(x: cstring) = ewriteln(x)
-
-proc echo[Ty](x: Ty) =
-  echo(x)
-
-proc echo[Ty](x: openArray[Ty]) =
-  for a in items(x): echo(a)
+proc rawEcho {.compilerproc.} =
+  var node = document.getElementsByTagName("body")[0]
+  if node == nil: raise newException(EIO, "<body> element does not exist yet!")
+  asm """
+    for (var i = 0; i < arguments.length; ++i) {
+      var x = `toEcmaStr`(arguments[i]);
+      `node`.appendChild(document.createTextNode(x))
+    }
+  """
+  node.appendChild(document.createElement("br"))
 
 # Arithmetic:
 proc addInt(a, b: int): int {.pure, compilerproc.} =
   asm """
     var result = `a` + `b`;
-    if (result > 2147483647 || result < -2147483648) raiseOverflow();
+    if (result > 2147483647 || result < -2147483648) `raiseOverflow`();
     return result;
   """
 
 proc subInt(a, b: int): int {.pure, compilerproc.} =
   asm """
     var result = `a` - `b`;
-    if (result > 2147483647 || result < -2147483648) raiseOverflow();
+    if (result > 2147483647 || result < -2147483648) `raiseOverflow`();
     return result;
   """
 
 proc mulInt(a, b: int): int {.pure, compilerproc.} =
   asm """
     var result = `a` * `b`;
-    if (result > 2147483647 || result < -2147483648) raiseOverflow();
+    if (result > 2147483647 || result < -2147483648) `raiseOverflow`();
     return result;
   """
 
 proc divInt(a, b: int): int {.pure, compilerproc.} =
   asm """
-    if (`b` == 0) raiseDivByZero();
-    if (`b` == -1 && `a` == 2147483647) raiseOverflow();
+    if (`b` == 0) `raiseDivByZero`();
+    if (`b` == -1 && `a` == 2147483647) `raiseOverflow`();
     return Math.floor(`a` / `b`);
   """
 
 proc modInt(a, b: int): int {.pure, compilerproc.} =
   asm """
-    if (`b` == 0) raiseDivByZero();
-    if (`b` == -1 && `a` == 2147483647) raiseOverflow();
+    if (`b` == 0) `raiseDivByZero`();
+    if (`b` == -1 && `a` == 2147483647) `raiseOverflow`();
     return Math.floor(`a` % `b`);
   """
 
-
-
 proc addInt64(a, b: int): int {.pure, compilerproc.} =
   asm """
     var result = `a` + `b`;
     if (result > 9223372036854775807
-    || result < -9223372036854775808) raiseOverflow();
+    || result < -9223372036854775808) `raiseOverflow`();
     return result;
   """
 
@@ -379,7 +360,7 @@ proc subInt64(a, b: int): int {.pure, compilerproc.} =
   asm """
     var result = `a` - `b`;
     if (result > 9223372036854775807
-    || result < -9223372036854775808) raiseOverflow();
+    || result < -9223372036854775808) `raiseOverflow`();
     return result;
   """
 
@@ -387,21 +368,21 @@ proc mulInt64(a, b: int): int {.pure, compilerproc.} =
   asm """
     var result = `a` * `b`;
     if (result > 9223372036854775807
-    || result < -9223372036854775808) raiseOverflow();
+    || result < -9223372036854775808) `raiseOverflow`();
     return result;
   """
 
 proc divInt64(a, b: int): int {.pure, compilerproc.} =
   asm """
-    if (`b` == 0) raiseDivByZero();
-    if (`b` == -1 && `a` == 9223372036854775807) raiseOverflow();
+    if (`b` == 0) `raiseDivByZero`();
+    if (`b` == -1 && `a` == 9223372036854775807) `raiseOverflow`();
     return Math.floor(`a` / `b`);
   """
 
 proc modInt64(a, b: int): int {.pure, compilerproc.} =
   asm """
-    if (`b` == 0) raiseDivByZero();
-    if (`b` == -1 && `a` == 9223372036854775807) raiseOverflow();
+    if (`b` == 0) `raiseDivByZero`();
+    if (`b` == -1 && `a` == 9223372036854775807) `raiseOverflow`();
     return Math.floor(`a` % `b`);
   """
 
@@ -415,13 +396,13 @@ proc internalAssert(file: cstring, line: int) {.pure, compilerproc.} =
   asm """`e`.message = "[Assertion failure] file: "+`file`+", line: "+`line`"""
   raise e
 
-include hti
+include "system/hti"
 
 proc isFatPointer(ti: PNimType): bool =
   # This has to be consistent with the code generator!
-  return ti.base.kind notin {tyRecord, tyRecordConstr, tyObject,
+  return ti.base.kind notin {tyObject,
     tyArray, tyArrayConstr, tyPureObject, tyTuple,
-    tyEmptySet, tyOpenArray, tySet, tyVar, tyRef, tyPtr}
+    tyOpenArray, tySet, tyVar, tyRef, tyPtr}
 
 proc NimCopy(x: pointer, ti: PNimType): pointer {.compilerproc.}
 
@@ -452,7 +433,7 @@ proc NimCopy(x: pointer, ti: PNimType): pointer =
         `result`[0] = `x`[0];
         `result`[1] = `x`[1];
       """
-  of tyEmptySet, tySet:
+  of tySet:
     asm """
       `result` = {};
       for (var key in `x`) { `result`[key] = `x`[key]; }
diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim
index c473c42f0..65e233476 100755
--- a/lib/system/excpt.nim
+++ b/lib/system/excpt.nim
@@ -10,6 +10,10 @@
 # Exception handling code. This is difficult because it has
 # to work if there is no more memory (but it doesn't yet!).
 
+var
+  stackTraceNewLine* = "\n" ## undocumented feature; it is replaced by ``<br>``
+                            ## for CGI applications
+
 when not defined(windows) or not defined(guiapp):
   proc writeToStdErr(msg: CString) = write(stdout, msg)
 
@@ -32,7 +36,7 @@ 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
+    exc: ref E_Base  # XXX only needed for bootstrapping; unused
     context: C_JmpBuf
 
 var
@@ -55,6 +59,58 @@ proc pushCurrentException(e: ref E_Base) {.compilerRtl, inl.} =
 proc popCurrentException {.compilerRtl, inl.} =
   currException = currException.parent
 
+# some platforms have native support for stack traces:
+const
+  nimrodStackTrace = compileOption("stacktrace")
+  nativeStackTrace = (defined(macosx) or defined(linux)) and 
+                     not nimrodStackTrace and false
+
+# `nativeStackTrace` does not work for me --> deactivated for now. Maybe for 
+# the next release version.
+
+when nativeStacktrace:
+  type
+    TDl_info {.importc: "Dl_info", header: "<dlfcn.h>", 
+               final, pure.} = object
+      dli_fname: CString
+      dli_fbase: pointer
+      dli_sname: CString
+      dli_saddr: pointer
+
+  proc backtrace(symbols: ptr pointer, size: int): int {.
+    importc: "backtrace", header: "<execinfo.h>".}
+  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
+
+  proc auxWriteStackTraceWithBacktrace(s: var string) =
+    # 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)), 
+                         len(tempAddresses))
+    var enabled = false
+    for i in 0..size-1:
+      var dlresult = dladdr(tempAddresses[i], addr(tempDlInfo))
+      if enabled:
+        if dlresult != 0:
+          var oldLen = s.len
+          add(s, tempDlInfo.dli_fname)
+          if tempDlInfo.dli_sname != nil:
+            for k in 1..max(1, 25-(s.len-oldLen)): add(s, ' ')
+            add(s, tempDlInfo.dli_sname)
+        else:
+          add(s, '?')
+        add(s, stackTraceNewLine)
+      else:
+        if dlresult != 0 and tempDlInfo.dli_sname != nil and
+            c_strcmp(tempDlInfo.dli_sname, "signalHandler") == 0'i32:
+          # Once we're past signalHandler, we're at what the user is
+          # interested in
+          enabled = true
+
 type
   PFrame = ptr TFrame
   TFrame {.importc, nodecl, final.} = object
@@ -74,9 +130,6 @@ var
 
   tempFrames: array [0..127, PFrame] # cannot be allocated on the stack!
   
-  stackTraceNewLine* = "\n" ## undocumented feature; it is replaced by ``<br>``
-                            ## for CGI applications
-
 proc auxWriteStackTrace(f: PFrame, s: var string) =
   const 
     firstCalls = 32
@@ -120,7 +173,7 @@ proc auxWriteStackTrace(f: PFrame, s: var string) =
     add(s, stackTraceNewLine)
 
 proc rawWriteStackTrace(s: var string) =
-  when compileOption("stacktrace") or compileOption("linetrace"):
+  when nimrodStackTrace:
     if framePtr == nil:
       add(s, "No stack traceback available")
       add(s, stackTraceNewLine)
@@ -128,6 +181,10 @@ proc rawWriteStackTrace(s: var string) =
       add(s, "Traceback (most recent call last)")
       add(s, stackTraceNewLine)
       auxWriteStackTrace(framePtr, s)
+  elif nativeStackTrace:
+    add(s, "Traceback from system (most recent call last)")
+    add(s, stackTraceNewLine)
+    auxWriteStackTraceWithBacktrace(s)
   else:
     add(s, "No stack traceback available")
     add(s, stackTraceNewLine)
@@ -197,11 +254,6 @@ proc WriteStackTrace() =
   rawWriteStackTrace(s)
   writeToStdErr(s)
 
-#proc stackTraceWrapper {.noconv.} =
-#  writeStackTrace()
-
-#addQuitProc(stackTraceWrapper)
-
 var
   dbgAborting: bool # whether the debugger wants to abort
 
diff --git a/lib/system/gc.nim b/lib/system/gc.nim
index 0c403b4bc..c0461d89d 100755
--- a/lib/system/gc.nim
+++ b/lib/system/gc.nim
@@ -77,14 +77,16 @@ var
     # collection, not a lock for threads!
 
 proc lock(gch: var TGcHeap) {.inline.} = 
-  if isMultiThreaded: 
-    Lock(gch.zctLock)
-    lock(gch.cycleRootsLock)
+  when hasThreadSupport:
+    if isMultiThreaded: 
+      Lock(gch.zctLock)
+      lock(gch.cycleRootsLock)
 
 proc unlock(gch: var TGcHeap) {.inline.} = 
-  if isMultiThreaded: 
-    unlock(gch.zctLock)
-    unlock(gch.cycleRootsLock)
+  when hasThreadSupport:
+    if isMultiThreaded: 
+      unlock(gch.zctLock)
+      unlock(gch.cycleRootsLock)
 
 proc addZCT(s: var TCellSeq, c: PCell) {.noinline.} =
   if (c.refcount and rcZct) == 0:
@@ -202,15 +204,19 @@ proc prepareDealloc(cell: PCell) =
 
 proc rtlAddCycleRoot(c: PCell) {.rtl, inl.} = 
   # we MUST access gch as a global here, because this crosses DLL boundaries!
-  if isMultiThreaded: Lock(gch.cycleRootsLock)
+  when hasThreadSupport:
+    if isMultiThreaded: Lock(gch.cycleRootsLock)
   incl(gch.cycleRoots, c)
-  if isMultiThreaded: Unlock(gch.cycleRootsLock)
+  when hasThreadSupport:  
+    if isMultiThreaded: Unlock(gch.cycleRootsLock)
 
 proc rtlAddZCT(c: PCell) {.rtl, inl.} =
   # we MUST access gch as a global here, because this crosses DLL boundaries!
-  if isMultiThreaded: Lock(gch.zctLock)
+  when hasThreadSupport:
+    if isMultiThreaded: Lock(gch.zctLock)
   addZCT(gch.zct, c)
-  if isMultiThreaded: Unlock(gch.zctLock)
+  when hasThreadSupport:
+    if isMultiThreaded: Unlock(gch.zctLock)
 
 proc decRef(c: PCell) {.inline.} =
   when stressGC:
@@ -480,7 +486,7 @@ proc gcMark(p: pointer) {.inline.} =
       add(gch.decStack, cell)
 
 proc markThreadStacks(gch: var TGcHeap) = 
-  when isMultiThreaded:
+  when hasThreadSupport:
     nil
 
 # ----------------- stack management --------------------------------------
diff --git a/lib/system/systhread.nim b/lib/system/systhread.nim
index 583cd2a43..af001985e 100755
--- a/lib/system/systhread.nim
+++ b/lib/system/systhread.nim
@@ -7,12 +7,17 @@
 #    distribution, for details about the copyright.
 #
 
-when defined(gcc) or defined(llvm_gcc):
+const
+  hasThreadSupport = false # deactivate for now: thread stack walking
+                           # is missing!
+  maxThreads = 256
+
+when (defined(gcc) or defined(llvm_gcc)) and hasThreadSupport:
   proc sync_add_and_fetch(p: var int, val: int): int {.
     importc: "__sync_add_and_fetch", nodecl.}
   proc sync_sub_and_fetch(p: var int, val: int): int {.
     importc: "__sync_sub_and_fetch", nodecl.}
-elif defined(vcc):
+elif defined(vcc) and hasThreadSupport:
   proc sync_add_and_fetch(p: var int, val: int): int {.
     importc: "NimXadd", nodecl.}
 else:
@@ -20,19 +25,18 @@ else:
     inc(p, val)
     result = p
 
-const
-  isMultiThreaded* = true
-  maxThreads = 256
+var
+  isMultiThreaded: bool # true when prog created at least 1 thread
 
 proc atomicInc(memLoc: var int, x: int): int =
-  when isMultiThreaded:
+  when hasThreadSupport:
     result = sync_add_and_fetch(memLoc, x)
   else:
     inc(memLoc, x)
     result = memLoc
   
 proc atomicDec(memLoc: var int, x: int): int =
-  when isMultiThreaded:
+  when hasThreadSupport:
     when defined(sync_sub_and_fetch):
       result = sync_sub_and_fetch(memLoc, x)
     else:
@@ -85,11 +89,8 @@ type
   TThreadFunc* = proc (closure: pointer) {.cdecl.}
   
 proc createThread*(t: var TThread, fn: TThreadFunc) = 
-  
   nil
   
 proc destroyThread*(t: var TThread) =
   nil
 
-
-