Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / third_party / WebKit / Source / wtf / ThreadingPthreads.cpp
blob42091057fd34e47a65a4a6f406700eeb34c311eb
1 /*
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
8 * are met:
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.
31 #include "config.h"
32 #include "wtf/Threading.h"
34 #if USE(PTHREADS)
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/ThreadSpecific.h"
42 #include "wtf/ThreadingPrimitives.h"
43 #include "wtf/WTFThreadData.h"
44 #include "wtf/dtoa.h"
45 #include "wtf/dtoa/cached-powers.h"
46 #include <errno.h>
48 #if !COMPILER(MSVC)
49 #include <limits.h>
50 #include <sched.h>
51 #include <sys/time.h>
52 #endif
54 #if OS(MACOSX)
55 #include <objc/objc-auto.h>
56 #endif
58 #if OS(LINUX)
59 #include <sys/syscall.h>
60 #endif
62 #if OS(LINUX) || OS(ANDROID)
63 #include <unistd.h>
64 #endif
66 namespace WTF {
68 static Mutex* atomicallyInitializedStaticMutex;
70 void initializeThreading()
72 // This should only be called once.
73 ASSERT(!atomicallyInitializedStaticMutex);
75 // StringImpl::empty() does not construct its static string in a threadsafe fashion,
76 // so ensure it has been initialized from here.
77 StringImpl::empty();
78 StringImpl::empty16Bit();
79 atomicallyInitializedStaticMutex = new Mutex;
80 wtfThreadData();
81 s_dtoaP5Mutex = new Mutex;
82 initializeDates();
83 // Force initialization of static DoubleToStringConverter converter variable
84 // inside EcmaScriptConverter function while we are in single thread mode.
85 double_conversion::DoubleToStringConverter::EcmaScriptConverter();
88 void lockAtomicallyInitializedStaticMutex()
90 ASSERT(atomicallyInitializedStaticMutex);
91 atomicallyInitializedStaticMutex->lock();
94 void unlockAtomicallyInitializedStaticMutex()
96 atomicallyInitializedStaticMutex->unlock();
99 ThreadIdentifier currentThread()
101 #if OS(MACOSX)
102 return pthread_mach_thread_np(pthread_self());
103 #elif OS(LINUX)
104 return syscall(__NR_gettid);
105 #elif OS(ANDROID)
106 return gettid();
107 #else
108 return reinterpret_cast<uintptr_t>(pthread_self());
109 #endif
112 MutexBase::MutexBase(bool recursive)
114 pthread_mutexattr_t attr;
115 pthread_mutexattr_init(&attr);
116 pthread_mutexattr_settype(&attr, recursive ? PTHREAD_MUTEX_RECURSIVE : PTHREAD_MUTEX_NORMAL);
118 int result = pthread_mutex_init(&m_mutex.m_internalMutex, &attr);
119 ASSERT_UNUSED(result, !result);
120 #if ENABLE(ASSERT)
121 m_mutex.m_recursionCount = 0;
122 #endif
124 pthread_mutexattr_destroy(&attr);
127 MutexBase::~MutexBase()
129 int result = pthread_mutex_destroy(&m_mutex.m_internalMutex);
130 ASSERT_UNUSED(result, !result);
133 void MutexBase::lock()
135 int result = pthread_mutex_lock(&m_mutex.m_internalMutex);
136 ASSERT_UNUSED(result, !result);
137 #if ENABLE(ASSERT)
138 ++m_mutex.m_recursionCount;
139 #endif
142 void MutexBase::unlock()
144 #if ENABLE(ASSERT)
145 ASSERT(m_mutex.m_recursionCount);
146 --m_mutex.m_recursionCount;
147 #endif
148 int result = pthread_mutex_unlock(&m_mutex.m_internalMutex);
149 ASSERT_UNUSED(result, !result);
152 // There is a separate tryLock implementation for the Mutex and the
153 // RecursiveMutex since on Windows we need to manually check if tryLock should
154 // succeed or not for the non-recursive mutex. On Linux the two implementations
155 // are equal except we can assert the recursion count is always zero for the
156 // non-recursive mutex.
157 bool Mutex::tryLock()
159 int result = pthread_mutex_trylock(&m_mutex.m_internalMutex);
160 if (result == 0) {
161 #if ENABLE(ASSERT)
162 // The Mutex class is not recursive, so the recursionCount should be
163 // zero after getting the lock.
164 ASSERT(!m_mutex.m_recursionCount);
165 ++m_mutex.m_recursionCount;
166 #endif
167 return true;
169 if (result == EBUSY)
170 return false;
172 ASSERT_NOT_REACHED();
173 return false;
176 bool RecursiveMutex::tryLock()
178 int result = pthread_mutex_trylock(&m_mutex.m_internalMutex);
179 if (result == 0) {
180 #if ENABLE(ASSERT)
181 ++m_mutex.m_recursionCount;
182 #endif
183 return true;
185 if (result == EBUSY)
186 return false;
188 ASSERT_NOT_REACHED();
189 return false;
192 ThreadCondition::ThreadCondition()
194 pthread_cond_init(&m_condition, NULL);
197 ThreadCondition::~ThreadCondition()
199 pthread_cond_destroy(&m_condition);
202 void ThreadCondition::wait(MutexBase& mutex)
204 PlatformMutex& platformMutex = mutex.impl();
205 int result = pthread_cond_wait(&m_condition, &platformMutex.m_internalMutex);
206 ASSERT_UNUSED(result, !result);
207 #if ENABLE(ASSERT)
208 ++platformMutex.m_recursionCount;
209 #endif
212 bool ThreadCondition::timedWait(MutexBase& mutex, double absoluteTime)
214 if (absoluteTime < currentTime())
215 return false;
217 if (absoluteTime > INT_MAX) {
218 wait(mutex);
219 return true;
222 int timeSeconds = static_cast<int>(absoluteTime);
223 int timeNanoseconds = static_cast<int>((absoluteTime - timeSeconds) * 1E9);
225 timespec targetTime;
226 targetTime.tv_sec = timeSeconds;
227 targetTime.tv_nsec = timeNanoseconds;
229 PlatformMutex& platformMutex = mutex.impl();
230 int result = pthread_cond_timedwait(&m_condition, &platformMutex.m_internalMutex, &targetTime);
231 #if ENABLE(ASSERT)
232 ++platformMutex.m_recursionCount;
233 #endif
234 return result == 0;
237 void ThreadCondition::signal()
239 int result = pthread_cond_signal(&m_condition);
240 ASSERT_UNUSED(result, !result);
243 void ThreadCondition::broadcast()
245 int result = pthread_cond_broadcast(&m_condition);
246 ASSERT_UNUSED(result, !result);
249 #if ENABLE(ASSERT)
250 static bool s_threadCreated = false;
252 bool isAtomicallyInitializedStaticMutexLockHeld()
254 return atomicallyInitializedStaticMutex && atomicallyInitializedStaticMutex->locked();
257 bool isBeforeThreadCreated()
259 return !s_threadCreated;
262 void willCreateThread()
264 s_threadCreated = true;
266 #endif
268 } // namespace WTF
270 #endif // USE(PTHREADS)