That looks like some API/kernel call overhead; you've moved the fast path of the semaphore implementation into user space. But what you have there is undeniably a semaphore implementation: atomically tweak a counter, and based on that result, wait or signal.