Using InterlockedIncrement() as a Semaphore

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

> Mark Thompson wrote:

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.

Given that you’re waiting on an event object anyway, and must therefore
be at < DISPATCH_LEVEL, why not use a fast mutex instead of inventing
your own object? It has almost no overhead when there’s no contention.


Walter Oney, Consulting and Training
Basic and Advanced Driver Programming Seminars
Now teaming with John Hyde for USB Device Engineering Seminars
Check out our schedule at http://www.oneysoft.com

> I’m interested in getting feedback on the use of
InterlockedIncrement()

as a way to implement a semaphore to ensure mutual exclusion

Your before code has race condition between the compare and the
increment.
I think you have already reached this conclusion.

To implement a poor mans semaphore using these functions, you must not
inspect the value of the variable outside the increment/decrement
functions. The increment/decrement functions give you the “new”
value as return code and from that you can infer the before value.

Your after code looks clean.

Joe Nord