/* Increment first so broadcaster knows we are waiting. */
futex_down(&cond->lock);
atomic_inc(cond->num_waiting);
(*) futex_up(&mutex, 1);
a) futex_up(&cond->lock, 1); [move into syscall]
do {
b) ret = futex_down_time(&cond, ABSTIME); [cond_timed_wait]
} while (ret < 0 && errno == EINTR);
[futex_up(&cond->lock, 1); /* release condvar */]
futex_down(&mutex->futex);
return ret;
}
With the original code, we have a "signal/broadcast lost window (a->b)"
that shouldn't be there:
SUSV2 on pthread_cond_[timed]wait:
These functions atomically release mutex(*) and cause the calling
thread to block on the condition variable cond; atomically here means
"atomically with respect to access by another thread to the mutex and
then the condition variable". That is, if another thread is able to
acquire the mutex after the about-to-block thread has released it, then
a subsequent call to pthread_cond_signal() or pthread_cond_broadcast()
in that thread behaves as if it were issued after the about-to-block
thread has blocked.
So we would need to enhance the futex_down_timed() call, to
atomically release the cond->lock on entry, re-aquiring on exit (because
of the loop).
This boils down to a cond_var syscall to me (wouldn't sys_ulock(,,OP)
a better name ? with OPs like MUTEX_UP,MUTEX_DOWN, SEMA_UPn, SEMA_DOWNn,
COND_WAIT, COND_TIMED_WAIT, COND_SIGNAL, COND_BROADCAST, RWLOCK_WRLOCK,
RWLOCK_RDLOCK,RWLOCK_UNLOCK)
Also note that we have to recalculate the relative time to sleep when
signalled - or just using an absolute time stamp.
If the syscall is interruptible, we open the "signal/broadcast lost
window (a->b)" again... hmh (Here queuing up RT signals are much better
for handling the wakeup, because you can block them, and they don't get
lost)
Alternatively when using the uwaitq: they could use a lock to serialize
an add/wait and a possibly parallel wake operation (but with the above
locks you can achieve exactly this)
-- ----------------------------------------------------------------------- Peter Waechtler - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/