Recently I was trying to understand how asynchronous preemption is implemented in Go 1.14 and
basically figured out the call chain.
sysmon
↓
retake
↓
preemptone
↓
preemptM
↓
signalM(mp, sigPreempt) //send SIGURG to mp
↓
doSigPreempt(signal handler) //if isAsyncSafePoint returns true, it will go on to preempt
↓
ctxt.pushCall(funcPC(asyncPreempt))
↓
asyncPreempt
↓
asyncPreempt2
↓
mcall(preemptPark) or mcall(gopreempt_m)
And I wrote a simple program to verify:
```Go
func main() {
var wg sync.WaitGroup
wg.Add(30)
for i := 0; i < 30; i++ {
go func() {
defer wg.Done()
t := 0
for i := 0; i < 1e8; i++ {
t += 2
}
}()
}
wg.Wait()
}
```
As we know general purpose registers RAX/RBX/... are not included in goroutine context.
```
type runtime.gobuf struct {
uintptr sp;
uintptr pc;
runtime.guintptr g;
void *ctxt;
runtime/internal/sys.Uintreg ret;
uintptr lr;
uintptr bp;
}
```
So when there are temporary values in these registers, it should not be good time to preempt. In following example, the loop takes enough long time to make it be preempted.
`t+=2` and `i++` use RAX as temporay register so it should't be asynchronous safe point.
My problem is how Go judges which instruction is preemptable? is it determined at compile time?
```
//from disassemble /sr main.main.func1
17 t := 0
0x000000000047be7d <+93>: 48 c7 44 24 08 00 00 00 00 movq $0x0,0x8(%rsp)
18 for i:=0; i < 1e8; i++ {
0x000000000047be86 <+102>: 48 c7 44 24 10 00 00 00 00 movq $0x0,0x10(%rsp)
0x000000000047be8f <+111>: eb 00 jmp 0x47be91 <main.main.func1+113>
0x000000000047be91 <+113>: 48 81 7c 24 10 00 ca 9a 3b cmpq $0x3b9aca00,0x10(%rsp)
0x000000000047be9a <+122>: 7c 02 jl 0x47be9e <main.main.func1+126>
0x000000000047be9c <+124>: eb 1f jmp 0x47bebd <main.main.func1+157>
19 t += 2
0x000000000047be9e <+126>: 48 8b 44 24 08 mov 0x8(%rsp),%rax
0x000000000047bea3 <+131>: 48 83 c0 02 add $0x2,%rax
0x000000000047bea7 <+135>: 48 89 44 24 08 mov %rax,0x8(%rsp)
0x000000000047beac <+140>: eb 00 jmp 0x47beae <main.main.func1+142>
18 for i:=0; i < 1e8; i++ {
0x000000000047beae <+142>: 48 8b 44 24 10 mov 0x10(%rsp),%rax
0x000000000047beb3 <+147>: 48 ff c0 inc %rax
0x000000000047beb6 <+150>: 48 89 44 24 10 mov %rax,0x10(%rsp)
0x000000000047bebb <+155>: eb d4 jmp 0x47be91 <main.main.func1+113>
```