github.com/primecitizens/pcz/std@v0.2.1/core/os/goos.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright 2023 The Prime Citizens 3 // 4 // Copyright 2015 The Go Authors. All rights reserved. 5 // Use of this source code is governed by a BSD-style 6 // license that can be found in the LICENSE file. 7 8 // Package os contains GOOS-specific constants. 9 package os 10 11 import ( 12 "github.com/primecitizens/pcz/std/core/arch" 13 ) 14 15 // constants found from $GOROOT/src/runtime/malloc.go 16 const ( 17 // HeapAddrBits is the number of bits in a heap address. On 18 // amd64, addresses are sign-extended beyond HeapAddrBits. On 19 // other arches, they are zero-extended. 20 // 21 // On most 64-bit platforms, we limit this to 48 bits based on a 22 // combination of hardware and OS limitations. 23 // 24 // amd64 hardware limits addresses to 48 bits, sign-extended 25 // to 64 bits. Addresses where the top 16 bits are not either 26 // all 0 or all 1 are "non-canonical" and invalid. Because of 27 // these "negative" addresses, we offset addresses by 1<<47 28 // (arenaBaseOffset) on amd64 before computing indexes into 29 // the heap arenas index. In 2017, amd64 hardware added 30 // support for 57 bit addresses; however, currently only Linux 31 // supports this extension and the kernel will never choose an 32 // address above 1<<47 unless mmap is called with a hint 33 // address above 1<<47 (which we never do). 34 // 35 // arm64 hardware (as of ARMv8) limits user addresses to 48 36 // bits, in the range [0, 1<<48). 37 // 38 // ppc64, mips64, and s390x support arbitrary 64 bit addresses 39 // in hardware. On Linux, Go leans on stricter OS limits. Based 40 // on Linux's processor.h, the user address space is limited as 41 // follows on 64-bit architectures: 42 // 43 // Architecture Name Maximum Value (exclusive) 44 // --------------------------------------------------------------------- 45 // amd64 TASK_SIZE_MAX 0x007ffffffff000 (47 bit addresses) 46 // arm64 TASK_SIZE_64 0x01000000000000 (48 bit addresses) 47 // ppc64{,le} TASK_SIZE_USER64 0x00400000000000 (46 bit addresses) 48 // mips64{,le} TASK_SIZE64 0x00010000000000 (40 bit addresses) 49 // s390x TASK_SIZE 1<<64 (64 bit addresses) 50 // 51 // These limits may increase over time, but are currently at 52 // most 48 bits except on s390x. On all architectures, Linux 53 // starts placing mmap'd regions at addresses that are 54 // significantly below 48 bits, so even if it's possible to 55 // exceed Go's 48 bit limit, it's extremely unlikely in 56 // practice. 57 // 58 // On 32-bit platforms, we accept the full 32-bit address 59 // space because doing so is cheap. 60 // mips32 only has access to the low 2GB of virtual memory, so 61 // we further limit it to 31 bits. 62 // 63 // On ios/arm64, although 64-bit pointers are presumably 64 // available, pointers are truncated to 33 bits in iOS <14. 65 // Furthermore, only the top 4 GiB of the address space are 66 // actually available to the application. In iOS >=14, more 67 // of the address space is available, and the OS can now 68 // provide addresses outside of those 33 bits. Pick 40 bits 69 // as a reasonable balance between address space usage by the 70 // page allocator, and flexibility for what mmap'd regions 71 // we'll accept for the heap. We can't just move to the full 72 // 48 bits because this uses too much address space for older 73 // iOS versions. 74 // TODO(mknyszek): Once iOS <14 is deprecated, promote ios/arm64 75 // to a 48-bit address space like every other arm64 platform. 76 // 77 // WebAssembly currently has a limit of 4GB linear memory. 78 HeapAddrBits = (arch.Is64bit*(1-arch.IsWasm)*(1-IsIos*arch.IsArm64))*48 + 79 (1-arch.Is64bit+arch.IsWasm)*(32-(arch.IsMips+arch.IsMipsle)) + 80 40*IsIos*arch.IsArm64 81 82 // MaxAlloc is the maximum size of an allocation. On 64-bit, 83 // it's theoretically possible to allocate 1<<heapAddrBits bytes. On 84 // 32-bit, however, this is one less than 1<<32 because the 85 // number of bytes in the address space doesn't actually fit 86 // in a uintptr. 87 MaxAlloc = (1 << HeapAddrBits) - (1-arch.Is64bit)*1 88 89 // HeapArenaBytes is the size of a heap arena. The heap 90 // consists of mappings of size HeapArenaBytes, aligned to 91 // HeapArenaBytes. The initial heap mapping is one arena. 92 // 93 // This is currently 64MB on 64-bit non-Windows and 4MB on 94 // 32-bit and on Windows. We use smaller arenas on Windows 95 // because all committed memory is charged to the process, 96 // even if it's not touched. Hence, for processes with small 97 // heaps, the mapped arena space needs to be commensurate. 98 // This is particularly important with the race detector, 99 // since it significantly amplifies the cost of committed 100 // memory. 101 HeapArenaBytes = 1 << LogHeapArenaBytes 102 103 HeapArenaWords = HeapArenaBytes / arch.PtrSize 104 105 // LogHeapArenaBytes is log_2 of heapArenaBytes. For clarity, 106 // prefer using heapArenaBytes where possible (we need the 107 // constant to compute some other constants). 108 LogHeapArenaBytes = (6+20)*(arch.Is64bit*(1-IsWindows)*(1-arch.IsWasm)*(1-IsIos*arch.IsArm64)) + 109 (2+20)*(arch.Is64bit*IsWindows) + 110 (2+20)*(1-arch.Is64bit) + 111 (2+20)*arch.IsWasm + 112 (2+20)*IsIos*arch.IsArm64 113 114 // HeapArenaBitmapWords is the size of each heap arena's bitmap in uintptrs. 115 HeapArenaBitmapWords = HeapArenaWords / (8 * arch.PtrSize) 116 )