summary refs log tree commit diff stats
path: root/lib/system
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2011-07-18 23:59:39 +0200
committerAraq <rumpf_a@web.de>2011-07-18 23:59:39 +0200
commit81a917390bdb61d07310c8faf31092f65acbfb53 (patch)
tree479042020adbe5b92b518733a80a3b9164c0abe4 /lib/system
parent42e6130b2c37345963c0b5469e12a287b88bf3eb (diff)
downloadNim-81a917390bdb61d07310c8faf31092f65acbfb53.tar.gz
shared untraced heap; bugfix: mem corruptions in message passing code
Diffstat (limited to 'lib/system')
-rwxr-xr-xlib/system/alloc.nim102
-rwxr-xr-xlib/system/cellsets.nim20
-rwxr-xr-xlib/system/inboxes.nim16
-rwxr-xr-xlib/system/mmdisp.nim33
-rwxr-xr-xlib/system/threads.nim13
5 files changed, 103 insertions, 81 deletions
diff --git a/lib/system/alloc.nim b/lib/system/alloc.nim
index efa372bcd..e3b1d589b 100755
--- a/lib/system/alloc.nim
+++ b/lib/system/alloc.nim
@@ -550,6 +550,35 @@ proc isAllocatedPtr(a: TMemRegion, p: pointer): bool =
         var c = cast[PBigChunk](c)
         result = p == addr(c.data) and cast[ptr TFreeCell](p).zeroField >% 1
 
+proc ptrSize(p: pointer): int =
+  var x = cast[pointer](cast[TAddress](p) -% sizeof(TFreeCell))
+  result = pageAddr(x).size - sizeof(TFreeCell)
+
+proc alloc(allocator: var TMemRegion, size: int): pointer =
+  result = rawAlloc(allocator, size+sizeof(TFreeCell))
+  cast[ptr TFreeCell](result).zeroField = 1 # mark it as used
+  sysAssert(not isAllocatedPtr(allocator, result))
+  result = cast[pointer](cast[TAddress](result) +% sizeof(TFreeCell))
+
+proc alloc0(allocator: var TMemRegion, size: int): pointer =
+  result = alloc(size)
+  zeroMem(result, size)
+
+proc dealloc(allocator: var TMemRegion, p: pointer) =
+  var x = cast[pointer](cast[TAddress](p) -% sizeof(TFreeCell))
+  sysAssert(cast[ptr TFreeCell](x).zeroField == 1)
+  rawDealloc(allocator, x)
+  sysAssert(not isAllocatedPtr(allocator, x))
+
+proc realloc(allocator: var TMemRegion, p: pointer, newsize: int): pointer =
+  if newsize > 0:
+    result = alloc(allocator, newsize)
+    if p != nil:
+      copyMem(result, p, ptrSize(p))
+      dealloc(allocator, p)
+  elif p != nil:
+    dealloc(allocator, p)
+
 proc deallocOsPages(a: var TMemRegion) =
   # we free every 'ordinarily' allocated page by iterating over the page bits:
   for p in elements(a.chunkStarts):
@@ -569,48 +598,17 @@ proc getOccupiedMem(a: TMemRegion): int {.inline.} =
 template InstantiateForRegion(allocator: expr) =
   proc deallocOsPages = deallocOsPages(allocator)
 
-  proc unlockedAlloc(size: int): pointer =
-    result = rawAlloc(allocator, size+sizeof(TFreeCell))
-    cast[ptr TFreeCell](result).zeroField = 1 # mark it as used
-    sysAssert(not isAllocatedPtr(allocator, result))
-    result = cast[pointer](cast[TAddress](result) +% sizeof(TFreeCell))
-
-  proc unlockedAlloc0(size: int): pointer =
-    result = unlockedAlloc(size)
-    zeroMem(result, size)
-
-  proc unlockedDealloc(p: pointer) =
-    var x = cast[pointer](cast[TAddress](p) -% sizeof(TFreeCell))
-    sysAssert(cast[ptr TFreeCell](x).zeroField == 1)
-    rawDealloc(allocator, x)
-    sysAssert(not isAllocatedPtr(allocator, x))
-
   proc alloc(size: int): pointer =
-    when hasThreadSupport and hasSharedHeap: AcquireSys(HeapLock)
-    result = unlockedAlloc(size)
-    when hasThreadSupport and hasSharedHeap: ReleaseSys(HeapLock)
+    result = alloc(allocator, size)
 
   proc alloc0(size: int): pointer =
-    result = alloc(size)
-    zeroMem(result, size)
+    result = alloc0(allocator, size)
 
   proc dealloc(p: pointer) =
-    when hasThreadSupport and hasSharedHeap: AcquireSys(HeapLock)
-    unlockedDealloc(p)
-    when hasThreadSupport and hasSharedHeap: ReleaseSys(HeapLock)
-
-  proc ptrSize(p: pointer): int =
-    var x = cast[pointer](cast[TAddress](p) -% sizeof(TFreeCell))
-    result = pageAddr(x).size - sizeof(TFreeCell)
+    dealloc(allocator, p)
 
   proc realloc(p: pointer, newsize: int): pointer =
-    if newsize > 0:
-      result = alloc(newsize)
-      if p != nil:
-        copyMem(result, p, ptrSize(p))
-        dealloc(p)
-    elif p != nil:
-      dealloc(p)
+    result = realloc(allocator, p, newsize)
 
   when false:
     proc countFreeMem(): int =
@@ -627,3 +625,37 @@ template InstantiateForRegion(allocator: expr) =
   proc getTotalMem(): int = return allocator.currMem
   proc getOccupiedMem(): int = return getTotalMem() - getFreeMem()
 
+  # -------------------- shared heap region ----------------------------------
+  when hasThreadSupport:
+    var sharedHeap: TMemRegion
+    var heapLock: TSysLock
+    InitSysLock(HeapLock)
+
+  proc allocShared(size: int): pointer =
+    when hasThreadSupport:
+      AcquireSys(HeapLock)
+      result = alloc(sharedHeap, size)
+      ReleaseSys(HeapLock)
+    else:
+      result = alloc(size)
+
+  proc allocShared0(size: int): pointer =
+    result = allocShared(size)
+    zeroMem(result, size)
+
+  proc deallocShared(p: pointer) =
+    when hasThreadSupport: 
+      AcquireSys(HeapLock)
+      dealloc(sharedHeap, p)
+      ReleaseSys(HeapLock)
+    else:
+      dealloc(p)
+
+  proc reallocShared(p: pointer, newsize: int): pointer =
+    when hasThreadSupport: 
+      AcquireSys(HeapLock)
+      result = realloc(sharedHeap, p, newsize)
+      ReleaseSys(HeapLock)
+    else:
+      result = realloc(p, newsize)
+
diff --git a/lib/system/cellsets.nim b/lib/system/cellsets.nim
index 7502636fa..b8bfbaf6d 100755
--- a/lib/system/cellsets.nim
+++ b/lib/system/cellsets.nim
@@ -47,9 +47,9 @@ proc contains(s: TCellSeq, c: PCell): bool {.inline.} =
 proc add(s: var TCellSeq, c: PCell) {.inline.} =
   if s.len >= s.cap:
     s.cap = s.cap * 3 div 2
-    var d = cast[PCellArray](unlockedAlloc(s.cap * sizeof(PCell)))
+    var d = cast[PCellArray](Alloc(s.cap * sizeof(PCell)))
     copyMem(d, s.d, s.len * sizeof(PCell))
-    unlockedDealloc(s.d)
+    Dealloc(s.d)
     s.d = d
     # XXX: realloc?
   s.d[s.len] = c
@@ -58,10 +58,10 @@ proc add(s: var TCellSeq, c: PCell) {.inline.} =
 proc init(s: var TCellSeq, cap: int = 1024) =
   s.len = 0
   s.cap = cap
-  s.d = cast[PCellArray](unlockedAlloc0(cap * sizeof(PCell)))
+  s.d = cast[PCellArray](Alloc0(cap * sizeof(PCell)))
 
 proc deinit(s: var TCellSeq) = 
-  unlockedDealloc(s.d)
+  Dealloc(s.d)
   s.d = nil
   s.len = 0
   s.cap = 0
@@ -70,7 +70,7 @@ const
   InitCellSetSize = 1024 # must be a power of two!
 
 proc Init(s: var TCellSet) =
-  s.data = cast[PPageDescArray](unlockedAlloc0(InitCellSetSize * sizeof(PPageDesc)))
+  s.data = cast[PPageDescArray](Alloc0(InitCellSetSize * sizeof(PPageDesc)))
   s.max = InitCellSetSize-1
   s.counter = 0
   s.head = nil
@@ -79,10 +79,10 @@ proc Deinit(s: var TCellSet) =
   var it = s.head
   while it != nil:
     var n = it.next
-    unlockedDealloc(it)
+    Dealloc(it)
     it = n
   s.head = nil # play it safe here
-  unlockedDealloc(s.data)
+  Dealloc(s.data)
   s.data = nil
   s.counter = 0
 
@@ -110,11 +110,11 @@ proc CellSetRawInsert(t: TCellSet, data: PPageDescArray, desc: PPageDesc) =
 proc CellSetEnlarge(t: var TCellSet) =
   var oldMax = t.max
   t.max = ((t.max+1)*2)-1
-  var n = cast[PPageDescArray](unlockedAlloc0((t.max + 1) * sizeof(PPageDesc)))
+  var n = cast[PPageDescArray](Alloc0((t.max + 1) * sizeof(PPageDesc)))
   for i in 0 .. oldmax:
     if t.data[i] != nil:
       CellSetRawInsert(t, n, t.data[i])
-  unlockedDealloc(t.data)
+  Dealloc(t.data)
   t.data = n
 
 proc CellSetPut(t: var TCellSet, key: TAddress): PPageDesc =
@@ -132,7 +132,7 @@ proc CellSetPut(t: var TCellSet, key: TAddress): PPageDesc =
   while t.data[h] != nil: h = nextTry(h, t.max)
   sysAssert(t.data[h] == nil)
   # the new page descriptor goes into result
-  result = cast[PPageDesc](unlockedAlloc0(sizeof(TPageDesc)))
+  result = cast[PPageDesc](Alloc0(sizeof(TPageDesc)))
   result.next = t.head
   result.key = key
   t.head = result
diff --git a/lib/system/inboxes.nim b/lib/system/inboxes.nim
index b2db103cb..d4a4b1eb4 100755
--- a/lib/system/inboxes.nim
+++ b/lib/system/inboxes.nim
@@ -77,7 +77,7 @@ proc storeAux(dest, src: Pointer, mt: PNimType, t: PInbox,
         x[] = nil

       else:

         var ss = cast[NimString](s2)

-        var ns = cast[NimString](rawAlloc(t.region, ss.len+1 + GenericSeqSize))

+        var ns = cast[NimString](Alloc(t.region, ss.len+1 + GenericSeqSize))

         copyMem(ns, ss, ss.len+1 + GenericSeqSize)

         x[] = ns

     else:

@@ -87,7 +87,7 @@ proc storeAux(dest, src: Pointer, mt: PNimType, t: PInbox,
         unsureAsgnRef(x, s2)

       else:

         unsureAsgnRef(x, copyString(cast[NimString](s2)))

-        rawDealloc(t.region, s2)

+        Dealloc(t.region, s2)

   of tySequence:

     var s2 = cast[ppointer](src)[]

     var seq = cast[PGenericSeq](s2)

@@ -100,7 +100,7 @@ proc storeAux(dest, src: Pointer, mt: PNimType, t: PInbox,
     else:

       sysAssert(dest != nil)

       if mode == mStore:

-        x[] = rawAlloc(t.region, seq.len *% mt.base.size +% GenericSeqSize)

+        x[] = Alloc(t.region, seq.len *% mt.base.size +% GenericSeqSize)

       else:

         unsureAsgnRef(x, newObj(mt, seq.len * mt.base.size + GenericSeqSize))

       var dst = cast[taddress](cast[ppointer](dest)[])

@@ -113,7 +113,7 @@ proc storeAux(dest, src: Pointer, mt: PNimType, t: PInbox,
       var dstseq = cast[PGenericSeq](dst)

       dstseq.len = seq.len

       dstseq.space = seq.len

-      if mode != mStore: rawDealloc(t.region, s2)

+      if mode != mStore: Dealloc(t.region, s2)

   of tyObject:

     # copy type field:

     var pint = cast[ptr PNimType](dest)

@@ -136,7 +136,7 @@ proc storeAux(dest, src: Pointer, mt: PNimType, t: PInbox,
         unsureAsgnRef(x, nil)

     else:

       if mode == mStore:

-        x[] = rawAlloc(t.region, mt.base.size)

+        x[] = Alloc(t.region, mt.base.size)

       else:

         # XXX we should use the dynamic type here too, but that is not stored in

         # the inbox at all --> use source[]'s object type? but how? we need a

@@ -144,7 +144,7 @@ proc storeAux(dest, src: Pointer, mt: PNimType, t: PInbox,
         var obj = newObj(mt.base, mt.base.size)

         unsureAsgnRef(x, obj)

       storeAux(x[], s, mt.base, t, mode)

-      if mode != mStore: rawDealloc(t.region, s)

+      if mode != mStore: Dealloc(t.region, s)

   else:

     copyMem(dest, src, mt.size) # copy raw bits

 

@@ -154,7 +154,7 @@ proc rawSend(q: PInbox, data: pointer, typ: PNimType) =
   if q.count >= cap:

     # start with capicity for 2 entries in the queue:

     if cap == 0: cap = 1

-    var n = cast[pbytes](rawAlloc0(q.region, cap*2*typ.size))

+    var n = cast[pbytes](Alloc0(q.region, cap*2*typ.size))

     var z = 0

     var i = q.rd

     var c = q.count

@@ -163,7 +163,7 @@ proc rawSend(q: PInbox, data: pointer, typ: PNimType) =
       copyMem(addr(n[z*typ.size]), addr(q.data[i*typ.size]), typ.size)

       i = (i + 1) and q.mask

       inc z

-    if q.data != nil: rawDealloc(q.region, q.data)

+    if q.data != nil: Dealloc(q.region, q.data)

     q.data = n

     q.mask = cap*2 - 1

     q.wr = q.count

diff --git a/lib/system/mmdisp.nim b/lib/system/mmdisp.nim
index 0cbee1d47..5d1371cf9 100755
--- a/lib/system/mmdisp.nim
+++ b/lib/system/mmdisp.nim
@@ -88,12 +88,18 @@ when defined(boehmgc):
   proc realloc(p: Pointer, newsize: int): pointer =
     result = boehmRealloc(p, newsize)
     if result == nil: raiseOutOfMem()
-  proc dealloc(p: Pointer) =
-    boehmDealloc(p)
+  proc dealloc(p: Pointer) = boehmDealloc(p)
 
-  proc unlockedAlloc(size: int): pointer {.inline.} = result = alloc(size)
-  proc unlockedAlloc0(size: int): pointer {.inline.} = result = alloc0(size)
-  proc unlockedDealloc(p: pointer) {.inline.} = dealloc(p)
+  proc allocShared(size: int): pointer =
+    result = boehmAlloc(size)
+    if result == nil: raiseOutOfMem()
+  proc allocShared0(size: int): pointer =
+    result = alloc(size)
+    zeroMem(result, size)
+  proc reallocShared(p: Pointer, newsize: int): pointer =
+    result = boehmRealloc(p, newsize)
+    if result == nil: raiseOutOfMem()
+  proc deallocShared(p: Pointer) = boehmDealloc(p)
 
   proc initGC() = 
     when defined(macosx): boehmGCinit()
@@ -136,20 +142,13 @@ when defined(boehmgc):
   type
     TMemRegion = object {.final, pure.}
   
-  var
-    dummy {.rtlThreadVar.}: int
-  
-  proc rawAlloc(r: var TMemRegion, size: int): pointer =
+  proc Alloc(r: var TMemRegion, size: int): pointer =
     result = boehmAlloc(size)
     if result == nil: raiseOutOfMem()
-  proc rawAlloc0(r: var TMemRegion, size: int): pointer =
+  proc Alloc0(r: var TMemRegion, size: int): pointer =
     result = alloc(size)
     zeroMem(result, size)
-  proc realloc(r: var TMemRegion, p: Pointer, newsize: int): pointer =
-    result = boehmRealloc(p, newsize)
-    if result == nil: raiseOutOfMem()
-  proc rawDealloc(r: var TMemRegion, p: Pointer) = boehmDealloc(p)
-
+  proc Dealloc(r: var TMemRegion, p: Pointer) = boehmDealloc(p)  
   proc deallocOsPages(r: var TMemRegion) {.inline.} = nil
   proc deallocOsPages() {.inline.} = nil
 
@@ -204,10 +203,6 @@ elif defined(nogc):
 else:
   include "system/alloc"
 
-  proc unlockedAlloc(size: int): pointer {.inline.} 
-  proc unlockedAlloc0(size: int): pointer {.inline.} 
-  proc unlockedDealloc(p: pointer) {.inline.} 
-  
   include "system/cellsets"
   sysAssert(sizeof(TCell) == sizeof(TFreeCell))
   include "system/gc"
diff --git a/lib/system/threads.nim b/lib/system/threads.nim
index 823844c55..ccca85cb7 100755
--- a/lib/system/threads.nim
+++ b/lib/system/threads.nim
@@ -210,10 +210,7 @@ when not defined(useNimRtl):
       echo "too large thread local storage size requested"
       quit 1
   
-  when hasSharedHeap:
-    var heapLock: TSysLock
-    InitSysLock(HeapLock)
-
+  when hasSharedHeap and not defined(boehmgc) and not defined(nogc):
     var
       threadList: PGcThread
       
@@ -275,19 +272,17 @@ template ThreadProcWrapperBody(closure: expr) =
   var t = cast[ptr TThread[TMsg]](closure)
   when useStackMaskHack:
     var tls: TThreadLocalStorage
-  when not defined(boehmgc) and not hasSharedHeap:
+  when not defined(boehmgc) and not defined(nogc) and not hasSharedHeap:
     # init the GC for this thread:
     setStackBottom(addr(t))
     initGC()
-  when hasSharedHeap:
+  when defined(registerThread):
     t.stackBottom = addr(t)
     registerThread(t)
   if t.emptyFn == nil: t.dataFn(t.data)
   else: t.emptyFn()
-  #finally:
-  # XXX shut-down is not executed when the thread is forced down!
   freeInbox(addr(t.inbox))
-  when hasSharedHeap: unregisterThread(t)
+  when defined(registerThread): unregisterThread(t)
   when defined(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