Analysis of Win32 core DPC design ideas and Implementation ideas

Source: Internet
Author: User
Tags apc

 Analysis of Win32 core DPC design ideas and Implementation ideas

Http://www.blogcn.com/user8/flier_lu/index.html? Id = 1397656 & run =. 09d4c2f

The X86 architecture is designed based on the concept of interruption. Therefore, from DOS to Win32, the concept of interruption is widely used in the operating system to express asynchronous operations. However, unlike dos exclusive scenarios, Win32 requires the system to schedule multiple tasks. Therefore, the interrupt response code must be as simple as possible and the control should be handed back to the system as soon as possible. In this way, the response speed and implementation process of system scheduling are convenient, but there are still many functions that need to be completed in the interrupt response. To this end, the Win32 core provides two special IRQL software interrupt levels, DPC (deferred Procedure Call) and APC (asynchronous procedure call), for implementation of latency and asynchronous process calls.
In IRQL layering, DPC and APC are between high-level device interruptions and passive interruptions at the lowest level, and are at the interruption level used by the operating system to complete special method calls. Unlike device interruptions that process hardware operations and higher-level clock and processor interruptions, these two levels of interruptions are designed to achieve asynchronous function calls, therefore, the operating system itself is highly dependent on them. APC is not discussed here for the time being. I will have the opportunity to write another article to discuss it later :)

DPC functions as part of the ISR (interrupt service routine. Just because ISR splits some functions out of the operating system and puts them in the corresponding DPC for simplicity and return control to the operating system, the call is delayed. Because the IRQL of DPC is only subject to APC and passive interruptions, the system can easily handle the accumulated relatively less urgent functions at the DPC level after a high level of interruption.
DPC can be understood as an encapsulated object of a callback function. The system itself or the device driver initializes a DPC object when the adddevice function or dispatchpnp function of the device driver processes the irp_mn_start_device request; to determine whether further interrupt processing is required in ISR, the request inserts the DPC object into the system DPC queue. After the system completes IRQL processing, the DPC objects in the DPC queue are processed slowly at the IRQL dispatch_level level. The callback function encapsulated by each DPC object uses the simultaneously encapsulated call parameters and is called by the system, you can still request to insert a DPC object to the DPC queue if you need further work.

DPC objects have two types of objects: dpcforisr and customdpc. The former is bound to the device object, and the latter is maintained by the driver. However, in terms of implementation, only one DPC object exists. The maintenance functions involved in dpcforisr are actually an encapsulation of customdpc.

First, let's look at the implementation of initializing DPC objects. The keinitializedpc function (ntoskedpcobj. C: 39) completes the initialization of the specific DPC object. In fact, it is to fill in a memory structure kdpc (ntosinc tosdef. h: 331 ).

Reference:

//
// Deferred Procedure Call (DPC) object
//

Typedef struct _ kdpc {
Cshort type;
Uchar number;
Uchar importance;
List_entry dpclistentry;
Pkdeferred_routine deferredroutine;
Pvoid deferredcontext;
Pvoid systemargument1;
Pvoid systemargument2;
Pulong_ptr lock;
} Kdpc, * pkdpc, * restricted_pointer prkdpc;
 

Type indicates the type of this kernel object, which is defined in kobjects Enumeration type (ntosincke. h: 122). The default value is dpcobject = 0X13. In addition, a threadeddpcobject = 0x18 is added to WINXP/2003.
Number is used to specify the processor's DPC queue to which the DPC object is added in a multi-processor environment. We will discuss the detailed description of the multi-processor. The default value is 0.
Importance indicates the importance of this DPC object. It is defined in the kdpc_importance Enumeration type (ntosinc tosdef. h: 321). The default value is mediumimportance = 1.
Dpclistentry is a linked list pointer used to maintain DPC queues.
Deferredroutine is the callback function bound to the DPC object. The following deferredcontext, systemargument1, and systemargument2 are the parameters used to call the callback function. For example, when iorequestdpc is called in ISR, the next two parameters are used to pass the IRP and context parameters to the callback function of DPC.
Lock stores the spin lock of the DPC queue where the DPC object is located. It is used to lock the DPC queue and determine whether the DPC object is added to a DPC queue.

After understanding the structure of the kdpc object, it is very easy to maintain the code. The keinitializedpc function initializes the structure of the kdpc object to the initial value. The ioinitializedpcrequest function is a simple packaging of the keinitializedpc function, as shown below:

Reference:

# Define ioinitializedpcrequest (deviceobject, dpcroutine )(
Keinitializedpc (& (deviceobject)-> DPC,
(Pkdeferred_routine) (dpcroutine ),
(Deviceobject )))
 

Note that in WINXP/2003, both the keinitializedpc function and the keinitializethreadeddpc function are completed by a kiinitializedpc function, but the object types defined by the last parameter passed are different.

Keinsertqueuedpc function (ntoskedpcobj. C: 89) is actually the core function of the system to maintain the DPC queue. Its pseudo code is as follows:

Reference:

Boolean keinsertqueuedpc (in prkdpc DPC, in pvoid systemargument1, in pvoid systemargument2)
{
Pkspin_lock lock;
Kirql oldirql;

Keraiseirql (high_level, & oldirql); // improves the current IRQL to the highest level, blocking other interruptions

Pkprcb = kegetcurrentprcb (); // obtain the current Processor Control Block

// Compare DPC-> lock to determine whether the DPC object has been added to the DPC queue;
// If the DPC object can be added to the queue, copy the DPC spin lock of the current processor control block to DPC-> lock.
If (Lock = interlockedcompareexchangepointer (& DPC-> lock, & prcb-> dpclock, null) = NULL)
{
// Update the statistics of the current Processor Control Block
Prcb-> dpccount + = 1;
Prcb-> dpcqueuedepth + = 1;

// Update the parameter information of the DPC object
DPC-> systemargument1 = systemargument1;
DPC-> systemargument2 = systemargument2;

// Based on the priority of the DPC object, it is determined to add it to the header or tail of the DPC queue.
If (DPC-> importance = highimportance)
Insertheadlist (& prcb-> dpclisthead, & DPC-> dpclistentry );
Else
Inserttaillist (& prcb-> dpclisthead, & DPC-> dpclistentry );

// If the current processor does not have a DPC object activity or a DPC interrupt request, determine whether to issue a DPC interrupt request.
If (prcb-> dpcroutineactive = false & prcb-> dpcinterruptrequested = false)
{
// If the priority of a DPC object is high;
// Or the DPC queue length exceeds the threshold value of maximumdpcqueuedepth;
// Or the DPC request rate is smaller than the threshold value minimumdpcrate
If (DPC-> importance! = Lowimportance) |
(Prcb-> dpcqueuedepth> = prcb-> maximumdpcqueuedepth) |
(Prcb-> dpcrequestrate <prcb-> minimumdpcrate ))
{
// If the trigger condition is met, a DPC interrupt request is sent.
Prcb-> dpcinterruptrequested = true;
Kirequestsoftwareinterrupt (dispatch_level );
}
}
}
Kelowerirql (oldirql );
Return (Lock = NULL );
}
 

The thresholds are determined by the global variables kimaximumdpcqueuedepth, kiminimumdpcrate, and kiadjustdpcthreshold in the kiinitializekernel function (ntoskei1_kernlini. C: 246. These global variables can be set through three key values: dpcqueuedepth, minimumdpcrate, and adjustdpcthreshold under the Registry Key (hkey_local_machinesystemcurrentcontrolsetcontrolsession managerkernel. For specific settings, see msdn and dynamic indexes such as processor % DPC time of performance counters.

The iorequestdpc function that processes the DPC object bound to the driver is a simple packaging of the keinsertqueuedpc function.

Reference:

# Define iorequestdpc (deviceobject, IRP, context )(
Keinsertqueuedpc (& (deviceobject)-> DPC, (IRP), (context )))
 

The keremovequeuedpc function (ntoskedpcobj. C: 272) corresponding to the keinsertqueuedpc function is actually just a simple function to delete a DPC object from a DPC queue.

Finally, the kesetimportancedpc functions (ntoskedpcobj. C: 367) and kesettargetprocessordpc functions (ntoskedpcobj. C: 401) that modify the attributes of the DPC object are actually the corresponding fields of the DPC object structure. Kdpc: when the number is greater than maximum_processors = 32, it is used to specify the target cpu Of the DPC object. For example, after you call kesettargetprocessordpc (pkdpc, 2), pkdpc = maximum_processors + 2.

After learning about the maintenance functions of DPC objects and DPC queues, let's take a look at the complicated maintenance process of DPC queues under multi-processor.

As mentioned above, kdpc: Number specifies the processor number used by the DPC object. Therefore, when the keinsertqueuedpc function starts to obtain the processor control block, it is necessary to determine whether the number points to a processor, obtain the corresponding processor control block from the global Processor Control Block List. The Code is as follows:

Reference:

If (DPC-> number> = maximum_processors) // if the number is greater than maximum_processors, it is used to specify the processor.
{
Processor = DPC-> Number-maximum_processors;
Prcb = kiprocessorblock [processor]; // list of globally unique Processor Control Blocks

}
Else
{
Prcb = kegetcurrentprcb ();
}

Kiacquirespinlock (& prcb-> dpclock); // use the spin lock to protect the DPC queue in the Processor Control Block
 

When the keinsertqueuedpc function determines whether a DPC interrupt request is sent, it also requires more complex logic judgment.
The target processor of the DPC object is the current processor. It can be processed in the same way as the previous one processor and directly send DPC interrupt requests. However, if the target processor of the DPC object is another processor, you must use the kiipisend function to send IPI (interprocessor interrupt) interruptions and notify the target processor to execute the action. This IPI interrupt is a special IRQL between the power-down (power_level) of the system and the clock interrupt. It is used to coordinate the work of multiple processors in the case of multiple processors.
In addition, in the case of multi-processor, various operations on the DPC queue must be protected by the DPC queue spin lock of the control block of this processor to avoid synchronization problems.

From this we can see that the DPC queue is actually one for each processor. We can bind a DPC object to a specific processor to achieve the effect of thread affinity, optimized the performance in a multi-processor environment. However, this also brings about the problem that ISR programs can be called with DPC callback functions at the same time, which also increases the development complexity to some extent. For specific solutions, see the related documentation in DDK.

Kernel-mode driver ubunturedesign guideservicing interruptsdpc objects and dpcs

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.