Implementation of condition variables

Apart from the missing return value checks, there are some more issues that should be fixable:

  • sem_destroy is not called.
  • Signal/broadcast touch the cond_node_t after waking the target thread, potentially resulting in a use-after-free.

Further comments:

  • The omitted destroy operation may require changes to the other operations so it is safe to destroy the condition variable when POSIX says it shall be safe. Not supporting destroy or imposing stronger restrictions on when it may be called will simplify things.
  • A production implementation would handle thread cancellation.
  • Backing out of a wait (such as required for thread cancellation and pthread_cond_timedwait timeouts) may lead to complications.
  • Your implementation queues threads in userland, which is done in some production implementations for performance reasons; I do not understand exactly why.
  • Your implementation always queues threads in LIFO order. This is often faster (such as because of cache effects) but may lead to starvation. Production implementation may use FIFO order sometimes to avoid starvation.

Basically your strategy looks ok, but you have one major danger, some undefined behavior, and a nit pick:

  • your are not inspecting the return values of your POSIX functions. In particular sem_wait is interruptible so under heavy load or bad luck your thread will be woken up spuriously. You'd have to carefully catch all that
  • none of your functions returns a value. If some user of the functions will decide to use the return values some day, this is undefined behavior. Carefully analyse the error codes that the condition functions are allowed to return and do just that.
  • don't cast the return of malloc or calloc

Edit: Actually, you don't need malloc/free at all. A local variable would do as well.