[llvm] r256087 - ThreadPool unittest: reimplement concurrency test, deterministically this time.

Mehdi Amini via llvm-commits llvm-commits at lists.llvm.org
Sat Dec 19 15:02:22 PST 2015


> On Dec 19, 2015, at 9:50 AM, Mehdi Amini via llvm-commits <llvm-commits at lists.llvm.org> wrote:
> 
> 
> 
> Sent from my iPhone
> 
>> On Dec 18, 2015, at 11:59 PM, Vedant Kumar <vsk at apple.com> wrote:
>> 
>> 
>>>> On Dec 18, 2015, at 8:30 PM, Vedant Kumar <vsk at apple.com> wrote:
>>>> 
>>>> Thanks :).
>>>> 
>>>>> +
>>>>> +  /// Make sure this thread not progress faster than the main thread.
>>>>> +  void waitForMainThread() {
>>>>> +    while (!MainThreadReady) {
>>>>> +      std::unique_lock<std::mutex> LockGuard(WaitMainThreadMutex);
>>>>> +      WaitMainThread.wait(LockGuard, [&] { return MainThreadReady; });
>>>> 
>>>> Nit: wait(CV, Predicate) is guaranteed to not wake up spuriously. The surrounding while loop here is redundant.
>>>> 
>>>> 
>>>>> +    }
>>>>> +  }
>>>>> +  std::condition_variable WaitMainThread;
>>>>> +  std::mutex WaitMainThreadMutex;
>>>>> +  bool MainThreadReady;
>>>>> +
>>>>> };
>>>>> 
>>>>> #define CHECK_UNSUPPORTED() \
>>>>> @@ -68,12 +80,17 @@ TEST_F(ThreadPoolTest, AsyncBarrier) {
>>>>> 
>>>>> std::atomic_int checked_in{0};
>>>>> 
>>>>> +  MainThreadReady = false;
>>>>> ThreadPool Pool;
>>>>> for (size_t i = 0; i < 5; ++i) {
>>>>> -    Pool.async([&checked_in, i] {
>>>>> +    Pool.async([this, &checked_in, i] {
>>>>> +      waitForMainThread();
>>>>>   ++checked_in;
>>>>> });
>>>>> }
>>>>> +  ASSERT_EQ(0, checked_in);
>>>>> +  MainThreadReady = true;
>>>> 
>>>> Paranoid nit: Can this assignment be reordered before the assert? If so, the main thread could context-switch to an async worker that's awake.
>>> 
>>> It's even worse: you're supposed to get the mutex before notifying a condition variable. I always forget that, Teresa already caught this on the original patch.
>>> 
>>>> Later, the assert will fail. Wdyt of changing this to --
>>>> 
>>>> void setMainThreadReadyState(bool Ready) {
>>>> std::unique_lock<std::mutex> LockGuard(WaitMainThreadMutex);
>>>> MainThreadReady = Ready;
>>>> }
>>>> 
>>>> setMainThreadReadyState(true);
>>>> 
>>>> That should still test the async behavior.
>>> 
>>> Would need the notify_all while holding the mutex. Otherwise LGTM.
>> 
>> Done, r256096.
>> 
> 
> Thanks!
> 
> (But I was terribly wrong about the condition variable and the lock, I'll fix it later. We need to hold the lock while changing the flag used in the condition::wait, but not during the notify)

Fixed in r256111, along with some restructuring.

— 
Mehdi


More information about the llvm-commits mailing list