Commit b2cdf30e authored by Russ Cox's avatar Russ Cox

[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
parent 59e3e535
......@@ -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
}
}
......
......@@ -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")
......
This diff is collapsed.
......@@ -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)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment