diff options
Diffstat (limited to 'lib/system')
-rw-r--r-- | lib/system/alloc.nim | 4 | ||||
-rw-r--r-- | lib/system/avltree.nim | 8 | ||||
-rw-r--r-- | lib/system/channels.nim | 54 | ||||
-rw-r--r-- | lib/system/deepcopy.nim | 19 | ||||
-rw-r--r-- | lib/system/sysstr.nim | 5 | ||||
-rw-r--r-- | lib/system/threads.nim | 2 |
6 files changed, 55 insertions, 37 deletions
diff --git a/lib/system/alloc.nim b/lib/system/alloc.nim index bed9fd906..745bbbf62 100644 --- a/lib/system/alloc.nim +++ b/lib/system/alloc.nim @@ -101,8 +101,8 @@ type # shared: var - bottomData: AvlNode - bottom: PAvlNode + bottomData {.threadvar.}: AvlNode + bottom {.threadvar.}: PAvlNode {.push stack_trace: off.} proc initAllocator() = diff --git a/lib/system/avltree.nim b/lib/system/avltree.nim index d5c901542..50faada26 100644 --- a/lib/system/avltree.nim +++ b/lib/system/avltree.nim @@ -9,7 +9,7 @@ # not really an AVL tree anymore, but still balanced ... -template isBottom(n: PAvlNode): bool = n == bottom +template isBottom(n: PAvlNode): bool = n.link[0] == n proc lowGauge(n: PAvlNode): int = var it = n @@ -52,7 +52,7 @@ proc split(t: var PAvlNode) = inc t.level proc add(a: var MemRegion, t: var PAvlNode, key, upperBound: int) {.benign.} = - if t == bottom: + if t.isBottom: t = allocAvlNode(a, key, upperBound) else: if key <% t.key: @@ -65,14 +65,14 @@ proc add(a: var MemRegion, t: var PAvlNode, key, upperBound: int) {.benign.} = split(t) proc del(a: var MemRegion, t: var PAvlNode, x: int) {.benign.} = - if t == bottom: return + if isBottom(t): return a.last = t if x <% t.key: del(a, t.link[0], x) else: a.deleted = t del(a, t.link[1], x) - if t == a.last and a.deleted != bottom and x == a.deleted.key: + 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 diff --git a/lib/system/channels.nim b/lib/system/channels.nim index caa709229..0c97bc8db 100644 --- a/lib/system/channels.nim +++ b/lib/system/channels.nim @@ -52,6 +52,7 @@ proc deinitRawChannel(p: pointer) = proc storeAux(dest, src: pointer, mt: PNimType, t: PRawChannel, mode: LoadStoreMode) {.benign.} + proc storeAux(dest, src: pointer, n: ptr TNimNode, t: PRawChannel, mode: LoadStoreMode) {.benign.} = var @@ -71,6 +72,9 @@ proc storeAux(dest, src: pointer, n: ptr TNimNode, t: PRawChannel, proc storeAux(dest, src: pointer, mt: PNimType, t: PRawChannel, mode: LoadStoreMode) = + template `+!`(p: pointer; x: int): pointer = + cast[pointer](cast[int](p) +% x) + var d = cast[ByteAddress](dest) s = cast[ByteAddress](src) @@ -93,7 +97,9 @@ proc storeAux(dest, src: pointer, mt: PNimType, t: PRawChannel, if s2 == nil: unsureAsgnRef(x, s2) else: - unsureAsgnRef(x, copyString(cast[NimString](s2))) + let y = copyDeepString(cast[NimString](s2)) + #echo "loaded ", cast[int](y), " ", cast[string](y) + unsureAsgnRef(x, y) dealloc(t.region, s2) of tySequence: var s2 = cast[PPointer](src)[] @@ -107,26 +113,27 @@ proc storeAux(dest, src: pointer, mt: PNimType, t: PRawChannel, else: sysAssert(dest != nil, "dest == nil") if mode == mStore: - x[] = alloc(t.region, seq.len *% mt.base.size +% GenericSeqSize) + x[] = alloc0(t.region, seq.len *% mt.base.size +% GenericSeqSize) else: unsureAsgnRef(x, newObj(mt, seq.len * mt.base.size + GenericSeqSize)) var dst = cast[ByteAddress](cast[PPointer](dest)[]) + var dstseq = cast[PGenericSeq](dst) + dstseq.len = seq.len + dstseq.reserved = seq.len for i in 0..seq.len-1: storeAux( cast[pointer](dst +% i*% mt.base.size +% GenericSeqSize), cast[pointer](cast[ByteAddress](s2) +% i *% mt.base.size +% GenericSeqSize), mt.base, t, mode) - var dstseq = cast[PGenericSeq](dst) - dstseq.len = seq.len - dstseq.reserved = seq.len if mode != mStore: dealloc(t.region, s2) of tyObject: - # copy type field: - var pint = cast[ptr PNimType](dest) - pint[] = cast[ptr PNimType](src)[] if mt.base != nil: storeAux(dest, src, mt.base, t, mode) + else: + # copy type field: + var pint = cast[ptr PNimType](dest) + pint[] = cast[ptr PNimType](src)[] storeAux(dest, src, mt.node, t, mode) of tyTuple: storeAux(dest, src, mt.node, t, mode) @@ -143,15 +150,24 @@ proc storeAux(dest, src: pointer, mt: PNimType, t: PRawChannel, else: unsureAsgnRef(x, nil) else: - let size = if mt.base.kind == tyObject: cast[ptr PNimType](s)[].size - else: mt.base.size + #let size = if mt.base.kind == tyObject: cast[ptr PNimType](s)[].size + # else: mt.base.size if mode == mStore: - x[] = alloc(t.region, size) + let dyntype = when declared(usrToCell): usrToCell(s).typ + else: mt + let size = dyntype.base.size + # we store the real dynamic 'ref type' at offset 0, so that + # no information is lost + let a = alloc0(t.region, size+sizeof(pointer)) + x[] = a + cast[PPointer](a)[] = dyntype + storeAux(a +! sizeof(pointer), s, dyntype.base, t, mode) else: - var obj = newObj(mt, size) + let dyntype = cast[ptr PNimType](s)[] + var obj = newObj(dyntype, dyntype.base.size) unsureAsgnRef(x, obj) - storeAux(x[], s, mt.base, t, mode) - if mode != mStore: dealloc(t.region, s) + storeAux(x[], s +! sizeof(pointer), dyntype.base, t, mode) + dealloc(t.region, s) else: copyMem(dest, src, mt.size) # copy raw bits @@ -194,10 +210,8 @@ template sendImpl(q: expr) {.immediate.} = if q.mask == ChannelDeadMask: sysFatal(DeadThreadError, "cannot send message; thread died") acquireSys(q.lock) - var m: TMsg - shallowCopy(m, msg) var typ = cast[PNimType](getTypeInfo(msg)) - rawSend(q, addr(m), typ) + rawSend(q, unsafeAddr(msg), typ) q.elemType = typ releaseSys(q.lock) signalSysCond(q.cond) @@ -228,8 +242,10 @@ proc recv*[TMsg](c: var Channel[TMsg]): TMsg = proc tryRecv*[TMsg](c: var Channel[TMsg]): tuple[dataAvailable: bool, msg: TMsg] = - ## try to receives a message from the channel `c` if available. Otherwise - ## it returns ``(false, default(msg))``. + ## try to receives a message from the channel `c`, but this can fail + ## for all sort of reasons, including contention. If it fails, + ## it returns ``(false, default(msg))`` otherwise it + ## returns ``(true, msg)``. var q = cast[PRawChannel](addr(c)) if q.mask != ChannelDeadMask: if tryAcquireSys(q.lock): diff --git a/lib/system/deepcopy.nim b/lib/system/deepcopy.nim index 5445a067c..38cc8cbf3 100644 --- a/lib/system/deepcopy.nim +++ b/lib/system/deepcopy.nim @@ -32,12 +32,6 @@ proc genericDeepCopyAux(dest, src: pointer, n: ptr TNimNode) {.benign.} = genericDeepCopyAux(dest, src, m) of nkNone: sysAssert(false, "genericDeepCopyAux") -proc copyDeepString(src: NimString): NimString {.inline.} = - if src != nil: - result = rawNewStringNoInit(src.len) - result.len = src.len - copyMem(addr(result.data), addr(src.data), src.len + 1) - proc genericDeepCopyAux(dest, src: pointer, mt: PNimType) = var d = cast[ByteAddress](dest) @@ -70,10 +64,11 @@ proc genericDeepCopyAux(dest, src: pointer, mt: PNimType) = 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) + else: + var pint = cast[ptr PNimType](dest) + pint[] = cast[ptr PNimType](src)[] genericDeepCopyAux(dest, src, mt.node) of tyTuple: genericDeepCopyAux(dest, src, mt.node) @@ -103,16 +98,16 @@ proc genericDeepCopyAux(dest, src: pointer, mt: PNimType) = 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) + let size = if mt.base.kind == tyObject: cast[ptr PNimType](s2)[].size + else: mt.base.size + let z = newObj(mt, size) unsureAsgnRef(cast[PPointer](dest), z) - genericDeepCopyAux(z, s2, realType.base) + genericDeepCopyAux(z, s2, mt.base) of tyPtr: # no cycle check here, but also not really required let s2 = cast[PPointer](src)[] diff --git a/lib/system/sysstr.nim b/lib/system/sysstr.nim index 3e170172b..3a93221e0 100644 --- a/lib/system/sysstr.nim +++ b/lib/system/sysstr.nim @@ -110,6 +110,11 @@ proc copyStringRC1(src: NimString): NimString {.compilerRtl.} = result.len = src.len copyMem(addr(result.data), addr(src.data), src.len + 1) +proc copyDeepString(src: NimString): NimString {.inline.} = + if src != nil: + result = rawNewStringNoInit(src.len) + result.len = src.len + copyMem(addr(result.data), addr(src.data), src.len + 1) proc hashString(s: string): int {.compilerproc.} = # the compiler needs exactly the same hash function! diff --git a/lib/system/threads.nim b/lib/system/threads.nim index 62829f62c..6f5bb38b1 100644 --- a/lib/system/threads.nim +++ b/lib/system/threads.nim @@ -356,6 +356,8 @@ proc threadProcWrapStackFrame[TArg](thrd: ptr Thread[TArg]) = template threadProcWrapperBody(closure: expr) {.immediate.} = when declared(globalsSlot): threadVarSetValue(globalsSlot, closure) + when declared(initAllocator): + initAllocator() var thrd = cast[ptr Thread[TArg]](closure) threadProcWrapStackFrame(thrd) # Since an unhandled exception terminates the whole process (!), there is |