diff options
Diffstat (limited to 'lib/system')
-rw-r--r-- | lib/system/ansi_c.nim | 25 | ||||
-rw-r--r-- | lib/system/arithm.nim | 40 | ||||
-rw-r--r-- | lib/system/assign.nim | 4 | ||||
-rw-r--r-- | lib/system/atomics.nim | 56 | ||||
-rw-r--r-- | lib/system/channels.nim | 11 | ||||
-rw-r--r-- | lib/system/deepcopy.nim | 141 | ||||
-rw-r--r-- | lib/system/excpt.nim | 10 | ||||
-rw-r--r-- | lib/system/gc.nim | 4 | ||||
-rw-r--r-- | lib/system/gc2.nim | 2 | ||||
-rw-r--r-- | lib/system/hti.nim | 3 | ||||
-rw-r--r-- | lib/system/jssys.nim | 4 | ||||
-rw-r--r-- | lib/system/mmdisp.nim | 28 | ||||
-rw-r--r-- | lib/system/repr.nim | 16 | ||||
-rw-r--r-- | lib/system/sysspawn.nim | 2 | ||||
-rw-r--r-- | lib/system/sysstr.nim | 4 | ||||
-rw-r--r-- | lib/system/threads.nim | 88 | ||||
-rw-r--r-- | lib/system/widestrs.nim | 8 |
17 files changed, 316 insertions, 130 deletions
diff --git a/lib/system/ansi_c.nim b/lib/system/ansi_c.nim index 511a006d3..673d55582 100644 --- a/lib/system/ansi_c.nim +++ b/lib/system/ansi_c.nim @@ -39,7 +39,7 @@ var c_stderr {.importc: "stderr", nodecl.}: C_TextFileStar # constants faked as variables: -when not defined(SIGINT): +when not declared(SIGINT): when NoFakeVars: when defined(windows): const @@ -78,10 +78,23 @@ when defined(macosx): else: template SIGBUS: expr = SIGSEGV -proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {. - header: "<setjmp.h>", importc: "longjmp".} -proc c_setjmp(jmpb: C_JmpBuf): cint {. - header: "<setjmp.h>", importc: "setjmp".} +when defined(nimSigSetjmp) and not defined(nimStdSetjmp): + proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {. + header: "<setjmp.h>", importc: "siglongjmp".} + template c_setjmp(jmpb: C_JmpBuf): cint = + proc c_sigsetjmp(jmpb: C_JmpBuf, savemask: cint): cint {. + header: "<setjmp.h>", importc: "sigsetjmp".} + c_sigsetjmp(jmpb, 0) +elif defined(nimRawSetjmp) and not defined(nimStdSetjmp): + proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {. + header: "<setjmp.h>", importc: "_longjmp".} + proc c_setjmp(jmpb: C_JmpBuf): cint {. + header: "<setjmp.h>", importc: "_setjmp".} +else: + proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {. + header: "<setjmp.h>", importc: "longjmp".} + proc c_setjmp(jmpb: C_JmpBuf): cint {. + header: "<setjmp.h>", importc: "setjmp".} proc c_signal(sig: cint, handler: proc (a: cint) {.noconv.}) {. importc: "signal", header: "<signal.h>".} @@ -132,7 +145,7 @@ proc c_realloc(p: pointer, newsize: int): pointer {. importc: "realloc", header: "<stdlib.h>".} when hostOS != "standalone": - when not defined(errno): + when not declared(errno): when defined(NimrodVM): var vmErrnoWrapper {.importc.}: ptr cint template errno: expr = diff --git a/lib/system/arithm.nim b/lib/system/arithm.nim index d9b3aebac..7672947cd 100644 --- a/lib/system/arithm.nim +++ b/lib/system/arithm.nim @@ -114,63 +114,69 @@ when asmVersion and not defined(gcc) and not defined(llvm_gcc): proc addInt(a, b: int): int {.compilerProc, asmNoStackFrame.} = # a in eax, and b in edx asm """ - mov eax, `a` - add eax, `b` + mov eax, ecx + add eax, edx jno theEnd call `raiseOverflow` theEnd: + ret """ proc subInt(a, b: int): int {.compilerProc, asmNoStackFrame.} = asm """ - mov eax, `a` - sub eax, `b` + mov eax, ecx + sub eax, edx jno theEnd call `raiseOverflow` theEnd: + ret """ proc negInt(a: int): int {.compilerProc, asmNoStackFrame.} = asm """ - mov eax, `a` + mov eax, ecx neg eax jno theEnd call `raiseOverflow` theEnd: + ret """ proc divInt(a, b: int): int {.compilerProc, asmNoStackFrame.} = asm """ - mov eax, `a` - mov ecx, `b` + mov eax, ecx + mov ecx, edx xor edx, edx idiv ecx jno theEnd call `raiseOverflow` theEnd: + ret """ proc modInt(a, b: int): int {.compilerProc, asmNoStackFrame.} = asm """ - mov eax, `a` - mov ecx, `b` + mov eax, ecx + mov ecx, edx xor edx, edx idiv ecx jno theEnd call `raiseOverflow` theEnd: mov eax, edx + ret """ proc mulInt(a, b: int): int {.compilerProc, asmNoStackFrame.} = asm """ - mov eax, `a` - mov ecx, `b` + mov eax, ecx + mov ecx, edx xor edx, edx imul ecx jno theEnd call `raiseOverflow` theEnd: + ret """ elif false: # asmVersion and (defined(gcc) or defined(llvm_gcc)): @@ -241,26 +247,26 @@ elif false: # asmVersion and (defined(gcc) or defined(llvm_gcc)): """ # Platform independent versions of the above (slower!) -when not defined(addInt): +when not declared(addInt): proc addInt(a, b: int): int {.compilerProc, inline.} = result = a +% b if (result xor a) >= 0 or (result xor b) >= 0: return result raiseOverflow() -when not defined(subInt): +when not declared(subInt): proc subInt(a, b: int): int {.compilerProc, inline.} = result = a -% b if (result xor a) >= 0 or (result xor not b) >= 0: return result raiseOverflow() -when not defined(negInt): +when not declared(negInt): proc negInt(a: int): int {.compilerProc, inline.} = if a != low(int): return -a raiseOverflow() -when not defined(divInt): +when not declared(divInt): proc divInt(a, b: int): int {.compilerProc, inline.} = if b == 0: raiseDivByZero() @@ -268,13 +274,13 @@ when not defined(divInt): raiseOverflow() return a div b -when not defined(modInt): +when not declared(modInt): proc modInt(a, b: int): int {.compilerProc, inline.} = if b == 0: raiseDivByZero() return a mod b -when not defined(mulInt): +when not declared(mulInt): # # This code has been inspired by Python's source code. # The native int product x*y is either exactly right or *way* off, being diff --git a/lib/system/assign.nim b/lib/system/assign.nim index 2ae945fb1..0e27eb57f 100644 --- a/lib/system/assign.nim +++ b/lib/system/assign.nim @@ -89,14 +89,10 @@ proc genericAssignAux(dest, src: pointer, mt: PNimType, shallow: bool) = copyMem(dest, src, mt.size) # copy raw bits proc genericAssign(dest, src: pointer, mt: PNimType) {.compilerProc.} = - GC_disable() genericAssignAux(dest, src, mt, false) - GC_enable() proc genericShallowAssign(dest, src: pointer, mt: PNimType) {.compilerProc.} = - GC_disable() genericAssignAux(dest, src, mt, true) - GC_enable() when false: proc debugNimType(t: PNimType) = diff --git a/lib/system/atomics.nim b/lib/system/atomics.nim index 43b3f0438..3ef9d00ec 100644 --- a/lib/system/atomics.nim +++ b/lib/system/atomics.nim @@ -7,30 +7,36 @@ # distribution, for details about the copyright. # -## Atomic operations for Nimrod. +# Atomic operations for Nimrod. {.push stackTrace:off.} const someGcc = defined(gcc) or defined(llvm_gcc) or defined(clang) when someGcc and hasThreadSupport: - type - AtomMemModel* = enum - ATOMIC_RELAXED, ## No barriers or synchronization. - ATOMIC_CONSUME, ## Data dependency only for both barrier and - ## synchronization with another thread. - ATOMIC_ACQUIRE, ## Barrier to hoisting of code and synchronizes with - ## release (or stronger) - ## semantic stores from another thread. - ATOMIC_RELEASE, ## Barrier to sinking of code and synchronizes with - ## acquire (or stronger) - ## semantic loads from another thread. - ATOMIC_ACQ_REL, ## Full barrier in both directions and synchronizes - ## with acquire loads - ## and release stores in another thread. - ATOMIC_SEQ_CST ## Full barrier in both directions and synchronizes - ## with acquire loads - ## and release stores in all threads. - + type AtomMemModel* = distinct cint + var ATOMIC_RELAXED* {.importc: "__ATOMIC_RELAXED", nodecl.}: AtomMemModel + ## No barriers or synchronization. + var ATOMIC_CONSUME* {.importc: "__ATOMIC_CONSUME", nodecl.}: AtomMemModel + ## Data dependency only for both barrier and + ## synchronization with another thread. + var ATOMIC_ACQUIRE* {.importc: "__ATOMIC_ACQUIRE", nodecl.}: AtomMemModel + ## Barrier to hoisting of code and synchronizes with + ## release (or stronger) + ## semantic stores from another thread. + var ATOMIC_RELEASE* {.importc: "__ATOMIC_RELEASE", nodecl.}: AtomMemModel + ## Barrier to sinking of code and synchronizes with + ## acquire (or stronger) + ## semantic loads from another thread. + var ATOMIC_ACQ_REL* {.importc: "__ATOMIC_ACQ_REL", nodecl.}: AtomMemModel + ## Full barrier in both directions and synchronizes + ## with acquire loads + ## and release stores in another thread. + var ATOMIC_SEQ_CST* {.importc: "__ATOMIC_SEQ_CST", nodecl.}: AtomMemModel + ## Full barrier in both directions and synchronizes + ## with acquire loads + ## and release stores in all threads. + + type TAtomType* = TNumber|pointer|ptr|char ## Type Class representing valid types for use with atomic procs @@ -166,15 +172,15 @@ else: result = p[] proc atomicInc*(memLoc: var int, x: int = 1): int = - when defined(gcc) and hasThreadSupport: + when someGcc and hasThreadSupport: result = atomic_add_fetch(memLoc.addr, x, ATOMIC_RELAXED) else: inc(memLoc, x) result = memLoc proc atomicDec*(memLoc: var int, x: int = 1): int = - when defined(gcc) and hasThreadSupport: - when defined(atomic_sub_fetch): + when someGcc and hasThreadSupport: + when declared(atomic_sub_fetch): result = atomic_sub_fetch(memLoc.addr, x, ATOMIC_RELAXED) else: result = atomic_add_fetch(memLoc.addr, -x, ATOMIC_RELAXED) @@ -196,19 +202,19 @@ else: # XXX is this valid for 'int'? -when (defined(x86) or defined(amd64)) and (defined(gcc) or defined(llvm_gcc)): +when (defined(x86) or defined(amd64)) and someGcc: proc cpuRelax {.inline.} = {.emit: """asm volatile("pause" ::: "memory");""".} elif (defined(x86) or defined(amd64)) and defined(vcc): proc cpuRelax {.importc: "YieldProcessor", header: "<windows.h>".} -elif defined(intelc): +elif defined(icl): proc cpuRelax {.importc: "_mm_pause", header: "xmmintrin.h".} elif false: from os import sleep proc cpuRelax {.inline.} = os.sleep(1) -when not defined(fence) and hasThreadSupport: +when not declared(fence) and hasThreadSupport: # XXX fixme proc fence*() {.inline.} = var dummy: bool diff --git a/lib/system/channels.nim b/lib/system/channels.nim index e5535dbdc..a5d5c0802 100644 --- a/lib/system/channels.nim +++ b/lib/system/channels.nim @@ -14,7 +14,7 @@ ## **Note:** The current implementation of message passing is slow and does ## not work with cyclic data structures. -when not defined(NimString): +when not declared(NimString): {.error: "You must not import this module explicitly".} type @@ -226,15 +226,16 @@ proc recv*[TMsg](c: var TChannel[TMsg]): TMsg = llRecv(q, addr(result), cast[PNimType](getTypeInfo(result))) releaseSys(q.lock) -proc tryRecv*[TMsg](c: var TChannel[TMsg]): tuple[dataAvaliable: bool, +proc tryRecv*[TMsg](c: var TChannel[TMsg]): tuple[dataAvailable: bool, msg: TMsg] = ## try to receives a message from the channel `c` if available. Otherwise ## it returns ``(false, default(msg))``. var q = cast[PRawChannel](addr(c)) - if q.mask != ChannelDeadMask: - lockChannel(q): + if q.mask != ChannelDeadMask: + if tryAcquireSys(q.lock): llRecv(q, addr(result.msg), cast[PNimType](getTypeInfo(result.msg))) - result.dataAvaliable = true + result.dataAvailable = true + releaseSys(q.lock) proc peek*[TMsg](c: var TChannel[TMsg]): int = ## returns the current number of messages in the channel `c`. Returns -1 diff --git a/lib/system/deepcopy.nim b/lib/system/deepcopy.nim new file mode 100644 index 000000000..e7eb1cdb4 --- /dev/null +++ b/lib/system/deepcopy.nim @@ -0,0 +1,141 @@ +# +# +# Nimrod's Runtime Library +# (c) Copyright 2014 Andreas Rumpf +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +proc genericDeepCopyAux(dest, src: pointer, mt: PNimType) {.gcsafe.} +proc genericDeepCopyAux(dest, src: pointer, n: ptr TNimNode) {.gcsafe.} = + var + d = cast[TAddress](dest) + s = cast[TAddress](src) + case n.kind + of nkSlot: + genericDeepCopyAux(cast[pointer](d +% n.offset), + cast[pointer](s +% n.offset), n.typ) + of nkList: + for i in 0..n.len-1: + genericDeepCopyAux(dest, src, n.sons[i]) + of nkCase: + var dd = selectBranch(dest, n) + var m = selectBranch(src, n) + # reset if different branches are in use; note different branches also + # imply that's not self-assignment (``x = x``)! + if m != dd and dd != nil: + genericResetAux(dest, dd) + copyMem(cast[pointer](d +% n.offset), cast[pointer](s +% n.offset), + n.typ.size) + if m != nil: + genericDeepCopyAux(dest, src, m) + of nkNone: sysAssert(false, "genericDeepCopyAux") + +proc copyDeepString(src: NimString): NimString {.inline.} = + if src != nil: + result = rawNewString(src.space) + result.len = src.len + c_memcpy(result.data, src.data, (src.len + 1) * sizeof(char)) + +proc genericDeepCopyAux(dest, src: pointer, mt: PNimType) = + var + d = cast[TAddress](dest) + s = cast[TAddress](src) + sysAssert(mt != nil, "genericDeepCopyAux 2") + case mt.kind + of tyString: + var x = cast[PPointer](dest) + var s2 = cast[PPointer](s)[] + if s2 == nil: + unsureAsgnRef(x, s2) + else: + unsureAsgnRef(x, copyDeepString(cast[NimString](s2))) + of tySequence: + var s2 = cast[PPointer](src)[] + var seq = cast[PGenericSeq](s2) + var x = cast[PPointer](dest) + if s2 == nil: + unsureAsgnRef(x, s2) + return + sysAssert(dest != nil, "genericDeepCopyAux 3") + unsureAsgnRef(x, newSeq(mt, seq.len)) + var dst = cast[TAddress](cast[PPointer](dest)[]) + for i in 0..seq.len-1: + genericDeepCopyAux( + cast[pointer](dst +% i*% mt.base.size +% GenericSeqSize), + cast[pointer](cast[TAddress](s2) +% i *% mt.base.size +% + GenericSeqSize), + mt.base) + of tyObject: + # we need to copy m_type field for tyObject, as it could be empty for + # sequence reallocations: + var pint = cast[ptr PNimType](dest) + pint[] = cast[ptr PNimType](src)[] + if mt.base != nil: + genericDeepCopyAux(dest, src, mt.base) + genericDeepCopyAux(dest, src, mt.node) + of tyTuple: + genericDeepCopyAux(dest, src, mt.node) + of tyArray, tyArrayConstr: + for i in 0..(mt.size div mt.base.size)-1: + genericDeepCopyAux(cast[pointer](d +% i*% mt.base.size), + cast[pointer](s +% i*% mt.base.size), mt.base) + of tyRef: + if mt.base.deepCopy != nil: + let z = mt.base.deepCopy(cast[PPointer](src)[]) + unsureAsgnRef(cast[PPointer](dest), z) + else: + # we modify the header of the cell temporarily; instead of the type + # field we store a forwarding pointer. XXX This is bad when the cloning + # fails due to OOM etc. + let s2 = cast[PPointer](src)[] + if s2 == nil: + unsureAsgnRef(cast[PPointer](dest), s2) + return + when declared(usrToCell): + # unfortunately we only have cycle detection for our native GCs. + let x = usrToCell(s2) + let forw = cast[int](x.typ) + if (forw and 1) == 1: + # we stored a forwarding pointer, so let's use that: + let z = cast[pointer](forw and not 1) + unsureAsgnRef(cast[PPointer](dest), z) + else: + let realType = x.typ + let z = newObj(realType, realType.base.size) + + unsureAsgnRef(cast[PPointer](dest), z) + x.typ = cast[PNimType](cast[int](z) or 1) + genericDeepCopyAux(z, s2, realType.base) + x.typ = realType + else: + let realType = mt + let z = newObj(realType, realType.base.size) + unsureAsgnRef(cast[PPointer](dest), z) + genericDeepCopyAux(z, s2, realType.base) + of tyPtr: + # no cycle check here, but also not really required + if mt.base.deepCopy != nil: + cast[PPointer](dest)[] = mt.base.deepCopy(cast[PPointer](s)[]) + else: + cast[PPointer](dest)[] = cast[PPointer](s)[] + else: + copyMem(dest, src, mt.size) + +proc genericDeepCopy(dest, src: pointer, mt: PNimType) {.compilerProc.} = + genericDeepCopyAux(dest, src, mt) + +proc genericSeqDeepCopy(dest, src: pointer, mt: PNimType) {.compilerProc.} = + # also invoked for 'string' + var src = src + genericDeepCopy(dest, addr(src), mt) + +proc genericDeepCopyOpenArray(dest, src: pointer, len: int, + mt: PNimType) {.compilerproc.} = + var + d = cast[TAddress](dest) + s = cast[TAddress](src) + for i in 0..len-1: + genericDeepCopy(cast[pointer](d +% i*% mt.base.size), + cast[pointer](s +% i*% mt.base.size), mt.base) diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim index e1a5a958f..3c5436afb 100644 --- a/lib/system/excpt.nim +++ b/lib/system/excpt.nim @@ -38,11 +38,11 @@ proc chckRangeF(x, a, b: float): float {.inline, compilerproc, gcsafe.} proc chckNil(p: pointer) {.noinline, compilerproc, gcsafe.} var - framePtr {.rtlThreadVar.}: PFrame - excHandler {.rtlThreadVar.}: PSafePoint + framePtr {.threadvar.}: PFrame + excHandler {.threadvar.}: PSafePoint # list of exception handlers # a global variable for the root of all try blocks - currException {.rtlThreadVar.}: ref E_Base + currException {.threadvar.}: ref E_Base proc popFrame {.compilerRtl, inl.} = framePtr = framePtr.prev @@ -307,7 +307,7 @@ when not defined(noSignalHandler): action("SIGBUS: Illegal storage access. (Attempt to read from nil?)\n") else: block platformSpecificSignal: - when defined(SIGPIPE): + when declared(SIGPIPE): if s == SIGPIPE: action("SIGPIPE: Pipe closed.\n") break platformSpecificSignal @@ -336,7 +336,7 @@ when not defined(noSignalHandler): c_signal(SIGFPE, signalHandler) c_signal(SIGILL, signalHandler) c_signal(SIGBUS, signalHandler) - when defined(SIGPIPE): + when declared(SIGPIPE): c_signal(SIGPIPE, signalHandler) registerSignalHandler() # call it in initialization section diff --git a/lib/system/gc.nim b/lib/system/gc.nim index 3b85fe600..0c1fc7748 100644 --- a/lib/system/gc.nim +++ b/lib/system/gc.nim @@ -30,7 +30,7 @@ const # cycles instead of the complex # algorithm -when withRealTime and not defined(getTicks): +when withRealTime and not declared(getTicks): include "system/timers" when defined(memProfiler): proc nimProfile(requestedSize: int) @@ -413,7 +413,7 @@ proc addNewObjToZCT(res: PCell, gch: var TGcHeap) {.inline.} = {.push stackTrace: off, profiler:off.} proc gcInvariant*() = sysAssert(allocInv(gch.region), "injected") - when defined(markForDebug): + when declared(markForDebug): markForDebug(gch) {.pop.} diff --git a/lib/system/gc2.nim b/lib/system/gc2.nim index 31c99a601..132da9885 100644 --- a/lib/system/gc2.nim +++ b/lib/system/gc2.nim @@ -26,7 +26,7 @@ const # this seems to be a good value withRealTime = defined(useRealtimeGC) -when withRealTime and not defined(getTicks): +when withRealTime and not declared(getTicks): include "system/timers" when defined(memProfiler): proc nimProfile(requestedSize: int) diff --git a/lib/system/hti.nim b/lib/system/hti.nim index 64174e60f..ef8f50831 100644 --- a/lib/system/hti.nim +++ b/lib/system/hti.nim @@ -7,7 +7,7 @@ # distribution, for details about the copyright. # -when defined(NimString): +when declared(NimString): # we are in system module: {.pragma: codegenType, compilerproc.} else: @@ -86,6 +86,7 @@ type node: ptr TNimNode # valid for tyRecord, tyObject, tyTuple, tyEnum finalizer: pointer # the finalizer for the type marker: proc (p: pointer, op: int) {.nimcall, gcsafe.} # marker proc for GC + deepcopy: proc (p: pointer): pointer {.nimcall, gcsafe.} PNimType = ptr TNimType # node.len may be the ``first`` element of a set diff --git a/lib/system/jssys.nim b/lib/system/jssys.nim index 8766906e3..423f63e2a 100644 --- a/lib/system/jssys.nim +++ b/lib/system/jssys.nim @@ -515,7 +515,7 @@ proc isFatPointer(ti: PNimType): bool = proc nimCopy(x: pointer, ti: PNimType): pointer {.compilerproc.} -proc nimCopyAux(dest, src: Pointer, n: ptr TNimNode) {.compilerproc.} = +proc nimCopyAux(dest, src: pointer, n: ptr TNimNode) {.compilerproc.} = case n.kind of nkNone: sysAssert(false, "nimCopyAux") of nkSlot: @@ -566,7 +566,7 @@ proc nimCopy(x: pointer, ti: PNimType): pointer = else: result = x -proc genericReset(x: Pointer, ti: PNimType): pointer {.compilerproc.} = +proc genericReset(x: pointer, ti: PNimType): pointer {.compilerproc.} = case ti.kind of tyPtr, tyRef, tyVar, tyNil: if not isFatPointer(ti): diff --git a/lib/system/mmdisp.nim b/lib/system/mmdisp.nim index a09b6cf93..606743f51 100644 --- a/lib/system/mmdisp.nim +++ b/lib/system/mmdisp.nim @@ -131,6 +131,14 @@ when defined(boehmgc): if result == nil: raiseOutOfMem() proc deallocShared(p: pointer) = boehmDealloc(p) + when hasThreadSupport: + proc getFreeSharedMem(): int = + boehmGetFreeBytes() + proc getTotalSharedMem(): int = + boehmGetHeapSize() + proc getOccupiedSharedMem(): int = + getTotalSharedMem() - getFreeSharedMem() + #boehmGCincremental() proc GC_disable() = boehmGC_disable() @@ -164,11 +172,11 @@ when defined(boehmgc): proc nimGCref(p: pointer) {.compilerproc, inline.} = discard proc nimGCunref(p: pointer) {.compilerproc, inline.} = discard - proc unsureAsgnRef(dest: ppointer, src: pointer) {.compilerproc, inline.} = + proc unsureAsgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} = dest[] = src - proc asgnRef(dest: ppointer, src: pointer) {.compilerproc, inline.} = + proc asgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} = dest[] = src - proc asgnRefNoCycle(dest: ppointer, src: pointer) {.compilerproc, inline.} = + proc asgnRefNoCycle(dest: PPointer, src: pointer) {.compilerproc, inline.} = dest[] = src type @@ -180,7 +188,7 @@ when defined(boehmgc): proc alloc0(r: var TMemRegion, size: int): pointer = result = alloc(size) zeroMem(result, size) - proc dealloc(r: var TMemRegion, p: Pointer) = boehmDealloc(p) + proc dealloc(r: var TMemRegion, p: pointer) = boehmDealloc(p) proc deallocOsPages(r: var TMemRegion) {.inline.} = discard proc deallocOsPages() {.inline.} = discard @@ -239,11 +247,11 @@ elif defined(nogc) and defined(useMalloc): proc nimGCref(p: pointer) {.compilerproc, inline.} = discard proc nimGCunref(p: pointer) {.compilerproc, inline.} = discard - proc unsureAsgnRef(dest: ppointer, src: pointer) {.compilerproc, inline.} = + proc unsureAsgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} = dest[] = src - proc asgnRef(dest: ppointer, src: pointer) {.compilerproc, inline.} = + proc asgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} = dest[] = src - proc asgnRefNoCycle(dest: ppointer, src: pointer) {.compilerproc, inline.} = + proc asgnRefNoCycle(dest: PPointer, src: pointer) {.compilerproc, inline.} = dest[] = src type @@ -292,11 +300,11 @@ elif defined(nogc): proc nimGCref(p: pointer) {.compilerproc, inline.} = discard proc nimGCunref(p: pointer) {.compilerproc, inline.} = discard - proc unsureAsgnRef(dest: ppointer, src: pointer) {.compilerproc, inline.} = + proc unsureAsgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} = dest[] = src - proc asgnRef(dest: ppointer, src: pointer) {.compilerproc, inline.} = + proc asgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} = dest[] = src - proc asgnRefNoCycle(dest: ppointer, src: pointer) {.compilerproc, inline.} = + proc asgnRefNoCycle(dest: PPointer, src: pointer) {.compilerproc, inline.} = dest[] = src var allocator {.rtlThreadVar.}: TMemRegion diff --git a/lib/system/repr.nim b/lib/system/repr.nim index f8f949668..8e1bc5f26 100644 --- a/lib/system/repr.nim +++ b/lib/system/repr.nim @@ -121,7 +121,7 @@ proc reprSet(p: pointer, typ: PNimType): string {.compilerRtl.} = type TReprClosure {.final.} = object # we cannot use a global variable here # as this wouldn't be thread-safe - when defined(TCellSet): + when declared(TCellSet): marked: TCellSet recdepth: int # do not recurse endlessly indent: int # indentation @@ -130,16 +130,16 @@ when not defined(useNimRtl): proc initReprClosure(cl: var TReprClosure) = # Important: cellsets does not lock the heap when doing allocations! We # have to do it here ... - when hasThreadSupport and hasSharedHeap and defined(heapLock): + when hasThreadSupport and hasSharedHeap and declared(heapLock): AcquireSys(HeapLock) - when defined(TCellSet): + when declared(TCellSet): init(cl.marked) cl.recdepth = -1 # default is to display everything! cl.indent = 0 proc deinitReprClosure(cl: var TReprClosure) = - when defined(TCellSet): deinit(cl.marked) - when hasThreadSupport and hasSharedHeap and defined(heapLock): + when declared(TCellSet): deinit(cl.marked) + when hasThreadSupport and hasSharedHeap and declared(heapLock): ReleaseSys(HeapLock) proc reprBreak(result: var string, cl: TReprClosure) = @@ -201,7 +201,7 @@ when not defined(useNimRtl): proc reprRef(result: var string, p: pointer, typ: PNimType, cl: var TReprClosure) = # we know that p is not nil here: - when defined(TCellSet): + when declared(TCellSet): when defined(boehmGC) or defined(nogc): var cell = cast[PCell](p) else: @@ -221,7 +221,7 @@ when not defined(useNimRtl): dec(cl.recdepth) case typ.kind of tySet: reprSetAux(result, p, typ) - of tyArray: reprArray(result, p, typ, cl) + of tyArray, tyArrayConstr: reprArray(result, p, typ, cl) of tyTuple: reprRecord(result, p, typ, cl) of tyObject: var t = cast[ptr PNimType](p)[] @@ -275,7 +275,7 @@ when not defined(useNimRtl): cl: TReprClosure initReprClosure(cl) result = "" - if typ.kind in {tyObject, tyTuple, tyArray, tySet}: + if typ.kind in {tyObject, tyTuple, tyArray, tyArrayConstr, tySet}: reprAux(result, p, typ, cl) else: var p = p diff --git a/lib/system/sysspawn.nim b/lib/system/sysspawn.nim index 95cdba65d..5161104a9 100644 --- a/lib/system/sysspawn.nim +++ b/lib/system/sysspawn.nim @@ -9,7 +9,7 @@ ## Implements Nimrod's 'spawn'. -when not defined(NimString): +when not declared(NimString): {.error: "You must not import this module explicitly".} {.push stackTrace:off.} diff --git a/lib/system/sysstr.nim b/lib/system/sysstr.nim index 9db8ce378..bc79bb254 100644 --- a/lib/system/sysstr.nim +++ b/lib/system/sysstr.nim @@ -32,7 +32,7 @@ proc eqStrings(a, b: NimString): bool {.inline, compilerProc.} = return a.len == b.len and c_memcmp(a.data, b.data, a.len * sizeof(char)) == 0'i32 -when defined(allocAtomic): +when declared(allocAtomic): template allocStr(size: expr): expr = cast[NimString](allocAtomic(size)) else: @@ -85,7 +85,7 @@ proc copyStringRC1(src: NimString): NimString {.compilerRtl.} = if src != nil: var s = src.space if s < 8: s = 7 - when defined(newObjRC1): + when declared(newObjRC1): result = cast[NimString](newObjRC1(addr(strDesc), sizeof(TGenericSeq) + s+1)) else: diff --git a/lib/system/threads.nim b/lib/system/threads.nim index d3b3aa457..c30c57fb9 100644 --- a/lib/system/threads.nim +++ b/lib/system/threads.nim @@ -1,17 +1,17 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2012 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. # -## Thread support for Nimrod. **Note**: This is part of the system module. +## Thread support for Nim. **Note**: This is part of the system module. ## Do not import it directly. To activate thread support you need to compile ## with the ``--threads:on`` command line switch. ## -## Nimrod's memory model for threads is quite different from other common +## Nim's memory model for threads is quite different from other common ## programming languages (C, Pascal): Each thread has its own ## (garbage collected) heap and sharing of memory is restricted. This helps ## to prevent race conditions and improves efficiency. See `the manual for @@ -19,7 +19,7 @@ ## ## Example: ## -## .. code-block:: nimrod +## .. code-block:: Nim ## ## import locks ## @@ -39,7 +39,7 @@ ## createThread(thr[i], threadFunc, (i*10, i*10+5)) ## joinThreads(thr) -when not defined(NimString): +when not declared(NimString): {.error: "You must not import this module explicitly".} const @@ -190,7 +190,7 @@ var globalsSlot = threadVarAlloc() when emulatedThreadVars: proc GetThreadLocalVars(): pointer {.compilerRtl, inl.} = - result = addr(cast[PGcThread](ThreadVarGetValue(globalsSlot)).tls) + result = addr(cast[PGcThread](threadVarGetValue(globalsSlot)).tls) when useStackMaskHack: proc maskStackPointer(offset: int): pointer {.compilerRtl, inl.} = @@ -210,7 +210,7 @@ when not defined(useNimRtl): initGC() when emulatedThreadVars: - if NimThreadVarsSize() > sizeof(TThreadLocalStorage): + if nimThreadVarsSize() > sizeof(TThreadLocalStorage): echo "too large thread local storage size requested" quit 1 @@ -245,14 +245,14 @@ when not defined(useNimRtl): # the GC can examine the stacks? proc stopTheWord() = discard -# We jump through some hops here to ensure that Nimrod thread procs can have -# the Nimrod calling convention. This is needed because thread procs are +# We jump through some hops here to ensure that Nim thread procs can have +# the Nim calling convention. This is needed because thread procs are # ``stdcall`` on Windows and ``noconv`` on UNIX. Alternative would be to just # use ``stdcall`` since it is mapped to ``noconv`` on UNIX anyway. type TThread* {.pure, final.}[TArg] = - object of TGcThread ## Nimrod thread. A thread is a heavy object (~14K) + object of TGcThread ## Nim thread. A thread is a heavy object (~14K) ## that **must not** be part of a message! Use ## a ``TThreadId`` for that. when TArg is void: @@ -267,7 +267,7 @@ when not defined(boehmgc) and not hasSharedHeap: proc deallocOsPages() template threadProcWrapperBody(closure: expr) {.immediate.} = - when defined(globalsSlot): ThreadVarSetValue(globalsSlot, closure) + when declared(globalsSlot): threadVarSetValue(globalsSlot, closure) var t = cast[ptr TThread[TArg]](closure) when useStackMaskHack: var tls: TThreadLocalStorage @@ -275,13 +275,13 @@ template threadProcWrapperBody(closure: expr) {.immediate.} = # init the GC for this thread: setStackBottom(addr(t)) initGC() - when defined(registerThread): + when declared(registerThread): t.stackBottom = addr(t) registerThread(t) when TArg is void: t.dataFn() else: t.dataFn(t.data) - when defined(registerThread): unregisterThread(t) - when defined(deallocOsPages): deallocOsPages() + when declared(registerThread): unregisterThread(t) + when declared(deallocOsPages): deallocOsPages() # Since an unhandled exception terminates the whole process (!), there is # no need for a ``try finally`` here, nor would it be correct: The current # exception is tried to be re-raised by the code-gen after the ``finally``! @@ -305,22 +305,26 @@ proc running*[TArg](t: TThread[TArg]): bool {.inline.} = ## returns true if `t` is running. result = t.dataFn != nil -proc joinThread*[TArg](t: TThread[TArg]) {.inline.} = - ## waits for the thread `t` to finish. - when hostOS == "windows": +when hostOS == "windows": + proc joinThread*[TArg](t: TThread[TArg]) {.inline.} = + ## waits for the thread `t` to finish. discard waitForSingleObject(t.sys, -1'i32) - else: - discard pthread_join(t.sys, nil) -proc joinThreads*[TArg](t: varargs[TThread[TArg]]) = - ## waits for every thread in `t` to finish. - when hostOS == "windows": + proc joinThreads*[TArg](t: varargs[TThread[TArg]]) = + ## waits for every thread in `t` to finish. var a: array[0..255, TSysThread] sysAssert a.len >= t.len, "a.len >= t.len" for i in 0..t.high: a[i] = t[i].sys - discard waitForMultipleObjects(t.len.int32, + discard waitForMultipleObjects(t.len.int32, cast[ptr TSysThread](addr(a)), 1, -1) - else: + +else: + proc joinThread*[TArg](t: TThread[TArg]) {.inline.} = + ## waits for the thread `t` to finish. + discard pthread_join(t.sys, nil) + + proc joinThreads*[TArg](t: varargs[TThread[TArg]]) = + ## waits for every thread in `t` to finish. for i in 0..t.high: joinThread(t[i]) when false: @@ -332,25 +336,35 @@ when false: discard TerminateThread(t.sys, 1'i32) else: discard pthread_cancel(t.sys) - when defined(registerThread): unregisterThread(addr(t)) + when declared(registerThread): unregisterThread(addr(t)) t.dataFn = nil -proc createThread*[TArg](t: var TThread[TArg], - tp: proc (arg: TArg) {.thread.}, - param: TArg) = - ## 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. - when TArg isnot void: t.data = param - t.dataFn = tp - when hasSharedHeap: t.stackSize = ThreadStackSize - when hostOS == "windows": +when hostOS == "windows": + proc createThread*[TArg](t: var TThread[TArg], + tp: proc (arg: TArg) {.thread.}, + param: TArg) = + ## 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. + when TArg isnot void: t.data = param + t.dataFn = tp + when hasSharedHeap: t.stackSize = ThreadStackSize var dummyThreadId: int32 t.sys = createThread(nil, ThreadStackSize, threadProcWrapper[TArg], addr(t), 0'i32, dummyThreadId) if t.sys <= 0: raise newException(EResourceExhausted, "cannot create thread") - else: + +else: + proc createThread*[TArg](t: var TThread[TArg], + tp: proc (arg: TArg) {.thread.}, + param: TArg) = + ## 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. + when TArg isnot void: t.data = param + t.dataFn = tp + when hasSharedHeap: t.stackSize = ThreadStackSize var a {.noinit.}: Tpthread_attr pthread_attr_init(a) pthread_attr_setstacksize(a, ThreadStackSize) @@ -364,7 +378,7 @@ proc threadId*[TArg](t: var TThread[TArg]): TThreadId[TArg] {.inline.} = proc myThreadId*[TArg](): TThreadId[TArg] = ## returns the thread ID of the thread that calls this proc. This is unsafe ## because the type ``TArg`` is not checked for consistency! - result = cast[TThreadId[TArg]](ThreadVarGetValue(globalsSlot)) + result = cast[TThreadId[TArg]](threadVarGetValue(globalsSlot)) when false: proc mainThreadId*[TArg](): TThreadId[TArg] = diff --git a/lib/system/widestrs.nim b/lib/system/widestrs.nim index e2a5d87e9..cd64ff410 100644 --- a/lib/system/widestrs.nim +++ b/lib/system/widestrs.nim @@ -7,10 +7,10 @@ # distribution, for details about the copyright. # -## Nimrod support for C/C++'s `wide strings`:idx:. This is part of the system -## module! Do not import it directly! +# Nimrod support for C/C++'s `wide strings`:idx:. This is part of the system +# module! Do not import it directly! -when not defined(NimString): +when not declared(NimString): {.error: "You must not import this module explicitly".} type @@ -103,7 +103,7 @@ proc newWideCString*(source: cstring, L: int): WideCString = proc newWideCString*(s: cstring): WideCString = if s.isNil: return nil - when not defined(c_strlen): + when not declared(c_strlen): proc c_strlen(a: cstring): int {. header: "<string.h>", noSideEffect, importc: "strlen".} |