mirror of
https://github.com/golang/go
synced 2024-11-23 20:40:07 -07:00
[dev.cc] runtime: convert scheduler from C to Go
The conversion was done with an automated tool and then modified only as necessary to make it compile and run. [This CL is part of the removal of C code from package runtime. See golang.org/s/dev.cc for an overview.] LGTM=r R=r, daniel.morsing CC=austin, dvyukov, golang-codereviews, iant, khr https://golang.org/cl/172260043
This commit is contained in:
parent
59e3e5354d
commit
b2cdf30eb6
@ -101,8 +101,6 @@ var (
|
||||
eod = [3]uintptr{0, 1, 0}
|
||||
)
|
||||
|
||||
func setcpuprofilerate_m() // proc.c
|
||||
|
||||
func setcpuprofilerate(hz int32) {
|
||||
g := getg()
|
||||
g.m.scalararg[0] = uintptr(hz)
|
||||
|
@ -6,18 +6,6 @@ package runtime
|
||||
|
||||
import "unsafe"
|
||||
|
||||
// Breakpoint executes a breakpoint trap.
|
||||
func Breakpoint()
|
||||
|
||||
// LockOSThread wires the calling goroutine to its current operating system thread.
|
||||
// Until the calling goroutine exits or calls UnlockOSThread, it will always
|
||||
// execute in that thread, and no other goroutine can.
|
||||
func LockOSThread()
|
||||
|
||||
// UnlockOSThread unwires the calling goroutine from its fixed operating system thread.
|
||||
// If the calling goroutine has not called LockOSThread, UnlockOSThread is a no-op.
|
||||
func UnlockOSThread()
|
||||
|
||||
// GOMAXPROCS sets the maximum number of CPUs that can be executing
|
||||
// simultaneously and returns the previous setting. If n < 1, it does not
|
||||
// change the current setting.
|
||||
@ -66,5 +54,3 @@ func NumCgoCall() int64 {
|
||||
func NumGoroutine() int {
|
||||
return int(gcount())
|
||||
}
|
||||
|
||||
func gcount() int32
|
||||
|
@ -44,9 +44,9 @@ func TestFutexsleep(t *testing.T) {
|
||||
start := time.Now()
|
||||
for _, tt := range futexsleepTests {
|
||||
go func(tt futexsleepTest) {
|
||||
runtime.Entersyscall()
|
||||
runtime.Entersyscall(0)
|
||||
runtime.Futexsleep(&tt.mtx, tt.mtx, tt.ns)
|
||||
runtime.Exitsyscall()
|
||||
runtime.Exitsyscall(0)
|
||||
tt.ch <- tt
|
||||
}(tt)
|
||||
}
|
||||
|
@ -34,9 +34,6 @@ const (
|
||||
// Note that there can be spinning threads during all states - they do not
|
||||
// affect mutex's state.
|
||||
|
||||
func futexsleep(addr *uint32, val uint32, ns int64)
|
||||
func futexwakeup(addr *uint32, cnt uint32)
|
||||
|
||||
// We use the uintptr mutex.key and note.key as a uint32.
|
||||
func key32(p *uintptr) *uint32 {
|
||||
return (*uint32)(unsafe.Pointer(p))
|
||||
@ -198,8 +195,8 @@ func notetsleepg(n *note, ns int64) bool {
|
||||
gothrow("notetsleepg on g0")
|
||||
}
|
||||
|
||||
entersyscallblock()
|
||||
entersyscallblock(0)
|
||||
ok := notetsleep_internal(n, ns)
|
||||
exitsyscall()
|
||||
exitsyscall(0)
|
||||
return ok
|
||||
}
|
||||
|
@ -31,10 +31,6 @@ const (
|
||||
passive_spin = 1
|
||||
)
|
||||
|
||||
func semacreate() uintptr
|
||||
func semasleep(int64) int32
|
||||
func semawakeup(mp *m)
|
||||
|
||||
func lock(l *mutex) {
|
||||
gp := getg()
|
||||
if gp.m.locks < 0 {
|
||||
@ -263,8 +259,8 @@ func notetsleepg(n *note, ns int64) bool {
|
||||
if gp.m.waitsema == 0 {
|
||||
gp.m.waitsema = semacreate()
|
||||
}
|
||||
entersyscallblock()
|
||||
entersyscallblock(0)
|
||||
ok := notetsleep_internal(n, ns, nil, 0)
|
||||
exitsyscall()
|
||||
exitsyscall(0)
|
||||
return ok
|
||||
}
|
||||
|
@ -343,8 +343,7 @@ func netpollblock(pd *pollDesc, mode int32, waitio bool) bool {
|
||||
// this is necessary because runtime_pollUnblock/runtime_pollSetDeadline/deadlineimpl
|
||||
// do the opposite: store to closing/rd/wd, membarrier, load of rg/wg
|
||||
if waitio || netpollcheckerr(pd, mode) == 0 {
|
||||
f := netpollblockcommit
|
||||
gopark(**(**unsafe.Pointer)(unsafe.Pointer(&f)), unsafe.Pointer(gpp), "IO wait")
|
||||
gopark(netpollblockcommit, unsafe.Pointer(gpp), "IO wait")
|
||||
}
|
||||
// be careful to not lose concurrent READY notification
|
||||
old := xchguintptr(gpp, 0)
|
||||
|
@ -249,7 +249,7 @@ func TestGoroutineSwitch(t *testing.T) {
|
||||
// exists to record a PC without a traceback. Those are okay.
|
||||
if len(stk) == 2 {
|
||||
f := runtime.FuncForPC(stk[1])
|
||||
if f != nil && (f.Name() == "System" || f.Name() == "ExternalCode" || f.Name() == "GC") {
|
||||
if f != nil && (f.Name() == "runtime._System" || f.Name() == "runtime._ExternalCode" || f.Name() == "runtime._GC") {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
3489
src/runtime/proc.c
3489
src/runtime/proc.c
File diff suppressed because it is too large
Load Diff
@ -6,8 +6,6 @@ package runtime
|
||||
|
||||
import "unsafe"
|
||||
|
||||
func newsysmon()
|
||||
|
||||
func runtime_init()
|
||||
func main_init()
|
||||
func main_main()
|
||||
@ -55,6 +53,24 @@ func main() {
|
||||
|
||||
memstats.enablegc = true // now that runtime is initialized, GC is okay
|
||||
|
||||
if iscgo {
|
||||
if _cgo_thread_start == nil {
|
||||
gothrow("_cgo_thread_start missing")
|
||||
}
|
||||
if _cgo_malloc == nil {
|
||||
gothrow("_cgo_malloc missing")
|
||||
}
|
||||
if _cgo_free == nil {
|
||||
gothrow("_cgo_free missing")
|
||||
}
|
||||
if _cgo_setenv == nil {
|
||||
gothrow("_cgo_setenv missing")
|
||||
}
|
||||
if _cgo_unsetenv == nil {
|
||||
gothrow("_cgo_unsetenv missing")
|
||||
}
|
||||
}
|
||||
|
||||
main_init()
|
||||
|
||||
needUnlock = false
|
||||
@ -80,8 +96,6 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
var parkunlock_c byte
|
||||
|
||||
// start forcegc helper goroutine
|
||||
func init() {
|
||||
go forcegchelper()
|
||||
@ -115,7 +129,7 @@ func Gosched() {
|
||||
|
||||
// Puts the current goroutine into a waiting state and calls unlockf.
|
||||
// If unlockf returns false, the goroutine is resumed.
|
||||
func gopark(unlockf unsafe.Pointer, lock unsafe.Pointer, reason string) {
|
||||
func gopark(unlockf func(*g, unsafe.Pointer) bool, lock unsafe.Pointer, reason string) {
|
||||
mp := acquirem()
|
||||
gp := mp.curg
|
||||
status := readgstatus(gp)
|
||||
@ -123,7 +137,7 @@ func gopark(unlockf unsafe.Pointer, lock unsafe.Pointer, reason string) {
|
||||
gothrow("gopark: bad g status")
|
||||
}
|
||||
mp.waitlock = lock
|
||||
mp.waitunlockf = unlockf
|
||||
mp.waitunlockf = *(*unsafe.Pointer)(unsafe.Pointer(&unlockf))
|
||||
gp.waitreason = reason
|
||||
releasem(mp)
|
||||
// can't do anything that might move the G between Ms here.
|
||||
@ -133,14 +147,13 @@ func gopark(unlockf unsafe.Pointer, lock unsafe.Pointer, reason string) {
|
||||
// Puts the current goroutine into a waiting state and unlocks the lock.
|
||||
// The goroutine can be made runnable again by calling goready(gp).
|
||||
func goparkunlock(lock *mutex, reason string) {
|
||||
gopark(unsafe.Pointer(&parkunlock_c), unsafe.Pointer(lock), reason)
|
||||
gopark(parkunlock_c, unsafe.Pointer(lock), reason)
|
||||
}
|
||||
|
||||
func goready(gp *g) {
|
||||
mp := acquirem()
|
||||
mp.ptrarg[0] = unsafe.Pointer(gp)
|
||||
onM(ready_m)
|
||||
releasem(mp)
|
||||
onM(func() {
|
||||
ready(gp)
|
||||
})
|
||||
}
|
||||
|
||||
//go:nosplit
|
||||
@ -223,6 +236,11 @@ func newG() *g {
|
||||
return new(g)
|
||||
}
|
||||
|
||||
var (
|
||||
allgs []*g
|
||||
allglock mutex
|
||||
)
|
||||
|
||||
func allgadd(gp *g) {
|
||||
if readgstatus(gp) == _Gidle {
|
||||
gothrow("allgadd: bad status Gidle")
|
||||
|
3175
src/runtime/proc1.go
Normal file
3175
src/runtime/proc1.go
Normal file
File diff suppressed because it is too large
Load Diff
@ -10,15 +10,6 @@ func setMaxStack(in int) (out int) {
|
||||
return out
|
||||
}
|
||||
|
||||
func setGCPercent(in int32) (out int32) {
|
||||
mp := acquirem()
|
||||
mp.scalararg[0] = uintptr(int(in))
|
||||
onM(setgcpercent_m)
|
||||
out = int32(int(mp.scalararg[0]))
|
||||
releasem(mp)
|
||||
return out
|
||||
}
|
||||
|
||||
func setPanicOnFault(new bool) (old bool) {
|
||||
mp := acquirem()
|
||||
old = mp.curg.paniconfault
|
||||
@ -26,12 +17,3 @@ func setPanicOnFault(new bool) (old bool) {
|
||||
releasem(mp)
|
||||
return old
|
||||
}
|
||||
|
||||
func setMaxThreads(in int) (out int) {
|
||||
mp := acquirem()
|
||||
mp.scalararg[0] = uintptr(in)
|
||||
onM(setmaxthreads_m)
|
||||
out = int(mp.scalararg[0])
|
||||
releasem(mp)
|
||||
return out
|
||||
}
|
||||
|
@ -167,8 +167,8 @@ func selunlock(sel *_select) {
|
||||
}
|
||||
}
|
||||
|
||||
func selparkcommit(gp *g, sel *_select) bool {
|
||||
selunlock(sel)
|
||||
func selparkcommit(gp *g, sel unsafe.Pointer) bool {
|
||||
selunlock((*_select)(sel))
|
||||
return true
|
||||
}
|
||||
|
||||
@ -363,7 +363,7 @@ loop:
|
||||
|
||||
// wait for someone to wake us up
|
||||
gp.param = nil
|
||||
gopark(unsafe.Pointer(funcPC(selparkcommit)), unsafe.Pointer(sel), "select")
|
||||
gopark(selparkcommit, unsafe.Pointer(sel), "select")
|
||||
|
||||
// someone woke us up
|
||||
sellock(sel)
|
||||
|
Loading…
Reference in New Issue
Block a user