atomic.Storeuintptr(&extram, uintptr(unsafe.Pointer(mp)))
}
+// execLock serializes exec and clone to avoid bugs or unspecified behaviour
+// around exec'ing while creating/destroying threads. See issue #19546.
+//
+// TODO: look into using a rwmutex, to avoid serializing thread creation.
+var execLock mutex
+
// Create a new m. It will start off with a call to fn, or else the scheduler.
// fn needs to be static and not a heap allocated closure.
// May run with m.p==nil, so write barriers are not allowed.
if msanenabled {
msanwrite(unsafe.Pointer(&ts), unsafe.Sizeof(ts))
}
+ lock(&execLock)
asmcgocall(_cgo_thread_start, unsafe.Pointer(&ts))
+ unlock(&execLock)
return
}
+ lock(&execLock)
newosproc(mp, unsafe.Pointer(mp.g0.stack.hi))
+ unlock(&execLock)
}
// Stops execution of the current m until new work is available.
msigrestore(getg().m.sigmask)
}
+// Called from syscall package before Exec.
+//go:linkname syscall_runtime_BeforeExec syscall.runtime_BeforeExec
+func syscall_runtime_BeforeExec() {
+ lock(&execLock)
+}
+
+// Called from syscall package after Exec.
+//go:linkname syscall_runtime_AfterExec syscall.runtime_AfterExec
+func syscall_runtime_AfterExec() {
+ unlock(&execLock)
+}
+
// Allocate a new g, with a stack big enough for stacksize bytes.
func malg(stacksize int32) *g {
newg := new(g)
return pid, 0, err
}
+// Implemented in runtime package.
+func runtime_BeforeExec()
+func runtime_AfterExec()
+
// Exec invokes the execve(2) system call.
func Exec(argv0 string, argv []string, envv []string) (err error) {
argv0p, err := BytePtrFromString(argv0)
if err != nil {
return err
}
+ runtime_BeforeExec()
_, _, err1 := RawSyscall(SYS_EXECVE,
uintptr(unsafe.Pointer(argv0p)),
uintptr(unsafe.Pointer(&argvp[0])),
uintptr(unsafe.Pointer(&envvp[0])))
+ runtime_AfterExec()
return Errno(err1)
}