I cannot add directly to David's wonderful answers, templatetypedef, etc. - if you want to avoid cross-thread comm-delays and resource-wastes, do not do inter-thread comms with sleep () loops.
Proactive scheduling / scheduling:
At the CPU level, interrupts are the key. The OS does nothing until an interruption occurs, which is why its code will be entered. Please note that in OS terms, interrupts come in two flavors - “real” hardware interrupts that cause drivers to start and “software interrupts” - these are system OS calls from already running threads that can potentially cause a set of current threads to change. Keys, mouse movements, network cards, drives, page errors generate hardware interrupts. The wait and signal functions and sleep () fall into this second category. When a hardware interrupt causes the driver to start, the driver performs any hardware control that it is intended to execute. If the driver needs to signal the OS that some thread needs to be started (perhaps the disk buffer is now full and needs to be processed), the OS provides an input mechanism that the driver can call instead of directly executing the interrupt, return yourself, (important! )
Interrupts, like the examples above, can create threads that have been waiting to be started and / or can cause a thread that is running to enter a wait state. After processing the interrupt code, the OS applies its scheduling algorithm / s to decide whether the set of threads that were started before the interrupt was the same as the set to be started. If so, the OS simply interrupts, returns, if not, the OS must preempt one or more running threads. If the OS needs to crowd out a thread that runs on a processor core that is not an interrupt handler, it should take control of that CPU core. He does this with a “real” hardware interrupt - the OS interprocessor driver sets up a hardware signal that severely interrupts the kernel, which must be unloaded.
When the thread to be unloaded enters the OS code, the OS can retain the full context for the stream. Some registers will already be saved on the stream stack using the interrupt entry, and therefore saving the stream stack pointer will effectively “save” all these registers, but the OS will usually need to do more, for example. caches may need to be cleared, FPU state may need to be maintained, and in the case when the new thread that should be started belongs to a different process than the one that should be unloaded, the memory protection registers should be replaced. Usually, the OS switches from the intermittent thread stack onto the private OS stack as soon as possible to avoid overlapping OS stack requirements on each thread stack.
After saving / saving the context / s, the OS can "exchange" the extended context / sec for new threads / s that should be started. Now the OS can finally load the stack pointer for the new thread / s and perform interrupt-returns to create new ready-made threads.
Then the OS does nothing. Running threads are executed until another interrupt (hard or soft) occurs.
Important points:
1) The OS kernel should be considered as a large interrupt handler, which can decide to interrupt-return to a different set of threads than those that were interrupted.
2) The OS can control and stop, if necessary, any thread in any process, regardless of what state it is in or in which kernel it can work.
3) Proactive planning and scheduling generate all the synchronization problems, etc. that are published in these forums. Great potential is a fast response at the flow level to hard interruptions. Without it, all those high-performance applications that you run on your PC - streaming video, fast networks, etc., will be almost impossible.
4) The OS timer is just one of a large set of interrupts that can change the set of running threads. "Time-slicing", (ugh - I hate this term), between ready-made threads occurs only when the computer is rebooted, i.e. the set of ready-made threads is greater than the number of CPU cores available to run them. If any text that includes an explanation of OS planning mentions a “temporary break” before “interruptions,” this is more likely to cause more confusion than an explanation. Interrupting the timer is only “special” in that many system calls have timeouts for backing up their main function (OK, for sleep (), the IS timeout is the main function :).