[llvm-bugs] [Bug 47013] New: counting_semaphore deadlocks?
via llvm-bugs
llvm-bugs at lists.llvm.org
Thu Aug 6 02:01:23 PDT 2020
https://bugs.llvm.org/show_bug.cgi?id=47013
Bug ID: 47013
Summary: counting_semaphore deadlocks?
Product: libc++
Version: 11.0
Hardware: PC
OS: Windows NT
Status: NEW
Severity: normal
Priority: P
Component: All Bugs
Assignee: unassignedclangbugs at nondot.org
Reporter: gutenev at gmail.com
CC: llvm-bugs at lists.llvm.org, mclow.lists at gmail.com
counting_semaphore::release only notifies waiting thread when count reaches
zero. it only notifies one waiting thread if __update == 1:
void release(ptrdiff_t __update = 1)
{
if(0 < __a.fetch_add(__update, memory_order_release))
;
else if(__update > 1)
__a.notify_all();
else
__a.notify_one();
}
https://github.com/llvm/llvm-project/blob/4357986b411dd164932c66ebfe4a9cf96a7d74cd/libcxx/include/semaphore#L86-L94
counting_semaphore::acquire enters waiting when __a is observed to be zero:
void acquire()
{
auto const __test_fn = [=]() -> bool {
auto __old = __a.load(memory_order_relaxed);
return (__old != 0) && __a.compare_exchange_strong(__old, __old -
1, memory_order_acquire, memory_order_relaxed);
};
__cxx_atomic_wait(&__a.__a_, __test_fn);
}
https://github.com/llvm/llvm-project/blob/4357986b411dd164932c66ebfe4a9cf96a7d74cd/libcxx/include/semaphore#L96-L103
Now assume two threads are waiting on acquire call:
T1: { s.acquire(); }
T2: { s.acquire(); }
And third thread calls release, to release two times by one:
T3: { s.release(1); s.release(1); }
first release call unblocks one waiting thread. Assume it is T1, and assume
that before T1 did compare_exchange_strong, T3 executes the second release
call. Since second release observes __a to be 1 (from the previous call), it
never releases T2. So T2 stays blocked while __a == 1.
---
If this analysis is correct, I would have called notify_all() for all cases if
__a was observed to be 0. Except for counting_semaphore<1> specialization,
where it is always safe to call notify_one().
Another alternative could be avoiding 0 < __a.fetch_add check, this will
unblock T2 in subsequent release in my example, but it looks like to be less
efficient and more complex.
--
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20200806/9d294179/attachment-0001.html>
More information about the llvm-bugs
mailing list