I’m trying to set the current processor (CPU) from a windbg kernel-mode extension by using SetCurrentThreadId(). It returns S_OK, but a subsequent GetCurrentThreadId() doesn’t match. Here’s some test code and output from a 4-CPU system. Is this the right way to set processor context? Other suggestions? Thanks!
HRESULT CALLBACK
rc_test(PDEBUG_CLIENT4 Client, PCSTR args)
{
INIT_API();
ULONG numProcs = 0;
if (g_ExtControl->GetNumberProcessors(&numProcs) == S_OK) {
PROCESSORINFO pi;
GetKdContext(&pi);
dprintf(“GetNumberProcessors() => %lu processors; GetKdContext => %hu\n”, numProcs, pi.NumberProcessors);
for (ULONG p = 0; p < numProcs; p++) {
// switch to processor p.
ULONG tid;
dprintf(“switching to processor %lu…\n”, p);
if (g_ExtSystemObjects->GetThreadIdByProcessor(p, &tid) == S_OK) {
dprintf(“processor %lu is mapped to TID %lu.\n”, p, tid);
// When in kernel mode, the “CurrentThread” corresponds to the current CPU.
HRESULT r;
if ((r = g_ExtSystemObjects->SetCurrentThreadId(tid)) == S_OK) {
dprintf(“current processor should now be %lu.\n”, p);
} else {
dprintf(“error: SetCurrentThreadId(%lu) for CPU %lu returned 0x%lx.\n”, tid, p, r);
}
} else {
dprintf(“error: GetThreadIdByProcessor() failed.\n”);
}
// double-check that we have the correct processor.
if (g_ExtSystemObjects->GetCurrentThreadId(&tid) == S_OK) {
dprintf(“current processor according to GetCurrentThreadId() is %hu.\n”, pi.Processor);
} else {
dprintf(“error: GetCurrentThreadId() failed.\n”);
}
GetKdContext(&pi);
dprintf(“current processor according to GetKdContext() is %hu.\n”, pi.Processor);
// print some register values from it.
const char* regNames = { “eax”, “ebx”, “esp”, 0 };
for (int i = 0; regNames[i]; i++) {
ULONG regNum;
DEBUG_VALUE regVal;
if (g_ExtRegisters->GetIndexByName(regNames[i], ®Num) != S_OK) {
dprintf(“error in readReg: cannot get index of ‘%s’ register.\n”, regNames[i]);
}
else if (g_ExtRegisters->GetValue(regNum, ®Val) != S_OK) {
dprintf(“error: cannot read ‘%s’ register.\n”, regNames[i]);
}
else {
dprintf(" ‘%s’ = 0x%08x\n", regNames[i], regVal.I32);
}
}
}
}
EXIT_API();
return S_OK;
}
3: kd> !rc_test
GetNumberProcessors() => 4 processors; GetKdContext => 4
switching to processor 0…
processor 0 is mapped to TID 0.
current processor should now be 0.
current processor according to GetCurrentThreadId() is 3.
current processor according to GetKdContext() is 3.
‘eax’ = 0xcc490d18
‘ebx’ = 0xf788dc70
‘esp’ = 0xf7a34d34
switching to processor 1…
processor 1 is mapped to TID 1.
current processor should now be 1.
current processor according to GetCurrentThreadId() is 3.
current processor according to GetKdContext() is 3.
‘eax’ = 0xcc490d18
‘ebx’ = 0xf788dc70
‘esp’ = 0xf7a34d34
switching to processor 2…
processor 2 is mapped to TID 2.
current processor should now be 2.
current processor according to GetCurrentThreadId() is 3.
current processor according to GetKdContext() is 3.
‘eax’ = 0xcc490d18
‘ebx’ = 0xf788dc70
‘esp’ = 0xf7a34d34
switching to processor 3…
processor 3 is mapped to TID 3.
current processor should now be 3.
current processor according to GetCurrentThreadId() is 3.
current processor according to GetKdContext() is 3.
‘eax’ = 0xcc490d18
‘ebx’ = 0xf788dc70
‘esp’ = 0xf7a34d34