Go

What happens to the scheduler when a goroutine makes a blocking syscall?

Question 157HardGo 1.22 to 1.25

Before the syscall, the runtime calls entersyscall. The G moves to _Gsyscall, and its P moves to _Psyscall but stays attached to the M. The goal is to make fast syscalls cheap.

  • Fast path: the syscall returns quickly. exitsyscall takes the same P back and the goroutine continues without any hand-off.
  • Slow path: sysmon sees that the P has been in a syscall for more than about 20 µs (one sysmon tick) and has other work to do. It calls retake → handoffp, and the P goes to another M. That M may be idle or newly created. When the syscall eventually returns, the original M tries to get an idle P. If none is free, it puts the G on the global queue and parks itself.
  • Syscalls known to block (entersyscallblock) hand the P off immediately.

Consequences:

  • Many goroutines blocked in file I/O or cgo can create many OS threads. The default limit is 10,000 threads (debug.SetMaxThreads), and going past it crashes the program.
  • Regular files cannot go through epoll on Linux, so file I/O blocks threads.
  • cgo calls are handled like syscalls.

More on Goroutines & the Scheduler

All 35 Goroutines & the Scheduler questions