There are many situations in which OS-level primitives such as blocking semaphores are available but userland primitives are not. When implementing libc, for example. Or when implementing a language runtime, or TBB, or boost::thread_pool, or what have you.