aboutsummaryrefslogtreecommitdiff
path: root/src/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime')
-rw-r--r--src/runtime/panic.go4
-rw-r--r--src/runtime/proc.go48
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
+ }
+}