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> ``` -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/eef5058e-1473-4b9a-893d-a8cfe6e0b6a4n%40googlegroups.com.