github.com/panjjo/go@v0.0.0-20161104043856-d62b31386338/src/runtime/HACKING.md (about) 1 This is a very incomplete and probably out-of-date guide to 2 programming in the Go runtime and how it differs from writing normal 3 Go. 4 5 Unmanaged memory 6 ================ 7 8 In general, the runtime tries to use regular heap allocation. However, 9 in some cases the runtime must allocate objects outside of the garbage 10 collected heap, in *unmanaged memory*. This is necessary if the 11 objects are part of the memory manager itself or if they must be 12 allocated in situations where the caller may not have a P. 13 14 There are three mechanisms for allocating unmanaged memory: 15 16 * sysAlloc obtains memory directly from the OS. This comes in whole 17 multiples of the system page size, but it can be freed with sysFree. 18 19 * persistentalloc combines multiple smaller allocations into a single 20 sysAlloc to avoid fragmentation. However, there is no way to free 21 persistentalloced objects (hence the name). 22 23 * fixalloc is a SLAB-style allocator that allocates objects of a fixed 24 size. fixalloced objects can be freed, but this memory can only be 25 reused by the same fixalloc pool, so it can only be reused for 26 objects of the same type. 27 28 In general, types that are allocated using any of these should be 29 marked `//go:notinheap` (see below). 30 31 Objects that are allocated in unmanaged memory **must not** contain 32 heap pointers unless the following rules are also obeyed: 33 34 1. Any pointers from unmanaged memory to the heap must be added as 35 explicit garbage collection roots in `runtime.markroot`. 36 37 2. If the memory is reused, the heap pointers must be zero-initialized 38 before they become visible as GC roots. Otherwise, the GC may 39 observe stale heap pointers. See "Zero-initialization versus 40 zeroing". 41 42 Zero-initialization versus zeroing 43 ================================== 44 45 There are two types of zeroing in the runtime, depending on whether 46 the memory is already initialized to a type-safe state. 47 48 If memory is not in a type-safe state, meaning it potentially contains 49 "garbage" because it was just allocated and it is being initialized 50 for first use, then it must be *zero-initialized* using 51 `memclrNoHeapPointers` or non-pointer writes. This does not perform 52 write barriers. 53 54 If memory is already in a type-safe state and is simply being set to 55 the zero value, this must be done using regular writes, `typedmemclr`, 56 or `memclrHasPointers`. This performs write barriers. 57 58 Runtime-only compiler directives 59 ================================ 60 61 In addition to the "//go:" directives documented in "go doc compile", 62 the compiler supports additional directives only in the runtime. 63 64 go:systemstack 65 -------------- 66 67 `go:systemstack` indicates that a function must run on the system 68 stack. This is checked dynamically by a special function prologue. 69 70 go:nowritebarrier 71 ----------------- 72 73 `go:nowritebarrier` directs the compiler to emit an error if the 74 following function contains any write barriers. (It *does not* 75 suppress the generation of write barriers; it is simply an assertion.) 76 77 Usually you want `go:nowritebarrierrec`. `go:nowritebarrier` is 78 primarily useful in situations where it's "nice" not to have write 79 barriers, but not required for correctness. 80 81 go:nowritebarrierrec and go:yeswritebarrierrec 82 ---------------------------------------------- 83 84 `go:nowritebarrierrec` directs the compiler to emit an error if the 85 following function or any function it calls recursively, up to a 86 `go:yeswritebarrierrec`, contains a write barrier. 87 88 Logically, the compiler floods the call graph starting from each 89 `go:nowritebarrierrec` function and produces an error if it encounters 90 a function containing a write barrier. This flood stops at 91 `go:yeswritebarrierrec` functions. 92 93 `go:nowritebarrierrec` is used in the implementation of the write 94 barrier to prevent infinite loops. 95 96 Both directives are used in the scheduler. The write barrier requires 97 an active P (`getg().m.p != nil`) and scheduler code often runs 98 without an active P. In this case, `go:nowritebarrierrec` is used on 99 functions that release the P or may run without a P and 100 `go:yeswritebarrierrec` is used when code re-acquires an active P. 101 Since these are function-level annotations, code that releases or 102 acquires a P may need to be split across two functions. 103 104 go:notinheap 105 ------------ 106 107 `go:notinheap` applies to type declarations. It indicates that a type 108 must never be heap allocated. Specifically, pointers to this type must 109 always fail the `runtime.inheap` check. The type may be used for 110 global variables, for stack variables, or for objects in unmanaged 111 memory (e.g., allocated with `sysAlloc`, `persistentalloc`, or 112 `fixalloc`). Specifically: 113 114 1. `new(T)`, `make([]T)`, `append([]T, ...)` and implicit heap 115 allocation of T are disallowed. (Though implicit allocations are 116 disallowed in the runtime anyway.) 117 118 2. A pointer to a regular type (other than `unsafe.Pointer`) cannot be 119 converted to a pointer to a `go:notinheap` type, even if they have 120 the same underlying type. 121 122 3. Any type that contains a `go:notinheap` type is itself 123 `go:notinheap`. Structs and arrays are `go:notinheap` if their 124 elements are. Maps and channels of `go:notinheap` types are 125 disallowed. To keep things explicit, any type declaration where the 126 type is implicitly `go:notinheap` must be explicitly marked 127 `go:notinheap` as well. 128 129 4. Write barriers on pointers to `go:notinheap` types can be omitted. 130 131 The last point is the real benefit of `go:notinheap`. The runtime uses 132 it for low-level internal structures to avoid memory barriers in the 133 scheduler and the memory allocator where they are illegal or simply 134 inefficient. This mechanism is reasonably safe and does not compromise 135 the readability of the runtime.