>
> In any case, I can’t see how a spinlock would work for me here. As
far
as I can see
> a spinlock is designed to solve a different problem than the one I
am
solving here.
Well, actually it is not that easy to understand what kind of problem
you
are trying to solve here. Please note that the same DPC cannot be
queued
to more than one CPU at a time. Therefore, the line like “schedule a
DPC
on every CPU” in setup implies that there must be a dedicated KDPC
object
for every CPU (i.e. every KDPC has only one certain CPU specified in
its
affinity mask) - otherwise, you have no chance to make your DPC run on
all
CPUs without re-queuing it…
KeRaiseIrql(HIGH_LEVEL, &old_irql);
for (i = 0; i < ActiveProcessorCount; i++)
{
if (i == 0)
KeInitializeDpc(&highsync_info->dpcs[i],
XenPci_HighSyncCallFunction0, highsync_info);
else
KeInitializeDpc(&highsync_info->dpcs[i],
XenPci_HighSyncCallFunctionN, highsync_info);
KeSetTargetProcessorDpc(&highsync_info->dpcs[i], (CCHAR)i);
KeSetImportanceDpc(&highsync_info->dpcs[i], HighImportance);
KeInsertQueueDpc(&highsync_info->dpcs[i], NULL, NULL);
}
KeLowerIrql(old_irql);
So yes, I create a DPC for each processor, target it to that processor,
set the Importance to High (maybe not really necessary?) and then make
it go. I do the scheduling at HIGH_LEVEL, although DISPATCH_LEVEL is
probably all that is required, and then drop back to PASSIVE_LEVEL to
let the DPC scheduled on the current processor start. All the routines
above are documented as “IRQL: Any level”.
At this point the only question that arises is " well, why don’t you
want
to queue just CPU 0’s DPC in setup and the ones to all other CPUs
right
from CPU 0’s DPC routine after it has already finished its actual job,
i.e. immediately before returning ( in order to make it easier, you
can
just define different service routines for CPU 0 and all other CPUs).
If
all other DPCs have to synchronize something between themselves, they
can
use a spinlock (in fact, I don’t see any reason why they would have to
use
HIGH_LEVEL IRQL anyway). What is the point of all the trouble you are
trying to go through???
I’ve repeated this a few times. I patch the Windows kernel
(specifically, anything that touches the TPR) and so I have to be
absolutely sure that nothing calls the windows kernel at any time
until the patching is complete, lest it call the kernel in a ‘half
patched’ state.
In particular, because I’m patching all TPR access, I also can’t make
any calls to anything that raises or lowers IRQL, for obvious reasons.
The same synchronisation code is also used to ensure that all CPU’s are
doing nothing when I call Xen’s suspend code. The patching side of
things works fine, it’s just coming back from suspend that causes the
hang. I’m sure that the cause of the hang is a bug in my code which is
called from my synchronisation code, not a bug in the synchronisation
code itself, but being sure doesn’t necessarily make me right 
Actually, my ‘spin’ code calls KeStallExecutionProcessor… I wonder how
safe that is…?
James