Is this pthread_cond_wait() race possible
Torvald Riegel
triegel@redhat.com
Wed Jun 7 19:41:00 GMT 2017
On Wed, 2017-06-07 at 18:48 +0200, Sebastian Andrzej Siewior wrote:
> Hi Torvald,
>
> I've been staring at the new pthread_cond_* code. Could you please tell
> if this race possible (two wait threads looking at the same __g_signals
> value while a third thread signals a wake before going to futex_wait()):
>
> T1 T2 T3
>
> __pthread_cond_wait_common()
> __condvar_fetch_add_wseq_acquire (cond, 2);
> __pthread_mutex_unlock_usercnt();
>
> __pthread_cond_wait_common()
> __condvar_fetch_add_wseq_acquire (cond, 2);
> __pthread_mutex_unlock_usercnt();
>
> __pthread_cond_signal()
> if ((cond->__data.__g_size[g1] != 0) â¦
>
> /* Add a signal. */
> atomic_fetch_add_relaxed (cond->__data.__g_signals + g1, 2);
>
> signals = atomic_load_acquire (cond->__data.__g_signals + g);
> signals = atomic_load_acquire (cond->__data.__g_signals + g);
>
> signals = 2 signals = 2
>
> /* If there is an available signal, don't block. */
> if (signals != 0) if (signals != 0)
> break; break;
>
> while (!atomic_compare_exchange_weak_acquire (cond->__data.__g_signals + g,
> &signals, signals - 2));
> signals = 0
> while (!atomic_compare_exchange_weak_acquire (cond->__data.__g_signals + g,
> &signals, signals - 2));
> signals = (int) -2
The second CAS would expect a value of 2 in *(cond->__data.__g_signals +
g). Because the first CAS succeeded in your example, the second CAS
will fail, and T2 will update it's view of __g_signals and store that in
signals.
More information about the Libc-alpha
mailing list