Skip to content

Commit 849e8a2

Browse files
new
Change-Id: I43f2dbd678860136f67e7f5178c122456514ef0c
1 parent 274de86 commit 849e8a2

File tree

5 files changed

+86
-5
lines changed

5 files changed

+86
-5
lines changed

src/runtime/crash_test.go

+17-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"path/filepath"
2020
"regexp"
2121
"runtime"
22+
"runtime/mainthread"
2223
"runtime/trace"
2324
"strings"
2425
"sync"
@@ -43,7 +44,22 @@ func TestMain(m *testing.M) {
4344

4445
_, coreErrBefore := os.Stat("core")
4546

46-
status := m.Run()
47+
sch := make(chan int)
48+
go func() {
49+
sch <- m.Run()
50+
}()
51+
var status int
52+
loop:
53+
for {
54+
select {
55+
case s := <-sch:
56+
status = s
57+
break loop
58+
case <-mainthread.Waiting():
59+
mainthread.Yield()
60+
}
61+
}
62+
4763
for _, file := range toRemove {
4864
os.RemoveAll(file)
4965
}

src/runtime/export_test.go

+6-2
Original file line numberDiff line numberDiff line change
@@ -1435,10 +1435,14 @@ func Escape[T any](x T) T {
14351435
}
14361436

14371437
// Acquirem blocks preemption.
1438-
func Acquirem() {
1439-
acquirem()
1438+
func Acquirem() *M {
1439+
return acquirem()
14401440
}
14411441

1442+
type M = m
1443+
1444+
var M0 = &m0
1445+
14421446
func Releasem() {
14431447
releasem(getg().m)
14441448
}

src/runtime/proc.go

+14-2
Original file line numberDiff line numberDiff line change
@@ -115,14 +115,18 @@ var modinfo string
115115

116116
var (
117117
m0 m
118-
m0func = make(chan func())
119-
waitm0 = make(chan struct{})
120118
g0 g
121119
mcache0 *mcache
122120
raceprocctx0 uintptr
123121
raceFiniLock mutex
124122
)
125123

124+
var (
125+
m0func = make(chan func())
126+
waitm0 = make(chan struct{})
127+
m0Exec = make(chan struct{}, 1)
128+
)
129+
126130
// This slice records the initializing tasks that need to be
127131
// done to start up the runtime. It is built by the linker.
128132
var runtime_inittasks []*initTask
@@ -153,13 +157,21 @@ func mainThreadDo(f func()) {
153157
}
154158
waitm0 <- struct{}{}
155159
m0func <- f
160+
_ = <-m0Exec
156161
}
157162

158163
func mainThreadYield() {
159164
g := getg()
160165
if g.m != &m0 {
161166
panic("runtime: call mainthread.Yield must on main thread")
162167
}
168+
// lock os thread ensure that the main thread always
169+
// run only f during a call to f.
170+
lockOSThread()
171+
defer func() {
172+
unlockOSThread()
173+
m0Exec <- struct{}{}
174+
}()
163175
f := <-m0func
164176
f()
165177
}

src/runtime/proc_test.go

+27
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"net"
1313
"runtime"
1414
"runtime/debug"
15+
"runtime/mainthread"
1516
"strings"
1617
"sync"
1718
"sync/atomic"
@@ -1161,4 +1162,30 @@ func TestBigGOMAXPROCS(t *testing.T) {
11611162

11621163
func TestMainThread(t *testing.T) {
11631164
checkCoroTestProgOutput(t, runTestProg(t, "testprog", "MainThread"))
1165+
t.Run("in mainthread call UnlockOSThread", func(t *testing.T) {
1166+
mainthread.Do(func() {
1167+
runtime.UnlockOSThread()
1168+
for range 1000 {
1169+
runtime.Gosched()
1170+
m := runtime.Acquirem()
1171+
runtime.Releasem()
1172+
if m != runtime.M0 {
1173+
// don`t use t.Fatal, because it call
1174+
// Goexit, cause TestMain goroutine exit,
1175+
// and test timeout.
1176+
t.Fail()
1177+
t.Log("mainthread.Do.f must on main thread")
1178+
return
1179+
}
1180+
}
1181+
runtime.LockOSThread()
1182+
})
1183+
})
1184+
t.Run("nested call mainthread.Do", func(t *testing.T) {
1185+
checkCoroTestProgOutput(t, runTestProg(t, "testprog", "MainThread2"))
1186+
})
1187+
}
1188+
1189+
func init() {
1190+
runtime.LockOSThread()
11641191
}

src/runtime/testdata/testprog/mainthread.go

+22
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,26 @@ func init() {
2828
println("expect: Ok")
2929
MainThread()
3030
})
31+
register("MainThread2", func() {
32+
println("expect: hello,world")
33+
MainThread2()
34+
})
35+
}
36+
37+
func MainThread2() {
38+
var wg sync.WaitGroup
39+
runtime.LockOSThread()
40+
wg.Add(1)
41+
go func() {
42+
defer wg.Done()
43+
mainthread.Do(func() {
44+
print("hello,")
45+
mainthread.Do(func() {
46+
print("world")
47+
})
48+
})
49+
}()
50+
<-mainthread.Waiting()
51+
mainthread.Yield()
52+
wg.Wait()
3153
}

0 commit comments

Comments
 (0)