source: trunk/Source/WTF/wtf/WordLock.h @ 200444

Revision 198345, 3.2 KB checked in by fpizlo@apple.com, 7 months ago (diff)

Silence leaks in ParkingLot
https://bugs.webkit.org/show_bug.cgi?id=155510

Reviewed by Alexey Proskuryakov.

ParkingLot has a concurrent hashtable that it reallocates on demand. It will not reallocate
it in steady state. The hashtable is sized to accommodate the high watermark of the number
of active threads - so long as the program doesn't just keep starting an unbounded number
of threads that are all active, the hashtable will stop resizing. Each resize operation is
designed to stay out of the way of the data-access-parallel normal path, in which two
threads operating on different lock addresses don't have to synchronize. To do this, it
simply drops the old hashtable without deleting it, so that threads that were still using
it don't crash. They will realize that they have the wrong hashtable before doing anything
bad, but we don't have a way of proving when all of those threads are no longer going to
read from the old hashtables. So, we just leak them.

This is a bounded leak, since the hashtable resizes exponentially. Thus the total memory
utilization of all hashtables, including the leaked ones, converges to a linear function of
the current hashtable's size (it's 2 * size of current hashtable).

But this leak is a problem for leaks tools, which will always report this leak. This is not
useful. It's better to silence the leak. That's what this patch does by ensuring that all
hashtables, including leaked ones, end up in a global vector. This is perf-neutral.

This requires making a StaticWordLock variant of WordLock. That's probably the biggest part
of this change.

  • wtf/ParkingLot.cpp:
  • wtf/WordLock.cpp:

(WTF::WordLockBase::lockSlow):
(WTF::WordLockBase::unlockSlow):
(WTF::WordLock::lockSlow): Deleted.
(WTF::WordLock::unlockSlow): Deleted.

  • wtf/WordLock.h:

(WTF::WordLockBase::lock):
(WTF::WordLockBase::isLocked):
(WTF::WordLock::WordLock):
(WTF::WordLock::lock): Deleted.
(WTF::WordLock::isLocked): Deleted.

Line 
1/*
2 * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#ifndef WTF_WordLock_h
27#define WTF_WordLock_h
28
29#include <wtf/Atomics.h>
30#include <wtf/Compiler.h>
31#include <wtf/Locker.h>
32#include <wtf/Noncopyable.h>
33
34namespace TestWebKitAPI {
35struct LockInspector;
36};
37
38namespace WTF {
39
40// A WordLock is a fully adaptive mutex that uses sizeof(void*) storage. It has a fast path that is
41// similar to a spinlock, and a slow path that is similar to std::mutex. In most cases, you should use
42// Lock instead. WordLock sits lower in the stack and is used to implement Lock, so Lock is the main
43// client of WordLock.
44
45struct WordLockBase {
46    void lock()
47    {
48        if (LIKELY(m_word.compareExchangeWeak(0, isLockedBit, std::memory_order_acquire))) {
49            // WordLock acquired!
50            return;
51        }
52
53        lockSlow();
54    }
55
56    void unlock()
57    {
58        if (LIKELY(m_word.compareExchangeWeak(isLockedBit, 0, std::memory_order_release))) {
59            // WordLock released, and nobody was waiting!
60            return;
61        }
62
63        unlockSlow();
64    }
65
66    bool isHeld() const
67    {
68        return m_word.load(std::memory_order_acquire) & isLockedBit;
69    }
70
71    bool isLocked() const
72    {
73        return isHeld();
74    }
75
76protected:
77    friend struct TestWebKitAPI::LockInspector;
78   
79    static const uintptr_t isLockedBit = 1;
80    static const uintptr_t isQueueLockedBit = 2;
81    static const uintptr_t queueHeadMask = 3;
82
83    WTF_EXPORT_PRIVATE void lockSlow();
84    WTF_EXPORT_PRIVATE void unlockSlow();
85
86    // Method used for testing only.
87    bool isFullyReset() const
88    {
89        return !m_word.load();
90    }
91
92    Atomic<uintptr_t> m_word;
93};
94
95class WordLock : public WordLockBase {
96    WTF_MAKE_NONCOPYABLE(WordLock);
97public:
98    WordLock()
99    {
100        m_word.store(0, std::memory_order_relaxed);
101    }
102};
103
104typedef WordLockBase StaticWordLock;
105typedef Locker<WordLockBase> WordLockHolder;
106
107} // namespace WTF
108
109using WTF::WordLock;
110using WTF::WordLockHolder;
111using WTF::StaticWordLock;
112
113#endif // WTF_WordLock_h
114
Note: See TracBrowser for help on using the repository browser.