Merge "Fix build break by removing TIZEN_RECORDING_SURFACE_SET" into tizen_2.1
[framework/web/webkit-efl.git] / Source / WTF / 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 "Threading.h"
33
34 #if USE(PTHREADS)
35
36 #include "CurrentTime.h"
37 #include "DateMath.h"
38 #include "dtoa.h"
39 #include "dtoa/cached-powers.h"
40 #include "HashMap.h"
41 #include "RandomNumberSeed.h"
42 #include "StdLibExtras.h"
43 #include "ThreadFunctionInvocation.h"
44 #include "ThreadIdentifierDataPthreads.h"
45 #include "ThreadSpecific.h"
46 #include "UnusedParam.h"
47 #include <wtf/OwnPtr.h>
48 #include <wtf/PassOwnPtr.h>
49 #include <wtf/WTFThreadData.h>
50 #include <errno.h>
51
52 #if !COMPILER(MSVC)
53 #include <limits.h>
54 #include <sched.h>
55 #include <sys/time.h>
56 #endif
57
58 #if OS(MAC_OS_X) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
59 #include <objc/objc-auto.h>
60 #endif
61
62 namespace WTF {
63
64 typedef HashMap<ThreadIdentifier, pthread_t> ThreadMap;
65
66 static Mutex* atomicallyInitializedStaticMutex;
67
68 void clearPthreadHandleForIdentifier(ThreadIdentifier);
69
70 static Mutex& threadMapMutex()
71 {
72     DEFINE_STATIC_LOCAL(Mutex, mutex, ());
73     return mutex;
74 }
75
76 void initializeThreading()
77 {
78     if (atomicallyInitializedStaticMutex)
79         return;
80
81     WTF::double_conversion::initialize();
82     // StringImpl::empty() does not construct its static string in a threadsafe fashion,
83     // so ensure it has been initialized from here.
84     StringImpl::empty();
85     atomicallyInitializedStaticMutex = new Mutex;
86     threadMapMutex();
87     initializeRandomNumberGenerator();
88     ThreadIdentifierData::initializeOnce();
89     wtfThreadData();
90     s_dtoaP5Mutex = new Mutex;
91     initializeDates();
92 }
93
94 void lockAtomicallyInitializedStaticMutex()
95 {
96     ASSERT(atomicallyInitializedStaticMutex);
97     atomicallyInitializedStaticMutex->lock();
98 }
99
100 void unlockAtomicallyInitializedStaticMutex()
101 {
102     atomicallyInitializedStaticMutex->unlock();
103 }
104
105 static ThreadMap& threadMap()
106 {
107     DEFINE_STATIC_LOCAL(ThreadMap, map, ());
108     return map;
109 }
110
111 static ThreadIdentifier identifierByPthreadHandle(const pthread_t& pthreadHandle)
112 {
113     MutexLocker locker(threadMapMutex());
114
115     ThreadMap::iterator i = threadMap().begin();
116     for (; i != threadMap().end(); ++i) {
117         if (pthread_equal(i->second, pthreadHandle))
118             return i->first;
119     }
120
121     return 0;
122 }
123
124 static ThreadIdentifier establishIdentifierForPthreadHandle(const pthread_t& pthreadHandle)
125 {
126     ASSERT(!identifierByPthreadHandle(pthreadHandle));
127
128     MutexLocker locker(threadMapMutex());
129
130     static ThreadIdentifier identifierCount = 1;
131
132     threadMap().add(identifierCount, pthreadHandle);
133
134     return identifierCount++;
135 }
136
137 static pthread_t pthreadHandleForIdentifier(ThreadIdentifier id)
138 {
139     MutexLocker locker(threadMapMutex());
140
141     return threadMap().get(id);
142 }
143
144 void clearPthreadHandleForIdentifier(ThreadIdentifier id)
145 {
146     MutexLocker locker(threadMapMutex());
147
148     ASSERT(threadMap().contains(id));
149
150     threadMap().remove(id);
151 }
152
153 static void* wtfThreadEntryPoint(void* param)
154 {
155     // Balanced by .leakPtr() in createThreadInternal.
156     OwnPtr<ThreadFunctionInvocation> invocation = adoptPtr(static_cast<ThreadFunctionInvocation*>(param));
157     invocation->function(invocation->data);
158
159     return 0;
160 }
161
162 ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, const char*)
163 {
164     OwnPtr<ThreadFunctionInvocation> invocation = adoptPtr(new ThreadFunctionInvocation(entryPoint, data));
165     pthread_t threadHandle;
166     if (pthread_create(&threadHandle, 0, wtfThreadEntryPoint, invocation.get())) {
167         LOG_ERROR("Failed to create pthread at entry point %p with data %p", wtfThreadEntryPoint, invocation.get());
168         return 0;
169     }
170
171     // Balanced by adoptPtr() in wtfThreadEntryPoint.
172     ThreadFunctionInvocation* leakedInvocation = invocation.leakPtr();
173     UNUSED_PARAM(leakedInvocation);
174
175     return establishIdentifierForPthreadHandle(threadHandle);
176 }
177
178 void initializeCurrentThreadInternal(const char* threadName)
179 {
180 #if HAVE(PTHREAD_SETNAME_NP)
181     pthread_setname_np(threadName);
182 #elif OS(QNX)
183     pthread_setname_np(pthread_self(), threadName);
184 #else
185     UNUSED_PARAM(threadName);
186 #endif
187
188 #if OS(MAC_OS_X) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
189     // All threads that potentially use APIs above the BSD layer must be registered with the Objective-C
190     // garbage collector in case API implementations use garbage-collected memory.
191     objc_registerThreadWithCollector();
192 #endif
193
194     ThreadIdentifier id = identifierByPthreadHandle(pthread_self());
195     ASSERT(id);
196     ThreadIdentifierData::initialize(id);
197 }
198
199 int waitForThreadCompletion(ThreadIdentifier threadID)
200 {
201     ASSERT(threadID);
202
203     pthread_t pthreadHandle = pthreadHandleForIdentifier(threadID);
204     if (!pthreadHandle)
205         return 0;
206
207     int joinResult = pthread_join(pthreadHandle, 0);
208     if (joinResult == EDEADLK)
209         LOG_ERROR("ThreadIdentifier %u was found to be deadlocked trying to quit", threadID);
210
211     return joinResult;
212 }
213
214 void detachThread(ThreadIdentifier threadID)
215 {
216     ASSERT(threadID);
217
218     pthread_t pthreadHandle = pthreadHandleForIdentifier(threadID);
219     if (!pthreadHandle)
220         return;
221
222     pthread_detach(pthreadHandle);
223 }
224
225 void yield()
226 {
227     sched_yield();
228 }
229
230 ThreadIdentifier currentThread()
231 {
232     ThreadIdentifier id = ThreadIdentifierData::identifier();
233     if (id)
234         return id;
235
236     // Not a WTF-created thread, ThreadIdentifier is not established yet.
237     id = establishIdentifierForPthreadHandle(pthread_self());
238     ThreadIdentifierData::initialize(id);
239     return id;
240 }
241
242 Mutex::Mutex()
243 {
244     pthread_mutexattr_t attr;
245     pthread_mutexattr_init(&attr);
246     pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
247
248     int result = pthread_mutex_init(&m_mutex, &attr);
249     ASSERT_UNUSED(result, !result);
250
251     pthread_mutexattr_destroy(&attr);
252 }
253
254 Mutex::~Mutex()
255 {
256     int result = pthread_mutex_destroy(&m_mutex);
257     ASSERT_UNUSED(result, !result);
258 }
259
260 void Mutex::lock()
261 {
262     int result = pthread_mutex_lock(&m_mutex);
263     ASSERT_UNUSED(result, !result);
264 }
265
266 bool Mutex::tryLock()
267 {
268     int result = pthread_mutex_trylock(&m_mutex);
269
270     if (result == 0)
271         return true;
272     if (result == EBUSY)
273         return false;
274
275     ASSERT_NOT_REACHED();
276     return false;
277 }
278
279 void Mutex::unlock()
280 {
281     int result = pthread_mutex_unlock(&m_mutex);
282     ASSERT_UNUSED(result, !result);
283 }
284
285 #if HAVE(PTHREAD_RWLOCK)
286 ReadWriteLock::ReadWriteLock()
287 {
288     pthread_rwlock_init(&m_readWriteLock, NULL);
289 }
290
291 ReadWriteLock::~ReadWriteLock()
292 {
293     pthread_rwlock_destroy(&m_readWriteLock);
294 }
295
296 void ReadWriteLock::readLock()
297 {
298     int result = pthread_rwlock_rdlock(&m_readWriteLock);
299     ASSERT_UNUSED(result, !result);
300 }
301
302 bool ReadWriteLock::tryReadLock()
303 {
304     int result = pthread_rwlock_tryrdlock(&m_readWriteLock);
305
306     if (result == 0)
307         return true;
308     if (result == EBUSY || result == EAGAIN)
309         return false;
310
311     ASSERT_NOT_REACHED();
312     return false;
313 }
314
315 void ReadWriteLock::writeLock()
316 {
317     int result = pthread_rwlock_wrlock(&m_readWriteLock);
318     ASSERT_UNUSED(result, !result);
319 }
320
321 bool ReadWriteLock::tryWriteLock()
322 {
323     int result = pthread_rwlock_trywrlock(&m_readWriteLock);
324
325     if (result == 0)
326         return true;
327     if (result == EBUSY || result == EAGAIN)
328         return false;
329
330     ASSERT_NOT_REACHED();
331     return false;
332 }
333
334 void ReadWriteLock::unlock()
335 {
336     int result = pthread_rwlock_unlock(&m_readWriteLock);
337     ASSERT_UNUSED(result, !result);
338 }
339 #endif  // HAVE(PTHREAD_RWLOCK)
340
341 ThreadCondition::ThreadCondition()
342
343     pthread_cond_init(&m_condition, NULL);
344 }
345
346 ThreadCondition::~ThreadCondition()
347 {
348     pthread_cond_destroy(&m_condition);
349 }
350     
351 void ThreadCondition::wait(Mutex& mutex)
352 {
353     int result = pthread_cond_wait(&m_condition, &mutex.impl());
354     ASSERT_UNUSED(result, !result);
355 }
356
357 bool ThreadCondition::timedWait(Mutex& mutex, double absoluteTime)
358 {
359     if (absoluteTime < currentTime())
360         return false;
361
362     if (absoluteTime > INT_MAX) {
363         wait(mutex);
364         return true;
365     }
366
367     int timeSeconds = static_cast<int>(absoluteTime);
368     int timeNanoseconds = static_cast<int>((absoluteTime - timeSeconds) * 1E9);
369
370     timespec targetTime;
371     targetTime.tv_sec = timeSeconds;
372     targetTime.tv_nsec = timeNanoseconds;
373
374     return pthread_cond_timedwait(&m_condition, &mutex.impl(), &targetTime) == 0;
375 }
376
377 void ThreadCondition::signal()
378 {
379     int result = pthread_cond_signal(&m_condition);
380     ASSERT_UNUSED(result, !result);
381 }
382
383 void ThreadCondition::broadcast()
384 {
385     int result = pthread_cond_broadcast(&m_condition);
386     ASSERT_UNUSED(result, !result);
387 }
388
389 } // namespace WTF
390
391 #endif // USE(PTHREADS)