Skip to content

Commit 9c78a7d

Browse files
committed
update preempt sc
1 parent be18673 commit 9c78a7d

File tree

1 file changed

+71
-0
lines changed

1 file changed

+71
-0
lines changed

1.14/signal_based_preemption.md

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,78 @@ asyncPreempt 是汇编实现的,分为三个部分:
380380
└─────────────────────────────────────────────────────────────────────┘ └──────────────────────────────────────────────────────────────────┘
381381
```
382382

383+
#### 你所想的上下文切换, 不一定等于你想要的上下文切换
384+
385+
这边需要注意的是, 抢占式调度中, 是`asyncPremmpt`这个操作保存了所有寄存器的值, 而`go`内部的诸如`systemstack``mcall`以及包括`runtime.Gosched()`的使用等, 是不会进行所有寄存器值的保留的, 所以在一些面对一些不常见的使用场景的时候需要注意, 避免寄存器发生非预期的篡改
386+
387+
例:
388+
```go
389+
// test.go
390+
package main
391+
392+
import (
393+
"fmt"
394+
"os"
395+
"os/signal"
396+
"runtime"
397+
"syscall"
398+
"time"
399+
)
400+
401+
//go:noescape
402+
func setget(v int64) int64
403+
404+
//go:noescape
405+
func set(v int64)
406+
407+
func gosched() {
408+
runtime.Gosched()
409+
}
410+
func main() {
411+
_ = gosched // avoid warning
412+
c := make(chan os.Signal, 1)
413+
signal.Notify(c, syscall.SIGURG)
414+
go func() {
415+
// for debug
416+
for {
417+
<-c
418+
fmt.Println("SIGURG")
419+
}
420+
}()
421+
go func() {
422+
for {
423+
if v := setget(1); v != 1 {
424+
fmt.Println("not equal:", v)
425+
os.Exit(1)
426+
} else {
427+
fmt.Println("equal")
428+
}
429+
}
430+
}()
431+
go func() {
432+
for {
433+
set(2)
434+
}
435+
}()
436+
time.Sleep(time.Hour)
437+
}
438+
```
439+
```assembly
440+
//test.s
441+
#include "textflag.h"
442+
443+
TEXT ·setget(SB),NOSPLIT,$0-16
444+
MOVL v+0(FP), R13
445+
//CALL ·gosched(SB) // runtime.Gosched() 没有进行所有寄存器现场的保留
446+
MOVQ R13, ret+8(FP)
447+
RET
448+
TEXT ·set(SB),NOSPLIT,$0-8
449+
MOVL v+0(FP), R13
450+
RET
451+
```
452+
以上这个简短的程序实现的是内部正常调度(非抢占式)下, 调度前后寄存器异常的问题。如果想要在应用内很好控制自身协程调度的, 那么就要小心这类问题。
383453
## asyncPreempt2
454+
接下去进行的就是常规内部上下文切换`mcall`
384455

385456
```go
386457
func asyncPreempt2() {

0 commit comments

Comments
 (0)