[WK2] Small Caps font variant issue for Italic fonts
[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 class PthreadState {
65 public:
66     enum JoinableState {
67         Joinable, // The default thread state. The thread can be joined on.
68
69         Joined, // Somebody waited on this thread to exit and this thread finally exited. This state is here because there can be a 
70                 // period of time between when the thread exits (which causes pthread_join to return and the remainder of waitOnThreadCompletion to run) 
71                 // and when threadDidExit is called. We need threadDidExit to take charge and delete the thread data since there's 
72                 // nobody else to pick up the slack in this case (since waitOnThreadCompletion has already returned).
73
74         Detached // The thread has been detached and can no longer be joined on. At this point, the thread must take care of cleaning up after itself.
75     };
76
77     // Currently all threads created by WTF start out as joinable. 
78     PthreadState(pthread_t handle)
79         : m_joinableState(Joinable)
80         , m_didExit(false)
81         , m_pthreadHandle(handle)
82     {
83     }
84
85     JoinableState joinableState() { return m_joinableState; }
86     pthread_t pthreadHandle() { return m_pthreadHandle; }
87     void didBecomeDetached() { m_joinableState = Detached; }
88     void didExit() { m_didExit = true; }
89     void didJoin() { m_joinableState = Joined; }
90     bool hasExited() { return m_didExit; }
91
92 private:
93     JoinableState m_joinableState;
94     bool m_didExit;
95     pthread_t m_pthreadHandle;
96 };
97
98 typedef HashMap<ThreadIdentifier, OwnPtr<PthreadState> > ThreadMap;
99
100 static Mutex* atomicallyInitializedStaticMutex;
101
102 void unsafeThreadWasDetached(ThreadIdentifier);
103 void threadDidExit(ThreadIdentifier);
104 void threadWasJoined(ThreadIdentifier);
105
106 static Mutex& threadMapMutex()
107 {
108     DEFINE_STATIC_LOCAL(Mutex, mutex, ());
109     return mutex;
110 }
111
112 void initializeThreading()
113 {
114     if (atomicallyInitializedStaticMutex)
115         return;
116
117     WTF::double_conversion::initialize();
118     // StringImpl::empty() does not construct its static string in a threadsafe fashion,
119     // so ensure it has been initialized from here.
120     StringImpl::empty();
121     atomicallyInitializedStaticMutex = new Mutex;
122     threadMapMutex();
123     initializeRandomNumberGenerator();
124     ThreadIdentifierData::initializeOnce();
125     wtfThreadData();
126     s_dtoaP5Mutex = new Mutex;
127     initializeDates();
128 }
129
130 void lockAtomicallyInitializedStaticMutex()
131 {
132     ASSERT(atomicallyInitializedStaticMutex);
133     atomicallyInitializedStaticMutex->lock();
134 }
135
136 void unlockAtomicallyInitializedStaticMutex()
137 {
138     atomicallyInitializedStaticMutex->unlock();
139 }
140
141 static ThreadMap& threadMap()
142 {
143     DEFINE_STATIC_LOCAL(ThreadMap, map, ());
144     return map;
145 }
146
147 static ThreadIdentifier identifierByPthreadHandle(const pthread_t& pthreadHandle)
148 {
149     MutexLocker locker(threadMapMutex());
150
151     ThreadMap::iterator i = threadMap().begin();
152     for (; i != threadMap().end(); ++i) {
153         if (pthread_equal(i->second->pthreadHandle(), pthreadHandle) && !i->second->hasExited())
154             return i->first;
155     }
156
157     return 0;
158 }
159
160 static ThreadIdentifier establishIdentifierForPthreadHandle(const pthread_t& pthreadHandle)
161 {
162     ASSERT(!identifierByPthreadHandle(pthreadHandle));
163     MutexLocker locker(threadMapMutex());
164     static ThreadIdentifier identifierCount = 1;
165     threadMap().add(identifierCount, adoptPtr(new PthreadState(pthreadHandle)));
166     return identifierCount++;
167 }
168
169 static pthread_t pthreadHandleForIdentifierWithLockAlreadyHeld(ThreadIdentifier id)
170 {
171     return threadMap().get(id)->pthreadHandle();
172 }
173
174 static void* wtfThreadEntryPoint(void* param)
175 {
176     // Balanced by .leakPtr() in createThreadInternal.
177     OwnPtr<ThreadFunctionInvocation> invocation = adoptPtr(static_cast<ThreadFunctionInvocation*>(param));
178     invocation->function(invocation->data);
179     return 0;
180 }
181
182 ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, const char*)
183 {
184     OwnPtr<ThreadFunctionInvocation> invocation = adoptPtr(new ThreadFunctionInvocation(entryPoint, data));
185     pthread_t threadHandle;
186     if (pthread_create(&threadHandle, 0, wtfThreadEntryPoint, invocation.get())) {
187         LOG_ERROR("Failed to create pthread at entry point %p with data %p", wtfThreadEntryPoint, invocation.get());
188         return 0;
189     }
190
191     // Balanced by adoptPtr() in wtfThreadEntryPoint.
192     ThreadFunctionInvocation* leakedInvocation = invocation.leakPtr();
193     UNUSED_PARAM(leakedInvocation);
194
195     return establishIdentifierForPthreadHandle(threadHandle);
196 }
197
198 void initializeCurrentThreadInternal(const char* threadName)
199 {
200 #if HAVE(PTHREAD_SETNAME_NP)
201     pthread_setname_np(threadName);
202 #elif OS(QNX)
203     pthread_setname_np(pthread_self(), threadName);
204 #else
205     UNUSED_PARAM(threadName);
206 #endif
207
208 #if OS(MAC_OS_X) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
209     // All threads that potentially use APIs above the BSD layer must be registered with the Objective-C
210     // garbage collector in case API implementations use garbage-collected memory.
211     objc_registerThreadWithCollector();
212 #endif
213
214     ThreadIdentifier id = identifierByPthreadHandle(pthread_self());
215     ASSERT(id);
216     ThreadIdentifierData::initialize(id);
217 }
218
219 int waitForThreadCompletion(ThreadIdentifier threadID)
220 {
221     pthread_t pthreadHandle;
222     ASSERT(threadID);
223
224     {
225         // We don't want to lock across the call to join, since that can block our thread and cause deadlock.
226         MutexLocker locker(threadMapMutex());
227         pthreadHandle = pthreadHandleForIdentifierWithLockAlreadyHeld(threadID);
228         ASSERT(pthreadHandle);
229     }
230
231     int joinResult = pthread_join(pthreadHandle, 0);
232
233     if (joinResult == EDEADLK)
234         LOG_ERROR("ThreadIdentifier %u was found to be deadlocked trying to quit", threadID);
235     else if (joinResult)
236         LOG_ERROR("ThreadIdentifier %u was unable to be joined.\n", threadID);
237
238     MutexLocker locker(threadMapMutex());
239     PthreadState* state = threadMap().get(threadID);
240     ASSERT(state);
241     ASSERT(state->joinableState() == PthreadState::Joinable);
242
243     // The thread has already exited, so clean up after it.
244     if (state->hasExited())
245         threadMap().remove(threadID);
246     // The thread hasn't exited yet, so don't clean anything up. Just signal that we've already joined on it so that it will clean up after itself.
247     else
248         state->didJoin();
249
250     return joinResult;
251 }
252
253 void detachThread(ThreadIdentifier threadID)
254 {
255     ASSERT(threadID);
256
257     MutexLocker locker(threadMapMutex());
258     pthread_t pthreadHandle = pthreadHandleForIdentifierWithLockAlreadyHeld(threadID);
259     ASSERT(pthreadHandle);
260
261     int detachResult = pthread_detach(pthreadHandle);
262     if (detachResult)
263         LOG_ERROR("ThreadIdentifier %u was unable to be detached\n", threadID);
264
265     PthreadState* state = threadMap().get(threadID);
266     ASSERT(state);
267     if (state->hasExited())
268         threadMap().remove(threadID);
269     else
270         threadMap().get(threadID)->didBecomeDetached();
271 }
272
273 void threadDidExit(ThreadIdentifier threadID)
274 {
275     MutexLocker locker(threadMapMutex());
276     PthreadState* state = threadMap().get(threadID);
277     ASSERT(state);
278     
279     state->didExit();
280
281     if (state->joinableState() != PthreadState::Joinable)
282         threadMap().remove(threadID);
283 }
284
285 void yield()
286 {
287     sched_yield();
288 }
289
290 ThreadIdentifier currentThread()
291 {
292     ThreadIdentifier id = ThreadIdentifierData::identifier();
293     if (id)
294         return id;
295
296     // Not a WTF-created thread, ThreadIdentifier is not established yet.
297     id = establishIdentifierForPthreadHandle(pthread_self());
298     ThreadIdentifierData::initialize(id);
299     return id;
300 }
301
302 Mutex::Mutex()
303 {
304     pthread_mutexattr_t attr;
305     pthread_mutexattr_init(&attr);
306     pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
307
308     int result = pthread_mutex_init(&m_mutex, &attr);
309     ASSERT_UNUSED(result, !result);
310
311     pthread_mutexattr_destroy(&attr);
312 }
313
314 Mutex::~Mutex()
315 {
316     int result = pthread_mutex_destroy(&m_mutex);
317     ASSERT_UNUSED(result, !result);
318 }
319
320 void Mutex::lock()
321 {
322     int result = pthread_mutex_lock(&m_mutex);
323     ASSERT_UNUSED(result, !result);
324 }
325
326 bool Mutex::tryLock()
327 {
328     int result = pthread_mutex_trylock(&m_mutex);
329
330     if (result == 0)
331         return true;
332     if (result == EBUSY)
333         return false;
334
335     ASSERT_NOT_REACHED();
336     return false;
337 }
338
339 void Mutex::unlock()
340 {
341     int result = pthread_mutex_unlock(&m_mutex);
342     ASSERT_UNUSED(result, !result);
343 }
344
345 #if HAVE(PTHREAD_RWLOCK)
346 ReadWriteLock::ReadWriteLock()
347 {
348     pthread_rwlock_init(&m_readWriteLock, NULL);
349 }
350
351 ReadWriteLock::~ReadWriteLock()
352 {
353     pthread_rwlock_destroy(&m_readWriteLock);
354 }
355
356 void ReadWriteLock::readLock()
357 {
358     int result = pthread_rwlock_rdlock(&m_readWriteLock);
359     ASSERT_UNUSED(result, !result);
360 }
361
362 bool ReadWriteLock::tryReadLock()
363 {
364     int result = pthread_rwlock_tryrdlock(&m_readWriteLock);
365
366     if (result == 0)
367         return true;
368     if (result == EBUSY || result == EAGAIN)
369         return false;
370
371     ASSERT_NOT_REACHED();
372     return false;
373 }
374
375 void ReadWriteLock::writeLock()
376 {
377     int result = pthread_rwlock_wrlock(&m_readWriteLock);
378     ASSERT_UNUSED(result, !result);
379 }
380
381 bool ReadWriteLock::tryWriteLock()
382 {
383     int result = pthread_rwlock_trywrlock(&m_readWriteLock);
384
385     if (result == 0)
386         return true;
387     if (result == EBUSY || result == EAGAIN)
388         return false;
389
390     ASSERT_NOT_REACHED();
391     return false;
392 }
393
394 void ReadWriteLock::unlock()
395 {
396     int result = pthread_rwlock_unlock(&m_readWriteLock);
397     ASSERT_UNUSED(result, !result);
398 }
399 #endif  // HAVE(PTHREAD_RWLOCK)
400
401 ThreadCondition::ThreadCondition()
402
403     pthread_cond_init(&m_condition, NULL);
404 }
405
406 ThreadCondition::~ThreadCondition()
407 {
408     pthread_cond_destroy(&m_condition);
409 }
410     
411 void ThreadCondition::wait(Mutex& mutex)
412 {
413     int result = pthread_cond_wait(&m_condition, &mutex.impl());
414     ASSERT_UNUSED(result, !result);
415 }
416
417 bool ThreadCondition::timedWait(Mutex& mutex, double absoluteTime)
418 {
419     if (absoluteTime < currentTime())
420         return false;
421
422     if (absoluteTime > INT_MAX) {
423         wait(mutex);
424         return true;
425     }
426
427     int timeSeconds = static_cast<int>(absoluteTime);
428     int timeNanoseconds = static_cast<int>((absoluteTime - timeSeconds) * 1E9);
429
430     timespec targetTime;
431     targetTime.tv_sec = timeSeconds;
432     targetTime.tv_nsec = timeNanoseconds;
433
434     return pthread_cond_timedwait(&m_condition, &mutex.impl(), &targetTime) == 0;
435 }
436
437 void ThreadCondition::signal()
438 {
439     int result = pthread_cond_signal(&m_condition);
440     ASSERT_UNUSED(result, !result);
441 }
442
443 void ThreadCondition::broadcast()
444 {
445     int result = pthread_cond_broadcast(&m_condition);
446     ASSERT_UNUSED(result, !result);
447 }
448
449 } // namespace WTF
450
451 #endif // USE(PTHREADS)