Upstream version 10.39.225.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/ThreadFunctionInvocation.h"
42 #include "wtf/ThreadSpecific.h"
43 #include "wtf/ThreadingPrimitives.h"
44 #include "wtf/WTFThreadData.h"
45 #include "wtf/dtoa.h"
46 #include "wtf/dtoa/cached-powers.h"
47 #include <errno.h>
48
49 #if !COMPILER(MSVC)
50 #include <limits.h>
51 #include <sched.h>
52 #include <sys/time.h>
53 #endif
54
55 #if OS(MACOSX)
56 #include <objc/objc-auto.h>
57 #endif
58
59 #if OS(LINUX)
60 #include <sys/syscall.h>
61 #endif
62
63 #if OS(LINUX) || OS(ANDROID)
64 #include <unistd.h>
65 #endif
66
67 namespace WTF {
68
69 static Mutex* atomicallyInitializedStaticMutex;
70
71 void initializeThreading()
72 {
73     // This should only be called once.
74     ASSERT(!atomicallyInitializedStaticMutex);
75
76     // StringImpl::empty() does not construct its static string in a threadsafe fashion,
77     // so ensure it has been initialized from here.
78     StringImpl::empty();
79     atomicallyInitializedStaticMutex = new Mutex;
80     wtfThreadData();
81     s_dtoaP5Mutex = new Mutex;
82     initializeDates();
83 }
84
85 void lockAtomicallyInitializedStaticMutex()
86 {
87     ASSERT(atomicallyInitializedStaticMutex);
88     atomicallyInitializedStaticMutex->lock();
89 }
90
91 void unlockAtomicallyInitializedStaticMutex()
92 {
93     atomicallyInitializedStaticMutex->unlock();
94 }
95
96 ThreadIdentifier currentThread()
97 {
98 #if OS(MACOSX)
99     return pthread_mach_thread_np(pthread_self());
100 #elif OS(LINUX)
101     return syscall(__NR_gettid);
102 #elif OS(ANDROID)
103     return gettid();
104 #else
105     return reinterpret_cast<uintptr_t>(pthread_self());
106 #endif
107 }
108
109 MutexBase::MutexBase(bool recursive)
110 {
111     pthread_mutexattr_t attr;
112     pthread_mutexattr_init(&attr);
113     pthread_mutexattr_settype(&attr, recursive ? PTHREAD_MUTEX_RECURSIVE : PTHREAD_MUTEX_NORMAL);
114
115     int result = pthread_mutex_init(&m_mutex.m_internalMutex, &attr);
116     ASSERT_UNUSED(result, !result);
117 #if ENABLE(ASSERT)
118     m_mutex.m_recursionCount = 0;
119 #endif
120
121     pthread_mutexattr_destroy(&attr);
122 }
123
124 MutexBase::~MutexBase()
125 {
126     int result = pthread_mutex_destroy(&m_mutex.m_internalMutex);
127     ASSERT_UNUSED(result, !result);
128 }
129
130 void MutexBase::lock()
131 {
132     int result = pthread_mutex_lock(&m_mutex.m_internalMutex);
133     ASSERT_UNUSED(result, !result);
134 #if ENABLE(ASSERT)
135     ++m_mutex.m_recursionCount;
136 #endif
137 }
138
139 void MutexBase::unlock()
140 {
141 #if ENABLE(ASSERT)
142     ASSERT(m_mutex.m_recursionCount);
143     --m_mutex.m_recursionCount;
144 #endif
145     int result = pthread_mutex_unlock(&m_mutex.m_internalMutex);
146     ASSERT_UNUSED(result, !result);
147 }
148
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()
155 {
156     int result = pthread_mutex_trylock(&m_mutex.m_internalMutex);
157     if (result == 0) {
158 #if ENABLE(ASSERT)
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;
163 #endif
164         return true;
165     }
166     if (result == EBUSY)
167         return false;
168
169     ASSERT_NOT_REACHED();
170     return false;
171 }
172
173 bool RecursiveMutex::tryLock()
174 {
175     int result = pthread_mutex_trylock(&m_mutex.m_internalMutex);
176     if (result == 0) {
177 #if ENABLE(ASSERT)
178         ++m_mutex.m_recursionCount;
179 #endif
180         return true;
181     }
182     if (result == EBUSY)
183         return false;
184
185     ASSERT_NOT_REACHED();
186     return false;
187 }
188
189 ThreadCondition::ThreadCondition()
190 {
191     pthread_cond_init(&m_condition, NULL);
192 }
193
194 ThreadCondition::~ThreadCondition()
195 {
196     pthread_cond_destroy(&m_condition);
197 }
198
199 void ThreadCondition::wait(MutexBase& mutex)
200 {
201     PlatformMutex& platformMutex = mutex.impl();
202     int result = pthread_cond_wait(&m_condition, &platformMutex.m_internalMutex);
203     ASSERT_UNUSED(result, !result);
204 #if ENABLE(ASSERT)
205     ++platformMutex.m_recursionCount;
206 #endif
207 }
208
209 bool ThreadCondition::timedWait(MutexBase& mutex, double absoluteTime)
210 {
211     if (absoluteTime < currentTime())
212         return false;
213
214     if (absoluteTime > INT_MAX) {
215         wait(mutex);
216         return true;
217     }
218
219     int timeSeconds = static_cast<int>(absoluteTime);
220     int timeNanoseconds = static_cast<int>((absoluteTime - timeSeconds) * 1E9);
221
222     timespec targetTime;
223     targetTime.tv_sec = timeSeconds;
224     targetTime.tv_nsec = timeNanoseconds;
225
226     PlatformMutex& platformMutex = mutex.impl();
227     int result = pthread_cond_timedwait(&m_condition, &platformMutex.m_internalMutex, &targetTime);
228 #if ENABLE(ASSERT)
229     ++platformMutex.m_recursionCount;
230 #endif
231     return result == 0;
232 }
233
234 void ThreadCondition::signal()
235 {
236     int result = pthread_cond_signal(&m_condition);
237     ASSERT_UNUSED(result, !result);
238 }
239
240 void ThreadCondition::broadcast()
241 {
242     int result = pthread_cond_broadcast(&m_condition);
243     ASSERT_UNUSED(result, !result);
244 }
245
246 } // namespace WTF
247
248 #endif // USE(PTHREADS)