Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / wtf / ThreadingPthreads.cpp
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.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
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.
18  *
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.
29  */
30
31 #include "config.h"
32 #include "wtf/Threading.h"
33
34 #if USE(PTHREADS)
35
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>
47
48 #if !COMPILER(MSVC)
49 #include <limits.h>
50 #include <sched.h>
51 #include <sys/time.h>
52 #endif
53
54 #if OS(MACOSX)
55 #include <objc/objc-auto.h>
56 #endif
57
58 #if OS(LINUX)
59 #include <sys/syscall.h>
60 #endif
61
62 #if OS(LINUX) || OS(ANDROID)
63 #include <unistd.h>
64 #endif
65
66 namespace WTF {
67
68 static Mutex* atomicallyInitializedStaticMutex;
69
70 void initializeThreading()
71 {
72     // This should only be called once.
73     ASSERT(!atomicallyInitializedStaticMutex);
74
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();
86 }
87
88 void lockAtomicallyInitializedStaticMutex()
89 {
90     ASSERT(atomicallyInitializedStaticMutex);
91     atomicallyInitializedStaticMutex->lock();
92 }
93
94 void unlockAtomicallyInitializedStaticMutex()
95 {
96     atomicallyInitializedStaticMutex->unlock();
97 }
98
99 ThreadIdentifier currentThread()
100 {
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
110 }
111
112 MutexBase::MutexBase(bool recursive)
113 {
114     pthread_mutexattr_t attr;
115     pthread_mutexattr_init(&attr);
116     pthread_mutexattr_settype(&attr, recursive ? PTHREAD_MUTEX_RECURSIVE : PTHREAD_MUTEX_NORMAL);
117
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
123
124     pthread_mutexattr_destroy(&attr);
125 }
126
127 MutexBase::~MutexBase()
128 {
129     int result = pthread_mutex_destroy(&m_mutex.m_internalMutex);
130     ASSERT_UNUSED(result, !result);
131 }
132
133 void MutexBase::lock()
134 {
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
140 }
141
142 void MutexBase::unlock()
143 {
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);
150 }
151
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()
158 {
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;
168     }
169     if (result == EBUSY)
170         return false;
171
172     ASSERT_NOT_REACHED();
173     return false;
174 }
175
176 bool RecursiveMutex::tryLock()
177 {
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;
184     }
185     if (result == EBUSY)
186         return false;
187
188     ASSERT_NOT_REACHED();
189     return false;
190 }
191
192 ThreadCondition::ThreadCondition()
193 {
194     pthread_cond_init(&m_condition, NULL);
195 }
196
197 ThreadCondition::~ThreadCondition()
198 {
199     pthread_cond_destroy(&m_condition);
200 }
201
202 void ThreadCondition::wait(MutexBase& mutex)
203 {
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
210 }
211
212 bool ThreadCondition::timedWait(MutexBase& mutex, double absoluteTime)
213 {
214     if (absoluteTime < currentTime())
215         return false;
216
217     if (absoluteTime > INT_MAX) {
218         wait(mutex);
219         return true;
220     }
221
222     int timeSeconds = static_cast<int>(absoluteTime);
223     int timeNanoseconds = static_cast<int>((absoluteTime - timeSeconds) * 1E9);
224
225     timespec targetTime;
226     targetTime.tv_sec = timeSeconds;
227     targetTime.tv_nsec = timeNanoseconds;
228
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;
235 }
236
237 void ThreadCondition::signal()
238 {
239     int result = pthread_cond_signal(&m_condition);
240     ASSERT_UNUSED(result, !result);
241 }
242
243 void ThreadCondition::broadcast()
244 {
245     int result = pthread_cond_broadcast(&m_condition);
246     ASSERT_UNUSED(result, !result);
247 }
248
249 } // namespace WTF
250
251 #endif // USE(PTHREADS)