Roman Kononov wrote:
On 08/20/2007 10:05 AM, Darmawan Salihun wrote:
According to the official documentation, DPC is running at IRQL_DISPATCH_LEVEL. Nonetheless, I think there is still problem because only one DPC object of one "type" can exist in the system at one instance.
What do you mean by "type"?
DPC objects that has the same "Deferred Routine"
If you have N CPUs:
Initialization: KeInitializeDpc() initializes N DPC objects, each object has the same "DeferredRoutine". KeSetTargetProcessorDpc() ties each DPC object with a CPU.
I might have made a wrong assumption previously. I thought that a DPC object that has the same "Deferred Routine" won't be queued twice in the system's DPC queue. Nonetheless, this might not be the case for multiprocessor machine because every processor has its own DPC queue which implies that DPC objects with the same "Deferred Routine" can be queued in different processor's DPC queue without anyone of them being rejected. In single processor machine, a DPC object with the same "Deferred Routine" cannot be queued twice because the second request to queue the DPC will be rejected by the kernel.
PCI Configuration Sequence: IRQL is raised to DISPATCH_LEVEL. KeGetCurrentProcessorNumber() tells which CPU it is. KeInsertQueueDpc() schedules the N-1 DPCs to run. All but this CPU are scheduled. Spin waiting for the DeferredRoutines to enter phase A. IRQL is raised to HIGH_LEVEL. The DeferredRoutins are flagged to enter phase B. Spin waiting for the DeferredRoutines to enter phase B. Do the 3f8/3fc business.
OK, this is parallel port, right? Mine would be CF8/CFC
The DeferredRoutins are flagged to finish. Restore the IRQL.
DeferredRoutine: Indicate that the phase is phase A. Spin waiting for being flagged to enter phase B. Raise IRQL to HICH_LEVEL. Indicate that the phase is phase B. Spin waiting for being flagged to finish. Restore the IRQL.
This means we need to provide different DPC object "type" for
different processor in multiprocessor environment to ensure "atomic" execution of the I/O code which seems to be an overkill and make the system too much loaded.
What is "too much"?
I implied that every DPC objects are being allocated from the kernel non-paged pool memory which can degrade system performance if we are overusing it. But, this might not be the case.
I found this when trying to code the "DPC
approach" in my latest device driver. Perhaps, using a kernel mode spinlock is a better approach. To ensure an atomic execution of the I/O operation.
A spin lock does not help. A CPU, which has acquired a spin lock, does not prevent another CPU to mess with the cf8/cfc registers. You need to lock all other CPUs.
Yes, locking all of the CPU in a spinlock is what I'm thinking about. But, there possibly other alternative.
Seems to be the DPC approach is not the right solution for
this type of problem.
You are the man, you make the decision.
OK, thanks.
Regards,
Darmawan Salihun