2015-02-05 13 views
6

Wenn ich einen C-Code von einer Goroutine aufrufen, beeinflusst es die Planung anderer Ghoutines in irgendeiner Weise? Ich weiß, dass wenn ich einen NIF in Erlang anrufe, es die anderen (Erlang) Prozesse blockiert, bis die Funktion zurückkehrt. Ist das in Golang der Fall? Blockiert C-Code den goroutines-Scheduler?C-Code und Goroutine-Planung

Antwort

8

Das Aufrufen einer C-Funktion von Go-Code verhindert nicht, dass andere Goroutines ausgeführt werden.

Es hat Auswirkungen auf den Scheduler. Eine Goroutine, die eine C-Funktion ausführt, zählt nicht unbedingt gegen den Grenzwert GOMAXPROCS. Es beginnt mit dem Zählen gegen GOMAXPROCS, aber wenn die C-Funktion für mehr als 20us zu dem Zeitpunkt blockiert ist, zu dem die Hintergrund-Goroutine läuft, dann wird dem Scheduler erlaubt, eine andere Goroutine zu starten, wenn eine bereit ist zu laufen. Diese Details hängen von der jeweiligen Go-Version ab und können sich ändern.

6

Dies ist eine sehr gute Frage, für die ich außer im Code keine offizielle Erklärung gefunden habe. Ich würde mich über Hinweise auf offizielle Dokumente freuen.

Die Antwort ist Nein, cgo Anrufe blockieren nicht den Scheduler.

Für die folgenden es ist gut zu wissen, dass intern Go verwendet G für goroutines, M für Maschinen (Threads) und P für proccessor. Goroutinen werden auf Prozessoren ausgeführt, die auf Maschinen laufen.

Aufruf einer C-Funktion von G wie folgt arbeitet nach dem code documentation:

// To call into the C function f from Go, the cgo-generated code calls 
// runtime.cgocall(_cgo_Cfunc_f, frame), where _cgo_Cfunc_f is a 
// gcc-compiled function written by cgo. 
// 
// runtime.cgocall (below) locks g to m, calls entersyscall 
// so as not to block other goroutines or the garbage collector, 
// and then calls runtime.asmcgocall(_cgo_Cfunc_f, frame). 
// 
// runtime.asmcgocall (in asm_$GOARCH.s) switches to the m->g0 stack 
// (assumed to be an operating system-allocated stack, so safe to run 
// gcc-compiled code on) and calls _cgo_Cfunc_f(frame). 
// 
// _cgo_Cfunc_f invokes the actual C function f with arguments 
// taken from the frame structure, records the results in the frame, 
// and returns to runtime.asmcgocall. 
// 
// After it regains control, runtime.asmcgocall switches back to the 
// original g (m->curg)'s stack and returns to runtime.cgocall. 
// 
// After it regains control, runtime.cgocall calls exitsyscall, which blocks 
// until this m can run Go code without violating the $GOMAXPROCS limit, 
// and then unlocks g from m. 

entersyscall erzählt im Wesentlichen die Laufzeit, die diese goroutine jetzt unter ‚externe‘ Kontrolle ist, genau wie in der Situation, wenn wir syscalls tun zum Kernel. Ein anderes wahrscheinlich nützliches Bit ist, dass das Sperren von g zu m (Sperren des CGO-Aufrufs von Goroutine zu dem OS-Thread) es ermöglicht, dass die Laufzeit einen neuen OS-Thread zuweist (theoretisch GOMAXPROCS überschreitend).

+1

Es gibt keine offizielle Dokumentation, die besagt, dass "das Aufrufen einer C-Funktion andere Gockel nicht blockiert", denn so sollte es natürlich funktionieren. Es wäre nur notwendig, dies zu dokumentieren, wenn es nicht so funktioniert. – iant