Function map [src]

Prototype

pub fn map(n: usize, alignment: mem.Alignment) ?[*]u8

Parameters

n: usizealignment: mem.Alignment

Source

pub fn map(n: usize, alignment: mem.Alignment) ?[*]u8 { const page_size = std.heap.pageSize(); if (n >= maxInt(usize) - page_size) return null; const alignment_bytes = alignment.toByteUnits(); if (native_os == .windows) { var base_addr: ?*anyopaque = null; var size: windows.SIZE_T = n; var status = ntdll.NtAllocateVirtualMemory(windows.GetCurrentProcess(), @ptrCast(&base_addr), 0, &size, windows.MEM_COMMIT | windows.MEM_RESERVE, windows.PAGE_READWRITE); if (status == SUCCESS and mem.isAligned(@intFromPtr(base_addr), alignment_bytes)) { return @ptrCast(base_addr); } if (status == SUCCESS) { var region_size: windows.SIZE_T = 0; _ = ntdll.NtFreeVirtualMemory(windows.GetCurrentProcess(), @ptrCast(&base_addr), ®ion_size, windows.MEM_RELEASE); } const overalloc_len = n + alignment_bytes - page_size; const aligned_len = mem.alignForward(usize, n, page_size); base_addr = null; size = overalloc_len; status = ntdll.NtAllocateVirtualMemory(windows.GetCurrentProcess(), @ptrCast(&base_addr), 0, &size, windows.MEM_RESERVE | MEM_RESERVE_PLACEHOLDER, windows.PAGE_NOACCESS); if (status != SUCCESS) return null; const placeholder_addr = @intFromPtr(base_addr); const aligned_addr = mem.alignForward(usize, placeholder_addr, alignment_bytes); const prefix_size = aligned_addr - placeholder_addr; if (prefix_size > 0) { var prefix_base = base_addr; var prefix_size_param: windows.SIZE_T = prefix_size; _ = ntdll.NtFreeVirtualMemory(windows.GetCurrentProcess(), @ptrCast(&prefix_base), &prefix_size_param, windows.MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); } const suffix_start = aligned_addr + aligned_len; const suffix_size = (placeholder_addr + overalloc_len) - suffix_start; if (suffix_size > 0) { var suffix_base = @as(?*anyopaque, @ptrFromInt(suffix_start)); var suffix_size_param: windows.SIZE_T = suffix_size; _ = ntdll.NtFreeVirtualMemory(windows.GetCurrentProcess(), @ptrCast(&suffix_base), &suffix_size_param, windows.MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); } base_addr = @ptrFromInt(aligned_addr); size = aligned_len; status = ntdll.NtAllocateVirtualMemory(windows.GetCurrentProcess(), @ptrCast(&base_addr), 0, &size, windows.MEM_COMMIT | MEM_PRESERVE_PLACEHOLDER, windows.PAGE_READWRITE); if (status == SUCCESS) { return @ptrCast(base_addr); } base_addr = @as(?*anyopaque, @ptrFromInt(aligned_addr)); size = aligned_len; _ = ntdll.NtFreeVirtualMemory(windows.GetCurrentProcess(), @ptrCast(&base_addr), &size, windows.MEM_RELEASE); return null; } const aligned_len = mem.alignForward(usize, n, page_size); const max_drop_len = alignment_bytes - @min(alignment_bytes, page_size); const overalloc_len = if (max_drop_len <= aligned_len - n) aligned_len else mem.alignForward(usize, aligned_len + max_drop_len, page_size); const hint = @atomicLoad(@TypeOf(std.heap.next_mmap_addr_hint), &std.heap.next_mmap_addr_hint, .unordered); const slice = posix.mmap( hint, overalloc_len, posix.PROT.READ | posix.PROT.WRITE, .{ .TYPE = .PRIVATE, .ANONYMOUS = true }, -1, 0, ) catch return null; const result_ptr = mem.alignPointer(slice.ptr, alignment_bytes) orelse return null; // 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 drop_len = result_ptr - slice.ptr; if (drop_len != 0) posix.munmap(slice[0..drop_len]); const remaining_len = overalloc_len - drop_len; if (remaining_len > aligned_len) posix.munmap(@alignCast(result_ptr[aligned_len..remaining_len])); const new_hint: [*]align(page_size_min) u8 = @alignCast(result_ptr + aligned_len); _ = @cmpxchgStrong(@TypeOf(std.heap.next_mmap_addr_hint), &std.heap.next_mmap_addr_hint, hint, new_hint, .monotonic, .monotonic); return result_ptr; }