Commit 1030cc97ca

Ryan Liptak <squeek502@hotmail.com>
2019-04-20 02:27:20
fix DirectAllocator not unmapping unused pages on large alignments
Fixes #2306
1 parent d44d278
Changed files (1)
std/heap.zig
@@ -68,21 +68,22 @@ pub const DirectAllocator = struct {
                 if (addr == p.MAP_FAILED) return error.OutOfMemory;
                 if (alloc_size == n) return @intToPtr([*]u8, addr)[0..n];
 
-                const aligned_addr = (addr & ~usize(alignment - 1)) + alignment;
-
-                // We can unmap the unused portions of our mmap, but we must only
-                // pass munmap bytes that exist outside our allocated pages or it
-                // will happily eat us too.
-
-                // Since alignment > page_size, we are by definition on a page boundary.
-                const unused_start = addr;
-                const unused_len = aligned_addr - 1 - unused_start;
-
-                const err = p.munmap(unused_start, unused_len);
-                assert(p.getErrno(err) == 0);
-
-                // It is impossible that there is an unoccupied page at the top of our
-                // mmap.
+                const aligned_addr = mem.alignForward(addr, alignment);
+
+                // Unmap the extra bytes that were only requested in order to guarantee
+                // that the range of memory we were provided had a proper alignment in
+                // it somewhere. The extra bytes could be at the beginning, or end, or both.
+                const unused_start_len = aligned_addr - addr;
+                if (unused_start_len != 0) {
+                    const err = p.munmap(addr, unused_start_len);
+                    assert(p.getErrno(err) == 0);
+                }
+                const aligned_end_addr = std.mem.alignForward(aligned_addr + n, os.page_size);
+                const unused_end_len = addr + alloc_size - aligned_end_addr;
+                if (unused_end_len != 0) {
+                    const err = p.munmap(aligned_end_addr, unused_end_len);
+                    assert(p.getErrno(err) == 0);
+                }
 
                 return @intToPtr([*]u8, aligned_addr)[0..n];
             },