summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--lib/system/alloc.nim81
-rw-r--r--tests/system/talloc.nim (renamed from tests/system/alloc.nim)15
-rw-r--r--tests/system/talloc2.nim37
-rw-r--r--tests/system/tio.nim (renamed from tests/system/io.nim)0
-rw-r--r--tests/system/tparams.nim (renamed from tests/system/params.nim)0
5 files changed, 92 insertions, 41 deletions
diff --git a/lib/system/alloc.nim b/lib/system/alloc.nim
index 4291013a2..6aef4f411 100644
--- a/lib/system/alloc.nim
+++ b/lib/system/alloc.nim
@@ -29,7 +29,9 @@ const
   FliOffset = 6
   RealFli = MaxFli - FliOffset
 
-  HugeChunkSize = int high(int32) - 1 # 2 GB, depends on TLSF's impl
+  # size of chunks in last matrix bin
+  MaxBigChunkSize = 1 shl MaxFli - 1 shl (MaxFli-MaxLog2Sli-1)
+  HugeChunkSize = MaxBigChunkSize + 1
 
 type
   PTrunk = ptr Trunk
@@ -154,10 +156,11 @@ proc mappingSearch(r, fl, sl: var int) {.inline.} =
   # PageSize alignment:
   let t = roundup((1 shl (msbit(uint32 r) - MaxLog2Sli)), PageSize) - 1
   r = r + t
+  r = r and not t
+  r = min(r, MaxBigChunkSize)
   fl = msbit(uint32 r)
   sl = (r shr (fl - MaxLog2Sli)) - MaxSli
   dec fl, FliOffset
-  r = r and not t
   sysAssert((r and PageMask) == 0, "mappingSearch: still not aligned")
 
 # See http://www.gii.upv.es/tlsf/files/papers/tlsf_desc.pdf for details of
@@ -518,55 +521,61 @@ proc updatePrevSize(a: var MemRegion, c: PBigChunk,
   if isAccessible(a, ri):
     ri.prevSize = prevSize or (ri.prevSize and 1)
 
+proc splitChunk2(a: var MemRegion, c: PBigChunk, size: int): PBigChunk =
+  result = cast[PBigChunk](cast[ByteAddress](c) +% size)
+  result.size = c.size - size
+  track("result.origSize", addr result.origSize, sizeof(int))
+  # XXX check if these two nil assignments are dead code given
+  # addChunkToMatrix's implementation:
+  result.next = nil
+  result.prev = nil
+  # size and not used:
+  result.prevSize = size
+  sysAssert((size and 1) == 0, "splitChunk 2")
+  sysAssert((size and PageMask) == 0,
+      "splitChunk: size is not a multiple of the PageSize")
+  updatePrevSize(a, c, result.size)
+  c.size = size
+  incl(a, a.chunkStarts, pageIndex(result))
+
+proc splitChunk(a: var MemRegion, c: PBigChunk, size: int) =
+  let rest = splitChunk2(a, c, size)
+  addChunkToMatrix(a, rest)
+
 proc freeBigChunk(a: var MemRegion, c: PBigChunk) =
   var c = c
   sysAssert(c.size >= PageSize, "freeBigChunk")
   inc(a.freeMem, c.size)
-  when coalescRight:
-    var ri = cast[PChunk](cast[ByteAddress](c) +% c.size)
-    sysAssert((cast[ByteAddress](ri) and PageMask) == 0, "freeBigChunk 2")
-    if isAccessible(a, ri) and chunkUnused(ri):
-      sysAssert(not isSmallChunk(ri), "freeBigChunk 3")
-      if not isSmallChunk(ri):
-        removeChunkFromMatrix(a, cast[PBigChunk](ri))
-        inc(c.size, ri.size)
-        excl(a.chunkStarts, pageIndex(ri))
+  c.prevSize = c.prevSize and not 1  # set 'used' to false
   when coalescLeft:
-    let prevSize = c.prevSize and not 1
+    let prevSize = c.prevSize
     if prevSize != 0:
       var le = cast[PChunk](cast[ByteAddress](c) -% prevSize)
       sysAssert((cast[ByteAddress](le) and PageMask) == 0, "freeBigChunk 4")
       if isAccessible(a, le) and chunkUnused(le):
         sysAssert(not isSmallChunk(le), "freeBigChunk 5")
-        if not isSmallChunk(le):
+        if not isSmallChunk(le) and le.size < MaxBigChunkSize:
           removeChunkFromMatrix(a, cast[PBigChunk](le))
           inc(le.size, c.size)
           excl(a.chunkStarts, pageIndex(c))
           c = cast[PBigChunk](le)
-
-  incl(a, a.chunkStarts, pageIndex(c))
-  updatePrevSize(a, c, c.size)
+          if c.size > MaxBigChunkSize:
+            let rest = splitChunk2(a, c, MaxBigChunkSize)
+            addChunkToMatrix(a, c)
+            c = rest
+  when coalescRight:
+    var ri = cast[PChunk](cast[ByteAddress](c) +% c.size)
+    sysAssert((cast[ByteAddress](ri) and PageMask) == 0, "freeBigChunk 2")
+    if isAccessible(a, ri) and chunkUnused(ri):
+      sysAssert(not isSmallChunk(ri), "freeBigChunk 3")
+      if not isSmallChunk(ri) and c.size < MaxBigChunkSize:
+        removeChunkFromMatrix(a, cast[PBigChunk](ri))
+        inc(c.size, ri.size)
+        excl(a.chunkStarts, pageIndex(ri))
+        if c.size > MaxBigChunkSize:
+          let rest = splitChunk2(a, c, MaxBigChunkSize)
+          addChunkToMatrix(a, rest)
   addChunkToMatrix(a, c)
-  # set 'used' to false:
-  c.prevSize = c.prevSize and not 1
-
-proc splitChunk(a: var MemRegion, c: PBigChunk, size: int) =
-  var rest = cast[PBigChunk](cast[ByteAddress](c) +% size)
-  rest.size = c.size - size
-  track("rest.origSize", addr rest.origSize, sizeof(int))
-  # XXX check if these two nil assignments are dead code given
-  # addChunkToMatrix's implementation:
-  rest.next = nil
-  rest.prev = nil
-  # size and not used:
-  rest.prevSize = size
-  sysAssert((size and 1) == 0, "splitChunk 2")
-  sysAssert((size and PageMask) == 0,
-      "splitChunk: size is not a multiple of the PageSize")
-  updatePrevSize(a, c, rest.size)
-  c.size = size
-  incl(a, a.chunkStarts, pageIndex(rest))
-  addChunkToMatrix(a, rest)
 
 proc getBigChunk(a: var MemRegion, size: int): PBigChunk =
   sysAssert(size > 0, "getBigChunk 2")
diff --git a/tests/system/alloc.nim b/tests/system/talloc.nim
index 7abefec2a..18396041d 100644
--- a/tests/system/alloc.nim
+++ b/tests/system/talloc.nim
@@ -8,7 +8,7 @@ x.dealloc()
 
 x = createU(int, 3)
 assert x != nil
-x.free()
+x.dealloc()
 
 x = create(int, 4)
 assert cast[ptr array[4, int]](x)[0] == 0
@@ -18,7 +18,7 @@ assert cast[ptr array[4, int]](x)[3] == 0
 
 x = x.resize(4)
 assert x != nil
-x.free()
+x.dealloc()
 
 x = cast[ptr int](allocShared(100))
 assert x != nil
@@ -26,7 +26,7 @@ deallocShared(x)
 
 x = createSharedU(int, 3)
 assert x != nil
-x.freeShared()
+x.deallocShared()
 
 x = createShared(int, 3)
 assert x != nil
@@ -37,7 +37,7 @@ assert cast[ptr array[3, int]](x)[2] == 0
 assert x != nil
 x = cast[ptr int](x.resizeShared(2))
 assert x != nil
-x.freeShared()
+x.deallocShared()
 
 x = create(int, 10)
 assert x != nil
@@ -49,4 +49,9 @@ x = createShared(int, 1)
 assert x != nil
 x = x.resizeShared(1)
 assert x != nil
-x.freeShared()
+x.deallocShared()
+
+x = cast[ptr int](alloc0(125 shl 23))
+dealloc(x)
+x = cast[ptr int](alloc0(126 shl 23))
+dealloc(x)
diff --git a/tests/system/talloc2.nim b/tests/system/talloc2.nim
new file mode 100644
index 000000000..c8cab78a1
--- /dev/null
+++ b/tests/system/talloc2.nim
@@ -0,0 +1,37 @@
+const
+  nmax = 2*1024*1024*1024
+
+proc test(n: int) =
+  var a = alloc0(9999)
+  var t = cast[ptr UncheckedArray[int8]](alloc(n))
+  var b = alloc0(9999)
+  t[0] = 1
+  t[1] = 2
+  t[n-2] = 3
+  t[n-1] = 4
+  dealloc(a)
+  dealloc(t)
+  dealloc(b)
+
+# allocator adds 48 bytes to BigChunk
+# BigChunk allocator edges at 2^n * (1 - s) for s = [1..32]/64
+proc test2(n: int) =
+  let d = n div 256  # cover edges and more
+  for i in countdown(128,1):
+    for j in [-4096, -64, -49, -48, -47, -32, 0, 4096]:
+      let b = n + j - i*d
+      if b>0 and b<=nmax:
+        test(b)
+        #echo b, ": ", getTotalMem(), " ", getOccupiedMem(), " ", getFreeMem()
+
+proc test3 =
+  var n = 1
+  while n <= nmax:
+    test2(n)
+    n *= 2
+  n = nmax
+  while n >= 1:
+    test2(n)
+    n = n div 2
+
+test3()
diff --git a/tests/system/io.nim b/tests/system/tio.nim
index 3d4df806b..3d4df806b 100644
--- a/tests/system/io.nim
+++ b/tests/system/tio.nim
diff --git a/tests/system/params.nim b/tests/system/tparams.nim
index 1358212f2..1358212f2 100644
--- a/tests/system/params.nim
+++ b/tests/system/tparams.nim
clean up comments in all subx files' href='/akkartik/mu/commit/subx/apps/factorial.subx?h=main&id=9d27e966b5e9bf1bd3da48f49d7e133d112a2bbe'>9d27e966 ^
6030d7e2 ^


9d27e966 ^
03d50cc8 ^
ee9a9237 ^
6030d7e2 ^
ee9a9237 ^
6030d7e2 ^
ee9a9237 ^
6030d7e2 ^
04be5eb2 ^
9d27e966 ^
6030d7e2 ^
5a9795bb ^
6030d7e2 ^
6ff9ce26 ^
9d27e966 ^
ee9a9237 ^
6030d7e2 ^


9d27e966 ^
6030d7e2 ^
9d27e966 ^
dd9ba09a ^
6030d7e2 ^

dd9ba09a ^
6030d7e2 ^

ee9a9237 ^
6030d7e2 ^
ee9a9237 ^
6030d7e2 ^
ee9a9237 ^
6030d7e2 ^

dd9ba09a ^
6030d7e2 ^
04be5eb2 ^
ee9a9237 ^
6030d7e2 ^



6ff9ce26 ^
03d50cc8 ^
6030d7e2 ^
ee9a9237 ^
6030d7e2 ^
ee9a9237 ^
6030d7e2 ^
ee9a9237 ^
6030d7e2 ^
00439520 ^
ee9a9237 ^
6030d7e2 ^


ee9a9237 ^
6030d7e2 ^
ee9a9237 ^
6030d7e2 ^


d48cfd0f ^
ee9a9237 ^
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112