| ... | ... | @@ -51,10 +51,6 @@ const slab_len: usize = @max(std.heap.page_size_max, 64 * 1024); |
| 51 | 51 | /// Because of storing free list pointers, the minimum size class is 3. |
| 52 | 52 | const min_class = math.log2(@sizeOf(usize)); |
| 53 | 53 | const size_class_count = math.log2(slab_len) - min_class; |
| 54 | | /// When a freelist length exceeds this number, a `free` will rotate up to |
| 55 | | /// `max_free_search` times before pushing. |
| 56 | | const max_freelist_len: u8 = 16; |
| 57 | | const max_free_search = 1; |
| 58 | 54 | /// Before mapping a fresh page, `alloc` will rotate this many times. |
| 59 | 55 | const max_alloc_search = 1; |
| 60 | 56 | |
| ... | ... | @@ -73,8 +69,6 @@ const Thread = struct { |
| 73 | 69 | next_addrs: [size_class_count]usize = @splat(0), |
| 74 | 70 | /// For each size class, points to the freed pointer. |
| 75 | 71 | frees: [size_class_count]usize = @splat(0), |
| 76 | | /// For each size class, tracks the number of items in the freelist. |
| 77 | | freelist_lens: [size_class_count]u8 = @splat(0), |
| 78 | 72 | |
| 79 | 73 | fn lock() *Thread { |
| 80 | 74 | var index = thread_index; |
| ... | ... | @@ -142,7 +136,6 @@ fn alloc(context: *anyopaque, len: usize, alignment: mem.Alignment, ra: usize) ? |
| 142 | 136 | defer t.unlock(); |
| 143 | 137 | const node: *usize = @ptrFromInt(top_free_ptr); |
| 144 | 138 | t.frees[class] = node.*; |
| 145 | | t.freelist_lens[class] -|= 1; |
| 146 | 139 | return @ptrFromInt(top_free_ptr); |
| 147 | 140 | } |
| 148 | 141 | |
| ... | ... | @@ -160,7 +153,6 @@ fn alloc(context: *anyopaque, len: usize, alignment: mem.Alignment, ra: usize) ? |
| 160 | 153 | // slab alignment here ensures the % slab len earlier catches the end of slots. |
| 161 | 154 | const slab = PageAllocator.map(slab_len, .fromByteUnits(slab_len)) orelse return null; |
| 162 | 155 | t.next_addrs[class] = @intFromPtr(slab) + slot_size; |
| 163 | | t.freelist_lens[class] = 0; |
| 164 | 156 | return slab; |
| 165 | 157 | } |
| 166 | 158 | |
| ... | ... | @@ -214,42 +206,12 @@ fn free(context: *anyopaque, memory: []u8, alignment: mem.Alignment, ra: usize) |
| 214 | 206 | } |
| 215 | 207 | |
| 216 | 208 | const node: *usize = @alignCast(@ptrCast(memory.ptr)); |
| 217 | | var search_count: u8 = 0; |
| 218 | | |
| 219 | | var t = Thread.lock(); |
| 220 | | |
| 221 | | outer: while (true) { |
| 222 | | const freelist_len = t.freelist_lens[class]; |
| 223 | | if (freelist_len < max_freelist_len) { |
| 224 | | @branchHint(.likely); |
| 225 | | defer t.unlock(); |
| 226 | | node.* = t.frees[class]; |
| 227 | | t.frees[class] = @intFromPtr(node); |
| 228 | | return; |
| 229 | | } |
| 230 | 209 | |
| 231 | | if (search_count >= max_free_search) { |
| 232 | | defer t.unlock(); |
| 233 | | t.freelist_lens[class] = freelist_len +| 1; |
| 234 | | node.* = t.frees[class]; |
| 235 | | t.frees[class] = @intFromPtr(node); |
| 236 | | return; |
| 237 | | } |
| 210 | const t = Thread.lock(); |
| 211 | defer t.unlock(); |
| 238 | 212 | |
| 239 | | t.unlock(); |
| 240 | | const cpu_count = getCpuCount(); |
| 241 | | assert(cpu_count != 0); |
| 242 | | var index = thread_index; |
| 243 | | while (true) { |
| 244 | | index = (index + 1) % cpu_count; |
| 245 | | t = &global.threads[index]; |
| 246 | | if (t.mutex.tryLock()) { |
| 247 | | thread_index = index; |
| 248 | | search_count += 1; |
| 249 | | continue :outer; |
| 250 | | } |
| 251 | | } |
| 252 | | } |
| 213 | node.* = t.frees[class]; |
| 214 | t.frees[class] = @intFromPtr(node); |
| 253 | 215 | } |
| 254 | 216 | |
| 255 | 217 | fn sizeClassIndex(len: usize, alignment: mem.Alignment) usize { |