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