Upstream version 7.36.149.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/ThreadIdentifierDataPthreads.h"
43 #include "wtf/ThreadSpecific.h"
44 #include "wtf/ThreadingPrimitives.h"
45 #include "wtf/WTFThreadData.h"
46 #include "wtf/dtoa.h"
47 #include "wtf/dtoa/cached-powers.h"
48 #include <errno.h>
49
50 #if !COMPILER(MSVC)
51 #include <limits.h>
52 #include <sched.h>
53 #include <sys/time.h>
54 #endif
55
56 #if OS(MACOSX)
57 #include <objc/objc-auto.h>
58 #endif
59
60 namespace WTF {
61
62 class PthreadState {
63     WTF_MAKE_FAST_ALLOCATED;
64 public:
65     enum JoinableState {
66         Joinable, // The default thread state. The thread can be joined on.
67
68         Joined, // Somebody waited on this thread to exit and this thread finally exited. This state is here because there can be a
69                 // period of time between when the thread exits (which causes pthread_join to return and the remainder of waitOnThreadCompletion to run)
70                 // and when threadDidExit is called. We need threadDidExit to take charge and delete the thread data since there's
71                 // nobody else to pick up the slack in this case (since waitOnThreadCompletion has already returned).
72
73         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.
74     };
75
76     // Currently all threads created by WTF start out as joinable.
77     PthreadState(pthread_t handle)
78         : m_joinableState(Joinable)
79         , m_didExit(false)
80         , m_pthreadHandle(handle)
81     {
82     }
83
84     JoinableState joinableState() { return m_joinableState; }
85     pthread_t pthreadHandle() { return m_pthreadHandle; }
86     void didBecomeDetached() { m_joinableState = Detached; }
87     void didExit() { m_didExit = true; }
88     void didJoin() { m_joinableState = Joined; }
89     bool hasExited() { return m_didExit; }
90
91 private:
92     JoinableState m_joinableState;
93     bool m_didExit;
94     pthread_t m_pthreadHandle;
95 };
96
97 typedef HashMap<ThreadIdentifier, OwnPtr<PthreadState> > ThreadMap;
98
99 static Mutex* atomicallyInitializedStaticMutex;
100
101 void unsafeThreadWasDetached(ThreadIdentifier);
102 void threadDidExit(ThreadIdentifier);
103 void threadWasJoined(ThreadIdentifier);
104
105 static Mutex& threadMapMutex()
106 {
107     DEFINE_STATIC_LOCAL(Mutex, mutex, ());
108     return mutex;
109 }
110
111 void initializeThreading()
112 {
113     // This should only be called once.
114     ASSERT(!atomicallyInitializedStaticMutex);
115
116     // StringImpl::empty() does not construct its static string in a threadsafe fashion,
117     // so ensure it has been initialized from here.
118     StringImpl::empty();
119     atomicallyInitializedStaticMutex = new Mutex;
120     threadMapMutex();
121     ThreadIdentifierData::initializeOnce();
122     wtfThreadData();
123     s_dtoaP5Mutex = new Mutex;
124     initializeDates();
125 }
126
127 void lockAtomicallyInitializedStaticMutex()
128 {
129     ASSERT(atomicallyInitializedStaticMutex);
130     atomicallyInitializedStaticMutex->lock();
131 }
132
133 void unlockAtomicallyInitializedStaticMutex()
134 {
135     atomicallyInitializedStaticMutex->unlock();
136 }
137
138 static ThreadMap& threadMap()
139 {
140     DEFINE_STATIC_LOCAL(ThreadMap, map, ());
141     return map;
142 }
143
144 static ThreadIdentifier identifierByPthreadHandle(const pthread_t& pthreadHandle)
145 {
146     MutexLocker locker(threadMapMutex());
147
148     ThreadMap::iterator i = threadMap().begin();
149     for (; i != threadMap().end(); ++i) {
150         if (pthread_equal(i->value->pthreadHandle(), pthreadHandle) && !i->value->hasExited())
151             return i->key;
152     }
153
154     return 0;
155 }
156
157 static ThreadIdentifier establishIdentifierForPthreadHandle(const pthread_t& pthreadHandle)
158 {
159     ASSERT(!identifierByPthreadHandle(pthreadHandle));
160     MutexLocker locker(threadMapMutex());
161     static ThreadIdentifier identifierCount = 1;
162     threadMap().add(identifierCount, adoptPtr(new PthreadState(pthreadHandle)));
163     return identifierCount++;
164 }
165
166 static pthread_t pthreadHandleForIdentifierWithLockAlreadyHeld(ThreadIdentifier id)
167 {
168     return threadMap().get(id)->pthreadHandle();
169 }
170
171 static void* wtfThreadEntryPoint(void* param)
172 {
173     // Balanced by .leakPtr() in createThreadInternal.
174     OwnPtr<ThreadFunctionInvocation> invocation = adoptPtr(static_cast<ThreadFunctionInvocation*>(param));
175     invocation->function(invocation->data);
176     return 0;
177 }
178
179 ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, const char*)
180 {
181     OwnPtr<ThreadFunctionInvocation> invocation = adoptPtr(new ThreadFunctionInvocation(entryPoint, data));
182     pthread_t threadHandle;
183     if (pthread_create(&threadHandle, 0, wtfThreadEntryPoint, invocation.get())) {
184         WTF_LOG_ERROR("Failed to create pthread at entry point %p with data %p", wtfThreadEntryPoint, invocation.get());
185         return 0;
186     }
187
188     // Balanced by adoptPtr() in wtfThreadEntryPoint.
189     ThreadFunctionInvocation* leakedInvocation ALLOW_UNUSED = invocation.leakPtr();
190
191     return establishIdentifierForPthreadHandle(threadHandle);
192 }
193
194 void initializeCurrentThreadInternal(const char* threadName)
195 {
196 #if HAVE(PTHREAD_SETNAME_NP)
197     pthread_setname_np(threadName);
198 #endif
199
200 #if OS(MACOSX)
201     // All threads that potentially use APIs above the BSD layer must be registered with the Objective-C
202     // garbage collector in case API implementations use garbage-collected memory.
203     objc_registerThreadWithCollector();
204 #endif
205
206     ThreadIdentifier id = identifierByPthreadHandle(pthread_self());
207     ASSERT(id);
208     ThreadIdentifierData::initialize(id);
209 }
210
211 int waitForThreadCompletion(ThreadIdentifier threadID)
212 {
213     pthread_t pthreadHandle;
214     ASSERT(threadID);
215
216     {
217         // We don't want to lock across the call to join, since that can block our thread and cause deadlock.
218         MutexLocker locker(threadMapMutex());
219         pthreadHandle = pthreadHandleForIdentifierWithLockAlreadyHeld(threadID);
220         ASSERT(pthreadHandle);
221     }
222
223     int joinResult = pthread_join(pthreadHandle, 0);
224
225     if (joinResult == EDEADLK)
226         WTF_LOG_ERROR("ThreadIdentifier %u was found to be deadlocked trying to quit", threadID);
227     else if (joinResult)
228         WTF_LOG_ERROR("ThreadIdentifier %u was unable to be joined.\n", threadID);
229
230     MutexLocker locker(threadMapMutex());
231     PthreadState* state = threadMap().get(threadID);
232     ASSERT(state);
233     ASSERT(state->joinableState() == PthreadState::Joinable);
234
235     // The thread has already exited, so clean up after it.
236     if (state->hasExited())
237         threadMap().remove(threadID);
238     // 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.
239     else
240         state->didJoin();
241
242     return joinResult;
243 }
244
245 void detachThread(ThreadIdentifier threadID)
246 {
247     ASSERT(threadID);
248
249     MutexLocker locker(threadMapMutex());
250     pthread_t pthreadHandle = pthreadHandleForIdentifierWithLockAlreadyHeld(threadID);
251     ASSERT(pthreadHandle);
252
253     int detachResult = pthread_detach(pthreadHandle);
254     if (detachResult)
255         WTF_LOG_ERROR("ThreadIdentifier %u was unable to be detached\n", threadID);
256
257     PthreadState* state = threadMap().get(threadID);
258     ASSERT(state);
259     if (state->hasExited())
260         threadMap().remove(threadID);
261     else
262         threadMap().get(threadID)->didBecomeDetached();
263 }
264
265 void threadDidExit(ThreadIdentifier threadID)
266 {
267     MutexLocker locker(threadMapMutex());
268     PthreadState* state = threadMap().get(threadID);
269     ASSERT(state);
270
271     state->didExit();
272
273     if (state->joinableState() != PthreadState::Joinable)
274         threadMap().remove(threadID);
275 }
276
277 void yield()
278 {
279     sched_yield();
280 }
281
282 ThreadIdentifier currentThread()
283 {
284     ThreadIdentifier id = ThreadIdentifierData::identifier();
285     if (id)
286         return id;
287
288     // Not a WTF-created thread, ThreadIdentifier is not established yet.
289     id = establishIdentifierForPthreadHandle(pthread_self());
290     ThreadIdentifierData::initialize(id);
291     return id;
292 }
293
294 Mutex::Mutex()
295 {
296     pthread_mutexattr_t attr;
297     pthread_mutexattr_init(&attr);
298     pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
299
300     int result = pthread_mutex_init(&m_mutex, &attr);
301     ASSERT_UNUSED(result, !result);
302
303     pthread_mutexattr_destroy(&attr);
304 }
305
306 Mutex::~Mutex()
307 {
308     int result = pthread_mutex_destroy(&m_mutex);
309     ASSERT_UNUSED(result, !result);
310 }
311
312 void Mutex::lock()
313 {
314     int result = pthread_mutex_lock(&m_mutex);
315     ASSERT_UNUSED(result, !result);
316 }
317
318 bool Mutex::tryLock()
319 {
320     int result = pthread_mutex_trylock(&m_mutex);
321
322     if (result == 0)
323         return true;
324     if (result == EBUSY)
325         return false;
326
327     ASSERT_NOT_REACHED();
328     return false;
329 }
330
331 void Mutex::unlock()
332 {
333     int result = pthread_mutex_unlock(&m_mutex);
334     ASSERT_UNUSED(result, !result);
335 }
336
337 ThreadCondition::ThreadCondition()
338 {
339     pthread_cond_init(&m_condition, NULL);
340 }
341
342 ThreadCondition::~ThreadCondition()
343 {
344     pthread_cond_destroy(&m_condition);
345 }
346
347 void ThreadCondition::wait(Mutex& mutex)
348 {
349     int result = pthread_cond_wait(&m_condition, &mutex.impl());
350     ASSERT_UNUSED(result, !result);
351 }
352
353 bool ThreadCondition::timedWait(Mutex& mutex, double absoluteTime)
354 {
355     if (absoluteTime < currentTime())
356         return false;
357
358     if (absoluteTime > INT_MAX) {
359         wait(mutex);
360         return true;
361     }
362
363     int timeSeconds = static_cast<int>(absoluteTime);
364     int timeNanoseconds = static_cast<int>((absoluteTime - timeSeconds) * 1E9);
365
366     timespec targetTime;
367     targetTime.tv_sec = timeSeconds;
368     targetTime.tv_nsec = timeNanoseconds;
369
370     return pthread_cond_timedwait(&m_condition, &mutex.impl(), &targetTime) == 0;
371 }
372
373 void ThreadCondition::signal()
374 {
375     int result = pthread_cond_signal(&m_condition);
376     ASSERT_UNUSED(result, !result);
377 }
378
379 void ThreadCondition::broadcast()
380 {
381     int result = pthread_cond_broadcast(&m_condition);
382     ASSERT_UNUSED(result, !result);
383 }
384
385 } // namespace WTF
386
387 #endif // USE(PTHREADS)