| ... | ... | @@ -223,15 +223,17 @@ pub const Thread = struct { |
| 223 | 223 | } |
| 224 | 224 | }; |
| 225 | 225 | |
| 226 | | const MAP_GROWSDOWN = if (os.linux.is_the_target) os.linux.MAP_GROWSDOWN else 0; |
| 227 | | |
| 226 | var guard_end_offset: usize = undefined; |
| 228 | 227 | var stack_end_offset: usize = undefined; |
| 229 | 228 | var thread_start_offset: usize = undefined; |
| 230 | 229 | var context_start_offset: usize = undefined; |
| 231 | 230 | var tls_start_offset: usize = undefined; |
| 232 | 231 | const mmap_len = blk: { |
| 233 | | // First in memory will be the stack, which grows downwards. |
| 234 | | var l: usize = mem.alignForward(default_stack_size, mem.page_size); |
| 232 | var l: usize = mem.page_size; |
| 233 | // Allocate a guard page right after the end of the stack region |
| 234 | guard_end_offset = l; |
| 235 | // The stack itself, which grows downwards. |
| 236 | l = mem.alignForward(l + default_stack_size, mem.page_size); |
| 235 | 237 | stack_end_offset = l; |
| 236 | 238 | // Above the stack, so that it can be in the same mmap call, put the Thread object. |
| 237 | 239 | l = mem.alignForward(l, @alignOf(Thread)); |
| ... | ... | @@ -253,20 +255,32 @@ pub const Thread = struct { |
| 253 | 255 | } |
| 254 | 256 | break :blk l; |
| 255 | 257 | }; |
| 258 | // Map the whole stack with no rw permissions to avoid committing the |
| 259 | // whole region right away |
| 256 | 260 | const mmap_slice = os.mmap( |
| 257 | 261 | null, |
| 258 | 262 | mem.alignForward(mmap_len, mem.page_size), |
| 259 | | os.PROT_READ | os.PROT_WRITE, |
| 260 | | os.MAP_PRIVATE | os.MAP_ANONYMOUS | MAP_GROWSDOWN, |
| 263 | os.PROT_NONE, |
| 264 | os.MAP_PRIVATE | os.MAP_ANONYMOUS, |
| 261 | 265 | -1, |
| 262 | 266 | 0, |
| 263 | 267 | ) catch |err| switch (err) { |
| 264 | | error.MemoryMappingNotSupported => unreachable, // no file descriptor |
| 265 | | error.AccessDenied => unreachable, // no file descriptor |
| 266 | | error.PermissionDenied => unreachable, // no file descriptor |
| 268 | error.MemoryMappingNotSupported => unreachable, |
| 269 | error.AccessDenied => unreachable, |
| 270 | error.PermissionDenied => unreachable, |
| 267 | 271 | else => |e| return e, |
| 268 | 272 | }; |
| 269 | 273 | errdefer os.munmap(mmap_slice); |
| 274 | |
| 275 | // Map everything but the guard page as rw |
| 276 | os.mprotect( |
| 277 | mmap_slice, |
| 278 | os.PROT_READ | os.PROT_WRITE, |
| 279 | ) catch |err| switch (err) { |
| 280 | error.AccessDenied => unreachable, |
| 281 | else => |e| return e, |
| 282 | }; |
| 283 | |
| 270 | 284 | const mmap_addr = @ptrToInt(mmap_slice.ptr); |
| 271 | 285 | |
| 272 | 286 | const thread_ptr = @alignCast(@alignOf(Thread), @intToPtr(*Thread, mmap_addr + thread_start_offset)); |