github.com/ltltlt/go-source-code@v0.0.0-20190830023027-95be009773aa/runtime/HACKING.md (about)

     1  This is a living document and at times it will be out of date. It is
     2  intended to articulate how programming in the Go runtime differs from
     3  writing normal Go. It focuses on pervasive concepts rather than
     4  details of particular interfaces.
     5  
     6  Scheduler structures
     7  ====================
     8  
     9  The scheduler manages three types of resources that pervade(遍布) the
    10  runtime: Gs, Ms, and Ps. It's important to understand these even if
    11  you're not working on the scheduler.
    12  
    13  Gs, Ms, Ps
    14  ----------
    15  
    16  A "G" is simply a goroutine. It's represented by type `g`. When a
    17  goroutine exits, its `g` object is returned to a pool of free `g`s and
    18  can later be reused for some other goroutine.
    19  一个G代表一个goroutine, 使用类型g表示, 当一个goroutine退出, 其g对象返回
    20  free g列表,并且之后可重用. 推论1: goroutine新建和毁灭的开销低
    21  
    22  An "M" is an OS thread that can be executing user Go code, runtime
    23  code, a system call, or be idle. It's represented by type `m`. There
    24  can be any number of Ms at a time since any number of threads may be
    25  blocked in system calls.
    26  M代表一个OS thread, 有几种状态: 执行Go代码, 执行runtime代码, 系统调用或者空闲
    27  任意时间可以有任意多的M, 因为可以有任意多个线程阻塞在系统调用
    28  
    29  Finally, a "P" represents the resources required to execute user Go
    30  code, such as scheduler and memory allocator state. It's represented
    31  by type `p`. There are exactly `GOMAXPROCS` Ps. A P can be thought of
    32  like a CPU in the OS scheduler and the contents of the `p` type like
    33  per-CPU state. This is a good place to put state that needs to be
    34  sharded for efficiency, but doesn't need to be per-thread or
    35  per-goroutine.
    36  P代表需要执行Go代码的资源, 比如调度器和内存分配状态. 恰好有GOMAXPROCS个P
    37  
    38  The scheduler's job is to match up a G (the code to execute), an M
    39  (where to execute it), and a P (the rights and resources to execute
    40  it). When an M stops executing user Go code, for example by entering a
    41  system call, it returns its P to the idle P pool. In order to resume
    42  executing user Go code, for example on return from a system call, it
    43  must acquire a P from the idle pool.
    44  调度器的任务是配对G, M和P. 当M停止执行用户Go代码(比如系统调用阻塞), 其会将其P返回
    45  闲置的P池, 使得这个P能被其他M获得, 这个P上的其他goroutine可以被执行. 要恢复执行
    46  用户Go代码, 比如从系统调用返回, 其必须从空闲P池中获取一个P.
    47  
    48  All `g`, `m`, and `p` objects are heap allocated, but are never freed,
    49  so their memory remains type stable. As a result, the runtime can
    50  avoid write barriers in the depths of the scheduler.
    51  所有的`g`, `m`, `p`对象都是在堆上分配的, 永远不会被释放, 所以其内存是稳定的.
    52  这导致runtime可以在调度器的层级避免写屏障
    53  
    54  User stacks and system stacks
    55  -----------------------------
    56  
    57  Every non-dead G has a *user stack* associated with it, which is what
    58  user Go code executes on. User stacks start small (e.g., 2K) and grow
    59  or shrink dynamically.
    60  每个未死亡的G都有一个用户栈, 用户Go代码在其上执行. 用户栈开始时从2K开始动态增长和缩小
    61  
    62  Every M has a *system stack* associated with it (also known as the M's
    63  "g0" stack because it's implemented as a stub G) and, on Unix
    64  platforms, a *signal stack* (also known as the M's "gsignal" stack).
    65  System and signal stacks cannot grow, but are large enough to execute
    66  runtime and cgo code (8K in a pure Go binary; system-allocated in a
    67  cgo binary).
    68  每个M有个系统栈(也被称为g0栈因为其以一个stub G实现)和一个信号栈(Unix平台下).
    69  这两个栈不能增长, 但已经足够大到执行运行时和cgo代码(纯Go二进制有8K, cgo二进制里是系统分配的)
    70  
    71  Runtime code often temporarily switches to the system stack using
    72  `systemstack`, `mcall`, or `asmcgocall` to perform tasks that must not
    73  be preempted, that must not grow the user stack, or that switch user
    74  goroutines. Code running on the system stack is implicitly
    75  non-preemptible and the garbage collector does not scan system stacks.
    76  While running on the system stack, the current user stack is not used
    77  for execution.
    78  runtime代码经常切换到系统栈执行不可被抢占的任务,不能增长用户栈的任务或切换用户goroutine的任务(?),
    79  使用`systemstack`, `mcall`, `asmcgocall`.
    80  运行在系统栈上的代码隐式不可被抢占,并且垃圾回收不扫描系统栈.
    81  当运行在系统栈时, 当前用户栈不用来执行.
    82  
    83  `getg()` and `getg().m.curg`
    84  ----------------------------
    85  
    86  To get the current user `g`, use `getg().m.curg`.
    87  要获取当前用户`g`, 使用`getg().m.curg`.
    88  
    89  `getg()` alone returns the current `g`, but when executing on the
    90  system or signal stacks, this will return the current M's "g0" or
    91  "gsignal", respectively. This is usually not what you want.
    92  单独的`getg()`会返回当前`g`, 但当在系统栈或信号栈上执行时,这会返回当前M的g0
    93  或gsinal.
    94  
    95  To determine if you're running on the user stack or the system stack,
    96  use `getg() == getg().m.curg`.
    97  使用`getg() == getg().m.curg`可以判断当前是否执行在系统或信号栈上
    98  
    99  Error handling and reporting
   100  ============================
   101  
   102  Errors that can reasonably be recovered from in user code should use
   103  `panic` like usual. However, there are some situations where `panic`
   104  will cause an immediate fatal error, such as when called on the system
   105  stack or when called during `mallocgc`.
   106  
   107  Most errors in the runtime are not recoverable. For these, use
   108  `throw`, which dumps the traceback and immediately terminates the
   109  process. In general, `throw` should be passed a string constant to
   110  avoid allocating in perilous situations. By convention, additional
   111  details are printed before `throw` using `print` or `println` and the
   112  messages are prefixed with "runtime:".
   113  
   114  For runtime error debugging, it's useful to run with
   115  `GOTRACEBACK=system` or `GOTRACEBACK=crash`.
   116  
   117  Synchronization
   118  ===============
   119  
   120  The runtime has multiple synchronization mechanisms. They differ in
   121  semantics and, in particular, in whether they interact with the
   122  goroutine scheduler or the OS scheduler.
   123  runtime有多种同步机制. 其语义和是否与goroutine调度器和OS调度器有所区别.
   124  
   125  The simplest is `mutex`, which is manipulated using `lock` and
   126  `unlock`. This should be used to protect shared structures for short
   127  periods. Blocking on a `mutex` directly blocks the M, without
   128  interacting with the Go scheduler. This means it is safe to use from
   129  the lowest levels of the runtime, but also prevents any associated G
   130  and P from being rescheduled. `rwmutex` is similar.
   131  最简单的是`mutex`. 这用来在短时间内保护共享数据结构. 阻塞`mutex`不直接与Go调度器
   132  交流, 直接阻塞M. 这意味着runtime最底层使用是安全的, 使用这个也避免和关联的G和P被
   133  重新调度.
   134  
   135  For one-shot notifications, use `note`, which provides `notesleep` and
   136  `notewakeup`. Unlike traditional UNIX `sleep`/`wakeup`, `note`s are
   137  race-free, so `notesleep` returns immediately if the `notewakeup` has
   138  already happened. A `note` can be reset after use with `noteclear`,
   139  which must not race with a sleep or wakeup. Like `mutex`, blocking on
   140  a `note` blocks the M. However, there are different ways to sleep on a
   141  `note`:`notesleep` also prevents rescheduling of any associated G and
   142  P, while `notetsleepg` acts like a blocking system call that allows
   143  the P to be reused to run another G. This is still less efficient than
   144  blocking the G directly since it consumes an M.
   145  对于一次性的提醒, 使用`note`. `note`也会阻塞M. 但其仍有两种情况, notesleep
   146  阻止关联的G和P重调度. `notetsleepg`运行P不被阻塞,继续被重用来执行其他G.
   147  这仍然不够高效,因为阻塞了一个M.
   148  
   149  To interact directly with the goroutine scheduler, use `gopark` and
   150  `goready`. `gopark` parks the current goroutine—putting it in the
   151  "waiting" state and removing it from the scheduler's run queue—and
   152  schedules another goroutine on the current M/P. `goready` puts a
   153  parked goroutine back in the "runnable" state and adds it to the run
   154  queue.
   155  为了直接与goroutine调度器直接交流, 使用`gopark`和`goready`. `gopark`停止当前
   156  goroutine, 将其放入等待状态,将其从调度器的运行队列中移除,然后调度另一个goroutine
   157  在当前M/P上执行.
   158  
   159  In summary,
   160  
   161  <table>
   162  <tr><th></th><th colspan="3">Blocks</th></tr>
   163  <tr><th>Interface</th><th>G</th><th>M</th><th>P</th></tr>
   164  <tr><td>(rw)mutex</td><td>Y</td><td>Y</td><td>Y</td></tr>
   165  <tr><td>note</td><td>Y</td><td>Y</td><td>Y/N</td></tr>
   166  <tr><td>park</td><td>Y</td><td>N</td><td>N</td></tr>
   167  </table>
   168  
   169  Unmanaged memory
   170  ================
   171  
   172  In general, the runtime tries to use regular heap allocation. However,
   173  in some cases the runtime must allocate objects outside of the garbage
   174  collected heap, in *unmanaged memory*. This is necessary if the
   175  objects are part of the memory manager itself or if they must be
   176  allocated in situations where the caller may not have a P.
   177  
   178  There are three mechanisms for allocating unmanaged memory:
   179  
   180  * sysAlloc obtains memory directly from the OS. This comes in whole
   181    multiples of the system page size, but it can be freed with sysFree.
   182  
   183  * persistentalloc combines multiple smaller allocations into a single
   184    sysAlloc to avoid fragmentation. However, there is no way to free
   185    persistentalloced objects (hence the name).
   186  
   187  * fixalloc is a SLAB-style allocator that allocates objects of a fixed
   188    size. fixalloced objects can be freed, but this memory can only be
   189    reused by the same fixalloc pool, so it can only be reused for
   190    objects of the same type.
   191  
   192  In general, types that are allocated using any of these should be
   193  marked `//go:notinheap` (see below).
   194  
   195  Objects that are allocated in unmanaged memory **must not** contain
   196  heap pointers unless the following rules are also obeyed:
   197  
   198  1. Any pointers from unmanaged memory to the heap must be added as
   199     explicit garbage collection roots in `runtime.markroot`.
   200  
   201  2. If the memory is reused, the heap pointers must be zero-initialized
   202     before they become visible as GC roots. Otherwise, the GC may
   203     observe stale heap pointers. See "Zero-initialization versus
   204     zeroing".
   205  
   206  Zero-initialization versus zeroing
   207  ==================================
   208  
   209  There are two types of zeroing in the runtime, depending on whether
   210  the memory is already initialized to a type-safe state.
   211  
   212  If memory is not in a type-safe state, meaning it potentially contains
   213  "garbage" because it was just allocated and it is being initialized
   214  for first use, then it must be *zero-initialized* using
   215  `memclrNoHeapPointers` or non-pointer writes. This does not perform
   216  write barriers.
   217  
   218  If memory is already in a type-safe state and is simply being set to
   219  the zero value, this must be done using regular writes, `typedmemclr`,
   220  or `memclrHasPointers`. This performs write barriers.
   221  
   222  Runtime-only compiler directives
   223  ================================
   224  
   225  In addition to the "//go:" directives documented in "go doc compile",
   226  the compiler supports additional directives only in the runtime.
   227  
   228  go:systemstack
   229  --------------
   230  
   231  `go:systemstack` indicates that a function must run on the system
   232  stack. This is checked dynamically by a special function prologue.
   233  
   234  go:nowritebarrier
   235  -----------------
   236  
   237  `go:nowritebarrier` directs the compiler to emit an error if the
   238  following function contains any write barriers. (It *does not*
   239  suppress the generation of write barriers; it is simply an assertion.)
   240  
   241  Usually you want `go:nowritebarrierrec`. `go:nowritebarrier` is
   242  primarily useful in situations where it's "nice" not to have write
   243  barriers, but not required for correctness.
   244  
   245  go:nowritebarrierrec and go:yeswritebarrierrec
   246  ----------------------------------------------
   247  
   248  `go:nowritebarrierrec` directs the compiler to emit an error if the
   249  following function or any function it calls recursively, up to a
   250  `go:yeswritebarrierrec`, contains a write barrier.
   251  
   252  Logically, the compiler floods the call graph starting from each
   253  `go:nowritebarrierrec` function and produces an error if it encounters
   254  a function containing a write barrier. This flood stops at
   255  `go:yeswritebarrierrec` functions.
   256  
   257  `go:nowritebarrierrec` is used in the implementation of the write
   258  barrier to prevent infinite loops.
   259  
   260  Both directives are used in the scheduler. The write barrier requires
   261  an active P (`getg().m.p != nil`) and scheduler code often runs
   262  without an active P. In this case, `go:nowritebarrierrec` is used on
   263  functions that release the P or may run without a P and
   264  `go:yeswritebarrierrec` is used when code re-acquires an active P.
   265  Since these are function-level annotations, code that releases or
   266  acquires a P may need to be split across two functions.
   267  
   268  go:notinheap
   269  ------------
   270  
   271  `go:notinheap` applies to type declarations. It indicates that a type
   272  must never be allocated from the GC'd heap. Specifically, pointers to
   273  this type must always fail the `runtime.inheap` check. The type may be
   274  used for global variables, for stack variables, or for objects in
   275  unmanaged memory (e.g., allocated with `sysAlloc`, `persistentalloc`,
   276  `fixalloc`, or from a manually-managed span). Specifically:
   277  
   278  1. `new(T)`, `make([]T)`, `append([]T, ...)` and implicit heap
   279     allocation of T are disallowed. (Though implicit allocations are
   280     disallowed in the runtime anyway.)
   281  
   282  2. A pointer to a regular type (other than `unsafe.Pointer`) cannot be
   283     converted to a pointer to a `go:notinheap` type, even if they have
   284     the same underlying type.
   285  
   286  3. Any type that contains a `go:notinheap` type is itself
   287     `go:notinheap`. Structs and arrays are `go:notinheap` if their
   288     elements are. Maps and channels of `go:notinheap` types are
   289     disallowed. To keep things explicit, any type declaration where the
   290     type is implicitly `go:notinheap` must be explicitly marked
   291     `go:notinheap` as well.
   292  
   293  4. Write barriers on pointers to `go:notinheap` types can be omitted.
   294  
   295  The last point is the real benefit of `go:notinheap`. The runtime uses
   296  it for low-level internal structures to avoid memory barriers in the
   297  scheduler and the memory allocator where they are illegal or simply
   298  inefficient. This mechanism is reasonably safe and does not compromise
   299  the readability of the runtime.