2 * Copyright (C) 2007, 2009 Apple Inc. All rights reserved.
3 * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com)
4 * Copyright (C) 2011 Research In Motion Limited. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
16 * its contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include "wtf/Threading.h"
36 #include "wtf/DateMath.h"
37 #include "wtf/HashMap.h"
38 #include "wtf/OwnPtr.h"
39 #include "wtf/PassOwnPtr.h"
40 #include "wtf/StdLibExtras.h"
41 #include "wtf/ThreadFunctionInvocation.h"
42 #include "wtf/ThreadSpecific.h"
43 #include "wtf/ThreadingPrimitives.h"
44 #include "wtf/WTFThreadData.h"
46 #include "wtf/dtoa/cached-powers.h"
56 #include <objc/objc-auto.h>
60 #include <sys/syscall.h>
63 #if OS(LINUX) || OS(ANDROID)
69 static Mutex* atomicallyInitializedStaticMutex;
71 void initializeThreading()
73 // This should only be called once.
74 ASSERT(!atomicallyInitializedStaticMutex);
76 // StringImpl::empty() does not construct its static string in a threadsafe fashion,
77 // so ensure it has been initialized from here.
79 atomicallyInitializedStaticMutex = new Mutex;
81 s_dtoaP5Mutex = new Mutex;
85 void lockAtomicallyInitializedStaticMutex()
87 ASSERT(atomicallyInitializedStaticMutex);
88 atomicallyInitializedStaticMutex->lock();
91 void unlockAtomicallyInitializedStaticMutex()
93 atomicallyInitializedStaticMutex->unlock();
96 ThreadIdentifier currentThread()
99 return pthread_mach_thread_np(pthread_self());
101 return syscall(__NR_gettid);
105 return reinterpret_cast<uintptr_t>(pthread_self());
109 MutexBase::MutexBase(bool recursive)
111 pthread_mutexattr_t attr;
112 pthread_mutexattr_init(&attr);
113 pthread_mutexattr_settype(&attr, recursive ? PTHREAD_MUTEX_RECURSIVE : PTHREAD_MUTEX_NORMAL);
115 int result = pthread_mutex_init(&m_mutex.m_internalMutex, &attr);
116 ASSERT_UNUSED(result, !result);
118 m_mutex.m_recursionCount = 0;
121 pthread_mutexattr_destroy(&attr);
124 MutexBase::~MutexBase()
126 int result = pthread_mutex_destroy(&m_mutex.m_internalMutex);
127 ASSERT_UNUSED(result, !result);
130 void MutexBase::lock()
132 int result = pthread_mutex_lock(&m_mutex.m_internalMutex);
133 ASSERT_UNUSED(result, !result);
135 ++m_mutex.m_recursionCount;
139 void MutexBase::unlock()
142 ASSERT(m_mutex.m_recursionCount);
143 --m_mutex.m_recursionCount;
145 int result = pthread_mutex_unlock(&m_mutex.m_internalMutex);
146 ASSERT_UNUSED(result, !result);
149 // There is a separate tryLock implementation for the Mutex and the
150 // RecursiveMutex since on Windows we need to manually check if tryLock should
151 // succeed or not for the non-recursive mutex. On Linux the two implementations
152 // are equal except we can assert the recursion count is always zero for the
153 // non-recursive mutex.
154 bool Mutex::tryLock()
156 int result = pthread_mutex_trylock(&m_mutex.m_internalMutex);
159 // The Mutex class is not recursive, so the recursionCount should be
160 // zero after getting the lock.
161 ASSERT(!m_mutex.m_recursionCount);
162 ++m_mutex.m_recursionCount;
169 ASSERT_NOT_REACHED();
173 bool RecursiveMutex::tryLock()
175 int result = pthread_mutex_trylock(&m_mutex.m_internalMutex);
178 ++m_mutex.m_recursionCount;
185 ASSERT_NOT_REACHED();
189 ThreadCondition::ThreadCondition()
191 pthread_cond_init(&m_condition, NULL);
194 ThreadCondition::~ThreadCondition()
196 pthread_cond_destroy(&m_condition);
199 void ThreadCondition::wait(MutexBase& mutex)
201 PlatformMutex& platformMutex = mutex.impl();
202 int result = pthread_cond_wait(&m_condition, &platformMutex.m_internalMutex);
203 ASSERT_UNUSED(result, !result);
205 ++platformMutex.m_recursionCount;
209 bool ThreadCondition::timedWait(MutexBase& mutex, double absoluteTime)
211 if (absoluteTime < currentTime())
214 if (absoluteTime > INT_MAX) {
219 int timeSeconds = static_cast<int>(absoluteTime);
220 int timeNanoseconds = static_cast<int>((absoluteTime - timeSeconds) * 1E9);
223 targetTime.tv_sec = timeSeconds;
224 targetTime.tv_nsec = timeNanoseconds;
226 PlatformMutex& platformMutex = mutex.impl();
227 int result = pthread_cond_timedwait(&m_condition, &platformMutex.m_internalMutex, &targetTime);
229 ++platformMutex.m_recursionCount;
234 void ThreadCondition::signal()
236 int result = pthread_cond_signal(&m_condition);
237 ASSERT_UNUSED(result, !result);
240 void ThreadCondition::broadcast()
242 int result = pthread_cond_broadcast(&m_condition);
243 ASSERT_UNUSED(result, !result);
248 #endif // USE(PTHREADS)