A critical section is a section of code that accesses a shared resource. When a virtual machine (VM) is executing code in a critical section, no other VM can execute code within their critical sections. By placing code that accesses shared resources within critical sections, shared resources are protected from simultaneous access by two or more VMs.
It is useful to think of the system as having a single, shared resource called the critical section which can represent any resource critical to the operation of all VMs. Only when a VM owns the critical section can it access the critical resource.
When a VM requests the critical section, it is said to have "claimed" the critical section. A VM that is executing code in the critical section is said to "own" the critical section. The VMM maintains an internal variable, called the claim count, that reflects the number of times the owner has claimed the critical section. Calling Begin_Critical_Section or Claim_Critical_Section increments the claim count; calling End_Critical_Section, End_Critical_Section_No_Block, or Release_Critical_Section decrements it. The owner releases the critical section only when the claim count is zero, allowing another VM to claim ownership. The claim count is not incremented when a VM attempts to claim the critical section while another virtual machine already owns it.
When one VM owns the critical section and a second VM attempts to claim ownership, the system blocks the second VM. Flags specified in the call to Begin_Critical_Section determine how the VM responds to interrupts while it is blocked. You should set the appropriate flags so that the VM processes hardware interrupts in a timely manner.
The system boosts the execution priority of a VM the when it first gains ownership of the critical section. This means that the system switches to another task only if the VM blocks on a semaphore or if a time-critical event occurs in another VM.
While the critical section is owned by any VM, you must not take any action that might cause MS-DOS to be reentered. If MS-DOS is used for paging, such actions include calling memory management services and touching pageable memory. Note that VxD_PAGEABLE_CODE_SEG and VxD_PAGEABLE_DATA_SEG segments are automatically locked if MS-DOS is used for paging.
A virtual device can request the VMM to notify it when a virtual machine has released the critical section by using the Call_When_Not_Critical or Call_Restricted_Event services. Note that the Call_When_Not_Critical service is equivalent to the following restricted event call:
xor eax, eax ; no boost
xor ebx, ebx ; global
mov ecx, PEF_Wait_Not_Crit
VMMCall Call_Restricted_Event
These services can be used to install a callback function that the VMM calls when the critical section is released. A virtual device typically uses the callback function to perform tasks that the must done only when no virtual machine owns the critical section. The system removes the callback function after calling it. To remove a restricted event callback function before it is called, use the Cancel_Restricted_Event service. For Windows 95, the Cancel_Call_When_Not_Critical service is a no-op, so if you need to be able to cancel the event, use Call_Restricted_Event with PEF_Wait_Not_Crit, and cancel it with Cancel_Restricted_Event.
The Get_Crit_Section_Status and Get_Crit_Status_No_Block services retrieve the claim count and the handle of the current owner of the critical section. When a virtual device released the critical section, the system sometimes delays the release while it processes events. Get_Crit_Section_Status allows the system to blocks the current virtual machine, if necessary, while completing any delayed releases. Get_Crit_Status_No_Block, on the other hand, returns immediately with the claim count and owner handle. Get_Crit_Status_Thread is similar to Get_Crit_Section_Status except that it retrieves the handle of the thread that owns the critical section, rather than the handle of the virtual machine.