-
Notifications
You must be signed in to change notification settings - Fork 7
Virtual Processors
A virtual processor represents an independent thread of execution. They are similar to threads traditional operating systems in the sense that they maintain CPU state and that they allow for the parallel execution of code. However they are different from threads in traditional operating systems in the sense that virtual processors have a much more loose connection to the process to which they are assigned at any given time.
An application does not create a virtual processor. Instead it acquires one when needed from the kernel and it relinquishes it back to the kernel when it no longer needs it. The relationship between a process and a virtual processor is a transient one - an application does not indefinitely hold on to a virtual processor like applications have traditionally done with threads. Instead it acquires a virtual processor when needed, does its work and then relinquishes the virtual processor back to the kernel.
The kernel manages a global pool of virtual processors. This allows the kernel to quickly provide a virtual processor to an application when needed. The kernel itself creates and destroys virtual processors as it sees fit based on the global state of the system.
Virtual processors are the basic unit of concurrency with which the scheduler and context switcher works. Each virtual processor stores the CPU state when it is currently not running and it maintains a user and kernel stack. The user stack is exclusively used by user space code while the kernel stack is exclusively used by the kernel itself. The kernel stack is usually much smaller compared to the user stack since kernel code is not allowed to use recursion.
Every virtual processor is assigned to a quality of service class. The quality of service class controls the fundamental scheduling decisions. Additionally every virtual processor is assigned a priority. The priority is per quality of service class and it controls the relative importance of a virtual processor versus the other virtual processors in the same quality of service class. Quality of service classes are organized in a string of importance. From highest to lowest importance the classes are:
- Realtime
- Interactive
- Utility
- Background
So for example, virtual processors in the realtime class receive preferential treatment over virtual processors in the background class. Preferential treatment among other things here means that realtime virtual processors are able to interrupt background virtual processors when they become run-able.
An application may use the vcpu functions of the C library to acquire, work with and relinquish virtual processors. However working with virtual processors this way is generically discouraged because it means that an application has to take care of a lot of low level details.
Instead applications should use the dispatch queue APIs defined in the libdispatch library. Dispatch queues take care of a lot of the details of virtual processor management and most importantly they automatically and transparently acquire and relinquish virtual processors as needed. This enables application developers to focus on the high level details of concurrency and scheduling work.
Every virtual processor belongs to a virtual processor group and each group is identified by a unique id. This id is unique with respect to the process that hosts the virtual processor group.
A virtual processor group can be used as the target of a signal. You can send a signal to a virtual processor group and the kernel will intelligently select a virtual processor from that group to run and to handle the signal.