Hi All,
I’m interested in getting feedback on the use of InterlockedIncrement() as a way to implement a semaphore to ensure mutual exclusion when executing critical sections of code.
I have been debugging an inherited section of code that went something like this:
if (!pCurrUnit->RecvCmdPacketRun) {
InterlockedIncrement (&pCurrUnit->RecvCmdPacketRun);
// Do some funky stuff here to the hardware
}
else {
waitLoop:;
KeClearEvent (&pCurrUnit->RecvCmdPacketDone);
KeWaitForSingleObject (
&pCurrUnit->RecvCmdPacketDone,
Executive,
KernelMode,
FALSE,
NULL);
if (pCurrUnit->RecvCmdPacketRun != 0)
goto waitLoop;
InterlockedIncrement (&pCurrUnit->RecvCmdPacketRun);
// Do the same funky stuff here
}
InterlockedDecrement (&pCurrUnit->RecvCmdPacketRun);
I believe there is a race in the test-and-set using pCurrUnit->RecvCmdPacketRun.
I think this could be better coded as:
while (InterlockedIncrement (&pCurrUnit->RecvCmdPacketRun) != 1){
InterlockedDecrement (&pCurrUnit->RecvCmdPacketRun);
KeClearEvent (&pCurrUnit->RecvCmdPacketDone);
InterlockedDecrement (&pCurrUnit->RecvCmdPacketRun);
KeWaitForSingleObject (
&pCurrUnit->RecvCmdPacketDone,
Executive,
KernelMode,
FALSE,
NULL);
}
// Do some funky stuff to the hardware
InterlockedDecrement (&pCurrUnit->RecvCmdPacketRun);
Thoughts? Opinions?
Regards, Mark T