Changeset 28979 in webkit


Ignore:
Timestamp:
Dec 24, 2007 10:55:23 PM (16 years ago)
Author:
mrowe@apple.com
Message:

Fix Bug 16596: ThreadSafeShared should be lock-free where possible.

Reviewed by Sam Weinig.

Implement a lock-free ThreadSafeShared for i386, x86_64, ppc and ppc64.

This is a 1.7x as fast as the lock-based implementation on x86 for a single-threaded use
of ThreadSafeShared but is closer to 280x as fast when there is heavy concurrent multi-threaded
access to a single ThreadSafeShared object.

The atomic operations are based on those used by the Boost C++ library's shared_ptr implementation.

Location:
trunk/WebCore
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r28977 r28979  
     12007-12-25  Mark Rowe  <mrowe@apple.com>
     2
     3        Reviewed by Sam Weinig.
     4
     5        Implement a lock-free ThreadSafeShared for i386, x86_64, ppc and ppc64.
     6        http://bugs.webkit.org/show_bug.cgi?id=16596
     7
     8        This is a 1.7x as fast as the lock-based implementation on x86 for a single-threaded use
     9        of ThreadSafeShared but is closer to 280x as fast when there is heavy concurrent multi-threaded
     10        access to a single ThreadSafeShared object.
     11
     12        The atomic operations are based on those used by the Boost C++ library's shared_ptr implementation.
     13
     14        * platform/Threading.h:
     15        (WebCore::atomicIncrement):
     16        (WebCore::atomicDecrement):
     17        (WebCore::ThreadSafeShared::ThreadSafeShared):
     18        (WebCore::ThreadSafeShared::ref): Use lock-free operations if available.
     19        (WebCore::ThreadSafeShared::deref): Ditto.
     20        (WebCore::ThreadSafeShared::hasOneRef):
     21        (WebCore::ThreadSafeShared::refCount):
     22        (WebCore::ThreadSafeShared::isThreadSafe):
     23
    1242007-12-24  Darin Adler  <darin@apple.com>
    225
  • trunk/WebCore/platform/Threading.h

    r28835 r28979  
    2626 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    2727 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28 *
     29 *
     30 * Note: The implementations of InterlockedIncrement and InterlockedDecrement are based
     31 * on atomic_increment and atomic_exchange_and_add from the Boost C++ Library. The license
     32 * is virtually identical to the Apple license above but is included here for completeness.
     33 *
     34 * Boost Software License - Version 1.0 - August 17th, 2003
     35 *
     36 * Permission is hereby granted, free of charge, to any person or organization
     37 * obtaining a copy of the software and accompanying documentation covered by
     38 * this license (the "Software") to use, reproduce, display, distribute,
     39 * execute, and transmit the Software, and to prepare derivative works of the
     40 * Software, and to permit third-parties to whom the Software is furnished to
     41 * do so, all subject to the following:
     42 *
     43 * The copyright notices in the Software and this entire statement, including
     44 * the above license grant, this restriction and the following disclaimer,
     45 * must be included in all copies of the Software, in whole or in part, and
     46 * all derivative works of the Software, unless such copies or derivative
     47 * works are solely in the form of machine-executable object code generated by
     48 * a source language processor.
     49 *
     50 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     51 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     52 * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
     53 * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
     54 * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
     55 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     56 * DEALINGS IN THE SOFTWARE.
    2857 */
    2958
     
    3362#include <wtf/Assertions.h>
    3463#include <wtf/Noncopyable.h>
     64
     65#if PLATFORM(WIN_OS)
     66#include <windows.h>
     67#endif
    3568
    3669#if USE(PTHREADS)
     
    124157    PlatformCondition m_condition;
    125158};
    126    
     159
     160#if PLATFORM(WIN_OS)
     161#define WTF_USE_LOCKFREE_THREADSAFESHARED 1
     162
     163inline void atomicIncrement(int volatile* addened) { InterlockedIncrement(addened); }
     164inline int atomicDecrement(int volatile* addened) { return InterlockedDecrement(addened); }
     165
     166#elif COMPILER(GCC) && (PLATFORM(X86) || PLATFORM(X86_64) || PLATFORM(PPC) || PLATFORM(PPC64))
     167#define WTF_USE_LOCKFREE_THREADSAFESHARED 1
     168
     169inline void atomicIncrement(int volatile* addend)
     170{
     171#if PLATFORM(X86) || PLATFORM(X86_64)
     172    __asm__(
     173        "lock\n\t"
     174        "incl %0":
     175        "=m"(*addend): // output (%0)
     176        "m"(*addend): // input (%1)
     177        "cc"
     178    );
     179#else
     180    int tmp;
     181    __asm__(
     182        "0:\n\t"
     183        "lwarx %1, 0, %2\n\t"
     184        "addi %1, %1, 1\n\t"
     185        "stwcx. %1, 0, %2\n\t"
     186        "bne- 0b":
     187
     188        "=m"(*addend), "=&b"(tmp):
     189        "r"(addend), "m"(*addend):
     190        "cc"
     191    );
     192#endif
     193}
     194
     195inline int atomicDecrement(int volatile* addend)
     196{
     197#if PLATFORM(X86) || PLATFORM(X86_64)
     198    int readval = 0;
     199    __asm__ __volatile__
     200    (
     201        "lock\n\t"
     202        "xadd %1, %0":
     203        "=m"(*addend), "=r"(readval): // outputs (%0, %1)
     204        "m"(*addend), "1"(-1): // inputs (%2, %3 == %1)
     205        "memory", "cc" // clobbers
     206    );
     207    return readval - 1;
     208#else
     209    int readval;
     210    __asm__ __volatile__(
     211        "sync\n\t"
     212        "0:\n\t"
     213        "lwarx %1, 0, %2\n\t"
     214        "addi %1, %1, -1\n\t"
     215        "stwcx. %1, 0, %2\n\t"
     216        "bne- 0b\n\t"
     217        "isync":
     218
     219        "=m"(*addend), "=&b"(readval):
     220        "r"(addend), "m"(*addend):
     221        "memory", "cc"
     222    );
     223    return readval;
     224#endif
     225}
     226#endif
     227
    127228template<class T> class ThreadSafeShared : Noncopyable {
    128229public:
    129230    ThreadSafeShared()
    130231        : m_refCount(0)
    131 #ifndef NDEBUG
    132         , m_inDestructor(0)
    133 #endif
    134232    {
    135233    }
     
    137235    void ref()
    138236    {
     237#if USE(LOCKFREE_THREADSAFESHARED)
     238        atomicIncrement(&m_refCount);
     239#else
    139240        MutexLocker locker(m_mutex);
    140         ASSERT(!m_inDestructor);
    141241        ++m_refCount;
     242#endif
    142243    }
    143244
    144245    void deref()
    145246    {
     247#if USE(LOCKFREE_THREADSAFESHARED)
     248        if (atomicDecrement(&m_refCount) <= 0)
     249#else
    146250        {
    147251            MutexLocker locker(m_mutex);
    148             ASSERT(!m_inDestructor);
    149252            --m_refCount;
    150253        }
    151        
    152         if (m_refCount <= 0) {
    153 #ifndef NDEBUG
    154             m_inDestructor = true;
     254        if (m_refCount <= 0)
    155255#endif
    156256            delete static_cast<T*>(this);
    157         }
    158257    }
    159258
    160259    bool hasOneRef()
    161260    {
     261        return refCount() == 1;
     262    }
     263
     264    int refCount() const
     265    {
     266#if !USE(LOCKFREE_THREADSAFESHARED)
    162267        MutexLocker locker(m_mutex);
    163         ASSERT(!m_inDestructor);
    164         return m_refCount == 1;
    165     }
    166 
    167     int refCount() const
    168     {
    169         MutexLocker locker(m_mutex);
    170         return m_refCount;
    171     }
    172 
    173     bool isThreadSafe() { return true; }
    174    
    175 private:
     268#endif
     269        return static_cast<int const volatile &>(m_refCount);
     270    }
     271
     272private:
     273    int m_refCount;
     274#if !USE(LOCKFREE_THREADSAFESHARED)
    176275    mutable Mutex m_mutex;
    177     int m_refCount;
    178 #ifndef NDEBUG
    179     bool m_inDestructor;
    180276#endif
    181277};
Note: See TracChangeset for help on using the changeset viewer.