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"?
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.
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. 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 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.
Seems to be the DPC approach is not the right solution for
this type of problem.
You are the man, you make the decision.
Regards,
Roman