go-gl/gl

Inquiry: Implications of Go >= 1.14 asynchronous preemptive scheduling for go-gl

Closed this issue · 6 comments

Go 1.14 introduced asynchronous preemptive scheduling.

As a result, loops without function calls no longer potentially deadlock the scheduler or significantly delay garbage collection.

Notice this part about system calls:

[...] programs that use packages like syscall or golang.org/x/sys/unix will see more slow system calls fail with EINTR errors. Those programs will have to handle those errors in some way, most likely looping to try the system call again.

Go 1.15 followed up with changes to the behavior of the os and net packages, both of which perform many system calls.

Packages os and net now automatically retry system calls that fail with EINTR. Previously this led to spurious failures, which became more common in Go 1.14 with the addition of asynchronous preemption.

Following this development I thought "doesn't OpenGL have to make system calls all the time to send and receive data to/from the GPU?". Can someone who is qualified explain what these changes mean for the reliability of OpenGL in Go 1.14 and beyond?

If I'm not mistaken, the gl bindings don't make system calls via the syscall package, so they should not be affected by this.

OpenGL and even the GLFW base make all os/system calls via CGo and the C APIs, so only changes to the way C handles it would be a problem. Fortunately C isn’t going to get a GC ever so it’s not an issue. In fact, C is picked as the language for these types of jobs because it has no automatic GC and allows precise control of memory.

Thanks for the swift replies, everyone.

You have to https://golang.org/pkg/runtime/#LockOSThread for OpenGL.

I forgot I knew about this. Have had it in my code all this time, in fact. I am still a bit confused on how GC happens for a goroutine that has called LockOSThread() though.

If I'm not mistaken, the gl bindings don't make system calls via the syscall package, so they should not be affected by this.

[...] only changes to the way C handles it would be a problem.

Are we sure the changes are specific to those Go packages? The sentence in the changelog really refers to "system calls" in general, and only mentions those packages as examples. As far as I can tell, any function which leads to Ring 0 activity is affected. That should e.g. on Windows apply to every function in kernel32.dll, regardless of whether I call it using the syscall package, or via CGO using #include <Windows.h> and a direct call of the C function. The changelog says they do this by sending signals after all. I am sorry in case I am wrong with all of this; my knowledge on this historically grown low-level stuff is terrible.

CGo hands all the memory management and everything in CGo on the c compiler side to prevent issues like this. Anything covered by the go compiler is affected, but CGo uses GCC/clang to build the c side of things. Not to say that’s the perfect approach, either. Being so heavily tied to gcc/clang is why CGo on Windows is a pain to setup

Thanks for the clarification! I'll close this, then.

CGo on Windows is a pain to setup

To be honest, I don't really understand why that came to be. For some reason it's a big secret that you need a recent gcc-compatible build (which is only really satisfied by this one) to consistently have successful CGO builds on Windows. Maybe people don't like recommending something that leads to Sourceforge? 🥴