mirror of
https://github.com/golang/go
synced 2024-11-02 11:50:30 +00:00
runtime: add HACKING section on nosplit functions
Change-Id: I247874d5c49d2c0d8db2a3d227aa848093551d9b Reviewed-on: https://go-review.googlesource.com/c/go/+/401759 Reviewed-by: Michael Pratt <mpratt@google.com>
This commit is contained in:
parent
c5be77b687
commit
c29be2d41c
1 changed files with 38 additions and 10 deletions
|
@ -41,8 +41,20 @@ All `g`, `m`, and `p` objects are heap allocated, but are never freed,
|
|||
so their memory remains type stable. As a result, the runtime can
|
||||
avoid write barriers in the depths of the scheduler.
|
||||
|
||||
User stacks and system stacks
|
||||
-----------------------------
|
||||
`getg()` and `getg().m.curg`
|
||||
----------------------------
|
||||
|
||||
To get the current user `g`, use `getg().m.curg`.
|
||||
|
||||
`getg()` alone returns the current `g`, but when executing on the
|
||||
system or signal stacks, this will return the current M's "g0" or
|
||||
"gsignal", respectively. This is usually not what you want.
|
||||
|
||||
To determine if you're running on the user stack or the system stack,
|
||||
use `getg() == getg().m.curg`.
|
||||
|
||||
Stacks
|
||||
======
|
||||
|
||||
Every non-dead G has a *user stack* associated with it, which is what
|
||||
user Go code executes on. User stacks start small (e.g., 2K) and grow
|
||||
|
@ -63,17 +75,33 @@ non-preemptible and the garbage collector does not scan system stacks.
|
|||
While running on the system stack, the current user stack is not used
|
||||
for execution.
|
||||
|
||||
`getg()` and `getg().m.curg`
|
||||
----------------------------
|
||||
nosplit functions
|
||||
-----------------
|
||||
|
||||
To get the current user `g`, use `getg().m.curg`.
|
||||
Most functions start with a prologue that inspects the stack pointer
|
||||
and the current G's stack bound and calls `morestack` if the stack
|
||||
needs to grow.
|
||||
|
||||
`getg()` alone returns the current `g`, but when executing on the
|
||||
system or signal stacks, this will return the current M's "g0" or
|
||||
"gsignal", respectively. This is usually not what you want.
|
||||
Functions can be marked `//go:nosplit` (or `NOSPLIT` in assembly) to
|
||||
indicate that they should not get this prologue. This has several
|
||||
uses:
|
||||
|
||||
To determine if you're running on the user stack or the system stack,
|
||||
use `getg() == getg().m.curg`.
|
||||
- Functions that must run on the user stack, but must not call into
|
||||
stack growth, for example because this would cause a deadlock, or
|
||||
because they have untyped words on the stack.
|
||||
|
||||
- Functions that must not be preempted on entry.
|
||||
|
||||
- Functions that may run without a valid G. For example, functions
|
||||
that run in early runtime start-up, or that may be entered from C
|
||||
code such as cgo callbacks or the signal handler.
|
||||
|
||||
Splittable functions ensure there's some amount of space on the stack
|
||||
for nosplit functions to run in and the linker checks that any static
|
||||
chain of nosplit function calls cannot exceed this bound.
|
||||
|
||||
Any function with a `//go:nosplit` annotation should explain why it is
|
||||
nosplit in its documentation comment.
|
||||
|
||||
Error handling and reporting
|
||||
============================
|
||||
|
|
Loading…
Reference in a new issue