I totally disagree with your assessment. WaitForMultipleObjects enters the kernel every time and blocks on kernel objects. The nearest equivalent is select, poll, epoll, kqueue, etc. Newer innovations like eventfd start to introduce synchronization objects into the mix of what type of kernel object to block on.
A Win32 mutex or semaphore is very heavy and typically avoided in a sane high performance application unless you need it to cross process boundaries. A lot of the time (most?) you will want a win32 critical section, which is similar to the modern futex based pthread mutex implementation in that it does not enter the kernel unless there is contention.
A pthread condition variable is clumsy. You need to give it an extra mutex and loop etc. It doesn't have any of the simplicity of WaitForMultipleObjects, even with all the faults of that interface of which there are many.