diff options
Diffstat (limited to 'src/runtime')
| -rw-r--r-- | src/runtime/panic.go | 4 | ||||
| -rw-r--r-- | src/runtime/proc.go | 48 |
2 files changed, 40 insertions, 12 deletions
diff --git a/src/runtime/panic.go b/src/runtime/panic.go index 918ab7682a..543fd23c01 100644 --- a/src/runtime/panic.go +++ b/src/runtime/panic.go @@ -183,10 +183,6 @@ func panicmem() { panic(memoryError) } -func throwinit() { - throw("recursive call during initialization - linker skew") -} - // Create a new deferred function fn with siz bytes of arguments. // The compiler turns a defer statement into a call to this. //go:nosplit diff --git a/src/runtime/proc.go b/src/runtime/proc.go index 6e56b4b1d1..a077a5da03 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -82,11 +82,11 @@ var ( raceprocctx0 uintptr ) -//go:linkname runtime_init runtime.init -func runtime_init() +//go:linkname runtime_inittask runtime..inittask +var runtime_inittask initTask -//go:linkname main_init main.init -func main_init() +//go:linkname main_inittask main..inittask +var main_inittask initTask // main_init_done is a signal used by cgocallbackg that initialization // has been completed. It is made before _cgo_notify_runtime_init_done, @@ -144,7 +144,7 @@ func main() { throw("runtime.main not on m0") } - runtime_init() // must be before defer + doInit(&runtime_inittask) // must be before defer if nanotime() == 0 { throw("nanotime returning zero") } @@ -184,8 +184,8 @@ func main() { cgocall(_cgo_notify_runtime_init_done, nil) } - fn := main_init // make an indirect call, as the linker doesn't know the address of the main package when laying down the runtime - fn() + doInit(&main_inittask) + close(main_init_done) needUnlock = false @@ -196,7 +196,7 @@ func main() { // has a main, but it is not executed. return } - fn = main_main // make an indirect call, as the linker doesn't know the address of the main package when laying down the runtime + fn := main_main // make an indirect call, as the linker doesn't know the address of the main package when laying down the runtime fn() if raceenabled { racefini() @@ -5185,3 +5185,35 @@ func gcd(a, b uint32) uint32 { } return a } + +// An initTask represents the set of initializations that need to be done for a package. +type initTask struct { + // TODO: pack the first 3 fields more tightly? + state uintptr // 0 = uninitialized, 1 = in progress, 2 = done + ndeps uintptr + nfns uintptr + // followed by ndeps instances of an *initTask, one per package depended on + // followed by nfns pcs, one per init function to run +} + +func doInit(t *initTask) { + switch t.state { + case 2: // fully initialized + return + case 1: // initialization in progress + throw("recursive call during initialization - linker skew") + default: // not initialized yet + t.state = 1 // initialization in progress + for i := uintptr(0); i < t.ndeps; i++ { + p := add(unsafe.Pointer(t), (3+i)*sys.PtrSize) + t2 := *(**initTask)(p) + doInit(t2) + } + for i := uintptr(0); i < t.nfns; i++ { + p := add(unsafe.Pointer(t), (3+t.ndeps+i)*sys.PtrSize) + f := *(*func())(unsafe.Pointer(&p)) + f() + } + t.state = 2 // initialization done + } +} |
