Explain the meaning of GMP models
- M structure is Machine, system thread, it is managed by the operating system, goroutine is running on M; M is a large structure that maintains a small object memory cache (McAche), a goroutine currently executed, a random number generator, and much more
- The P structure is the Processor, and its main purpose is to execute a Goroutine. It maintains a Goroutine queue, a runqueue. Let’s go from N:1 scheduling to the important part of M:N scheduling.
- G is the core structure of a Goroutine implementation. It contains the stack, instruction Pointers, and other information important to scheduling a Goroutine, such as the channel it blocks.
The number of processors is set at startup to the value of the environment variable GOMAXPROCS, or through the run-time scheduling function GOMAXPROCS(). A fixed number of processors means that only GOMAXPROCS threads are running go code at any one time
Scenario analysis
We use triangles, rectangles, and circles to represent the Machine Processor and Goroutine respectively.
Under normal circumstances
All goroutines run in the same M system thread, and each M system thread maintains one Processor. At any given time, only one Goroutine exists in one Processor, and all other goroutines wait in a Runqueue. After a Goroutine has run its time slice, it cedes context and returns to the RunQueue. In a multi-core Processor scenario, each M system thread holds one Processor in order to run goroutines.If both MS are running on the same CPU, this is concurrency; If two Ms are running on different cpus, this is parallel. The scheduler normally follows this process, assigning P to the next G when the goroutine’s time slice ends, but the thread blocks.
Thread block
When the running Goroutine (G0) blocks, such as a system call, another system thread (M1) is created, the current M0 thread abandons its Processor (P), and P runs in the new thread.
The runqueue execution is complete
When the runqueue of one of the processors is empty and there is no goroutine to dispatch, it steals half of the Goroutine from the other context.
First, a G object is created, and the G object is saved to the P local queue or global queue. P now wakes up an M. P continues its execution. M looks for a free P and moves the G object to itself if it does. Next M executes a scheduling loop (call G object -> execute -> clean up thread – continue to find a new Goroutine to execute).
Context switching can occur at any time during M execution. When a switchover occurs, you need to protect the execution site so that the execution site can be recovered when the execution is scheduled next time. The stack of THE Go scheduler M is stored on the G object. You only need to save the registers (SP, PC, etc.) required by M to the G object to achieve on-site protection. When the register data is secured, it is ready to do context switching, saving the scene before interrupting. If the task G is not finished, M can throw the task back to the task queue of P and wait for the next scheduled execution. When it is scheduled to execute again, M performs on-site recovery by accessing THE vdsoSP and vdsoPC registers of G (continuing execution from last interruption).
To learn more